C语言程序转汇编代码
最近在学着写bootloader,由于汇编太繁杂,希望可以使用C语言完成一部分,然后转成NASM汇编代码,经过摸索,最终找到了一个解决方案,记录于此,留作参考。
核心步骤
使用gcc编译得到.o文件
这一步需要加上一些参数对编译行为进行控制。具体自行参考gcc文档。
我最终使用的命令参数为
shell gcc -fno-pic -fno-asynchronous-unwind-tables -m32 -O2 -s -c -o $@ $<
具体含义我也没有深入了解,-m32是生成32位代码,-O2是一种优化级别,-fno-pic似乎是必要,要不然每个文件最终都会生成一个额外的函数。使用objconv程序将.o文件转换成汇编代码
objconv -fnasm $<
objconv可以将.o文件转成多种形式的汇编,具体自行查阅,上面的参数是要转成NASM代码。
问题
还有一个问题是,这样直接转换成的汇编代码包含多个段,以及各种对齐指令,以及enbdrXX指令,需要自己根据需要进行删减。
我所做的是只保留.text段,并删减对齐指令、enbdrXX指令。
我的需求及实现
最终我需要的是将使用C语言完成的函数转换成汇编形式的函数,并去掉编译器相关、对齐相关的一些代码。我的Makefile如下。
all : $(subst .c,.func,$(wildcard *.c))
%.func : %.asm
./extractFunc.py $<
%.asm : %.o
./objconv -fnasm $<
%.o : %.c
gcc -fno-pic -fno-asynchronous-unwind-tables -m32 -O2 -s -c -o $@ $<
clean :
rm -rf *.asm *.o *.func
其功能是将当前目录中的所有C语言文件转换成NASM汇编语言文件。
C函数文件示例:
//filename : stripe.c
#define DISPLAY_MEMORY_BASE 0xa0000
#define WIDTH 320
#define HEIGHT 200
void stripe()
{
for (int i = DISPLAY_MEMORY_BASE; i <= DISPLAY_MEMORY_BASE+WIDTH*HEIGHT/2; i++)
{
*((int *)i) = (0b11111100 & i);
}
}
使用make命令得到的结果如下:
; filename : stripe.func
stripe: ; Function begin
mov eax, 655360 ; 0004 _ B8, 000A0000
; Filling space: 7H
; Filler type: lea with same source and destination
; db 8DH, 0B4H, 26H, 00H, 00H, 00H, 00H
?_001: mov edx, eax ; 0010 _ 89. C2
add eax, 1 ; 0012 _ 83. C0, 01
and edx, 0FCH ; 0015 _ 81. E2, 000000FC
mov dword [eax-1H], edx ; 001B _ 89. 50, FF
cmp eax, 687361 ; 001E _ 3D, 000A7D01
jnz ?_001 ; 0023 _ 75, EB
ret ; 0025 _ C3
; stripe End of function
gcc和objconv已经在前面提到过了,那个python脚本的作用删掉一些我所不需要的代码,只保留.text部分,并删除其中的对齐指令和enbdrXX指令。内容如下:
#!/usr/bin/python3
#filename : extractFunc.py
import os
import sys
def extractFunc(filename):
fin = open(filename)
lines = fin.readlines()
start = 0
end = 0
lineNum = -1
for line in lines:
lineNum += 1
if line.startswith(f'SECTION .text'):
start = lineNum + 1
continue
if line.startswith(f'SECTION .data'):
end = lineNum
break
funcLines = lines[start:end]
cleanFuncLines = []
for line in funcLines:
if line.startswith(' endbr32') or line.startswith('ALIGN'):
continue
cleanFuncLines.append(line)
fout = open(f'{filename[:-4]}.func', 'w')
fout.writelines(cleanFuncLines)
print(filename)
if __name__ == '__main__':
extractFunc(sys.argv[1])
参考链接
- https://stackoverflow.com/questions/20737947/how-to-generate-a-nasm-compilable-assembly-code-from-c-source-code-on-linux
- https://stackoverflow.com/questions/1647359/is-there-a-way-to-get-gcc-to-output-raw-binary
C语言程序转汇编代码的更多相关文章
- 分析一个C语言程序生成的汇编代码-《Linux内核分析》Week1作业
署名信息 郭春阳 原创作品转载请注明出处 :<Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 C源码 这 ...
- 解析c语言背后的汇编代码
源码 很简单的c语言代码,作用是交换两个数: #include <stdio.h> void swap(int * a, int * b) { *a = *a + *b - (*b = * ...
- 一个简单C程序的汇编代码分析
几个重要的寄存器 eip - 用于存放当前所执行的指令地址 esp - 栈(顶)指针寄存器 ebp - 基址(栈底)指针寄存器 简单的C程序 int g(int x) { ; } int f(int ...
- 从C简单程序的汇编代码入手,以理解计算机工作原理。
贺邦 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000#/info 知识准备 ...
- 如何在Visual Studio里面查看程序的汇编代码?
开发工具:Visual Studio 2015 1,在源代码中设置至少一个断点,目的让我们进入调试模式. 2,启动调试,当程序进入调试模式,停留在我们设定的断点处时候,使用快捷键"ALT+8 ...
- 如何在Delphi里面查看程序的汇编代码?
开发工具:Delphi 10 Update2 1,在源代码中设置至少一个断点,目的让我们进入调试模式. 2,启动调试,当程序进入调试模式,停留在我们设定的断点处时候,使用快捷键"CTRL+A ...
- 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
秦鼎涛 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验一 通过汇编一个简单的C程序,分析汇编代码 ...
- Ubuntu16.04 中 Vscode 如何断点调试C语言程序
个人博客链接:Ubuntu16.04 中 Vscode 如何断点调试C语言程序 问题:环境是 Ubuntu16.04,如何使用 Vscode 断点调试C语言程序. 写代码没有调试环境是不能忍受的,所以 ...
- 《Linux内核分析》week1作业-分析一个简单c语言的汇编代码
1.C语言源码 #include <stdio.h> int g(int x){ ; } int f(int x){ return g(x); } int main(){ )+; } 2. ...
随机推荐
- 深入理解Java虚拟机-类加载连接和初始化解析
不管学习什么,我一直追求的是知其然,还要知其所以然,对真理的追求可以体现在方方面面.人生短短数十载,匆匆一世似烟云,我认为,既然来了,就应该留下一些有意义的东西.本系列文章是结合张龙老师的<深入 ...
- 部署Maven项目到tomcat报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderLi
Maven项目下update maven后Eclipse报错:java.lang.ClassNotFoundException: ContextLoaderL 严重: Error config ...
- 深入Node.js的进程与子进程:从文档到实践
欢迎关注Github仓库,这是一个自2018年起持续更新的前端&算法开源博客.目前已有node学习.js面试笔记.css3动画设计.webpack4系列教程.设计模式.剑指offer·js版等 ...
- 必须掌握的50条Linux基础操作命令
说明: 根据笔者平时使用情况,并结合参考一些其他资料,精心整理出以下必须掌握的50条Linux基础命令. 命令: 1. ssh 登录到远程主机 $ ssh -l jsmith remotehost.e ...
- Docker基础学习相关网址
中文学习地址:https://yeasy.gitbooks.io/docker_practice/content/ 官网介绍地址:https://www.docker.com 官网学习地址:https ...
- 大数据之Kafka史上最详细原理总结
Kafka Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实 ...
- 使用Python通过SMTP发送邮件
有些业务可能由于各种各样的原因并不适用于Zabbix监控,这时如果要做到系统出问题能立即发送邮件,就需要自己来写监控脚本了,出问题要实时通过邮件报警,以下案例使用Python脚本实现通过SMTP协议发 ...
- Jpofiler
参考链接: https://blog.csdn.net/u010638673/article/details/81703942
- CSS Module解决全局或本地使用@keyframes无效问题
最近使用CSSModule开发react项目,遇到一个问题,使用@keyframes无效,问题如下 /** less + css module **/ :global { .effect-bottom ...
- data structure test
1.设计算法,对带头结点的单链表实现就地逆置.并给出单链表的存储结构(数据类型)的定义. #include <iostream> #include <cstdlib> #inc ...