C语言程序转汇编代码
l_____py 人气:1最近在学着写bootloader,由于汇编太繁杂,希望可以使用C语言完成一部分,然后转成NASM汇编代码,经过摸索,最终找到了一个解决方案,记录于此,留作参考。
核心步骤
- 使用gcc编译得到.o文件
这一步需要加上一些参数对编译行为进行控制。具体自行参考gcc文档。
我最终使用的命令参数为
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`指令,需要自己根据需要进行删减。
到这里已经基本可以解决问题了,下面是我的需求和解决方案如下。
我的需求及实现
最终我需要的是将使用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结尾的函数文件(约定其中只包含一个函数,函数名同文件名)转换成汇编语言函数。
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脚本的作用删掉一些我所不需要的代码,只保留函数部分,并删除其中的对齐指令和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'{filename[:-4]}:'):
start = lineNum
continue
if line.startswith(f'; {filename[:-4]} End of function'):
end = lineNum
break
funcLines = lines[start:end+1]
cleanFuncLines = []
for line in funcLines:
if line.startswith(' endbr32') or line.startswith('ALIGN'):
continue
cleanFuncLines.append(line)
# print("".join(cleanFuncLines))
fout = open(f'{filename[:-4]}.func', 'w')
fout.writelines(cleanFuncLines)
print(filename)
def main():
# print(sys.argv[1])
# files = os.listdir()
# asmfiles = [file for file in files if file.endswith('.asm')]
# for filename in asmfiles:
extractFunc(sys.argv[1])
# print(filename)
if __name__ == '__main__':
main()
加载全部内容