我试图学习汇编语言作为一种爱好,我经常用它gcc -S来产生汇编输出.这非常简单,但我无法编译汇编输出.我只是好奇这是否可以完成.我尝试使用标准汇编输出和intel语法-masm=intel.两者都无法编译nasm和链接ld.
因此,我想问一下是否可以生成汇编代码,然后可以编译.
更准确地说,我使用了以下C代码.
>> cat csimp.c
int main (void){
int i,j;
for(i=1;i<21;i++)
j= i + 100;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
生成程序集gcc -S -O0 -masm=intel csimp.c并尝试编译nasm -f elf64 csimp.s和链接ld -m elf_x86_64 -s -o test csimp.o.我从nasm得到的输出读取:
csimp.s:1: error: attempt to define a local label before any non-local labels
csimp.s:1: error: parser: instruction expected
csimp.s:2: error: attempt to define a local label before any non-local labels
csimp.s:2: error: parser: instruction expected
Run Code Online (Sandbox Code Playgroud)
这很可能是由于程序集语法损坏造成的.我希望我能够解决这个问题,而无需手动纠正输出gcc -S
编辑:
我被暗示我的问题在另一个问题上得到了解决; 不幸的是,在测试了那里描述的方法之后,我无法生成nasm汇编格式.你可以看到objconv下面的输出.因此我仍然需要你的帮助.
>>cat csimp.asm
; Disassembly of file: csimp.o
; Sat Jan 30 20:17:39 2016
; Mode: 64 bits
; Syntax: YASM/NASM
; Instruction set: 8086, x64
global main: ; **the ':' should be removed !!!**
SECTION .text ; section number 1, code
main: ; Function begin
push rbp ; 0000 _ 55
mov rbp, rsp ; 0001 _ 48: 89. E5
mov dword [rbp-4H], 1 ; 0004 _ C7. 45, FC, 00000001
jmp ?_002 ; 000B _ EB, 0D
?_001: mov eax, dword [rbp-4H] ; 000D _ 8B. 45, FC
add eax, 100 ; 0010 _ 83. C0, 64
mov dword [rbp-8H], eax ; 0013 _ 89. 45, F8
add dword [rbp-4H], 1 ; 0016 _ 83. 45, FC, 01
?_002: cmp dword [rbp-4H], 20 ; 001A _ 83. 7D, FC, 14
jle ?_001 ; 001E _ 7E, ED
pop rbp ; 0020 _ 5D
ret ; 0021 _ C3
; main End of function
SECTION .data ; section number 2, data
SECTION .bss ; section number 3, bss
Run Code Online (Sandbox Code Playgroud)
明显的解决方案:
清理输出时我犯了一个错误objconv.我应该跑:
sed -i "s/align=1//g ; s/[a-z]*execute//g ; s/: *function//g; /default *rel/d" csimp.asm
Run Code Online (Sandbox Code Playgroud)
所有步骤都可以在bash脚本中压缩
#! /bin/bash
a=$( echo $1 | sed "s/\.c//" ) # strip the file extension .c
# compile binary with minimal information
gcc -fno-asynchronous-unwind-tables -s -c ${a}.c
# convert the executable to nasm format
./objconv/objconv -fnasm ${a}.o
# remove unnecesairy objconv information
sed -i "s/align=1//g ; s/[a-z]*execute//g ; s/: *function//g; /default *rel/d" ${a}.asm
# run nasm for 64-bit binary
nasm -f elf64 ${a}.asm
# link --> see comment of MichaelPetch below
ld -m elf_x86_64 -s ${a}.o
Run Code Online (Sandbox Code Playgroud)
运行此代码我收到ld警告:
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080
Run Code Online (Sandbox Code Playgroud)
以这种方式生成的可执行文件与分段错误消息一起崩溃.我很感激你的帮助.
我认为您遇到的入口点错误遇到的困难是在寻找名为 的入口点时尝试ld在包含名为 的入口点的目标文件上使用。mainld_start
有几个考虑因素。首先,如果您要与 C 库链接以使用诸如 之类的函数printf,则链接将期望main作为入口点,但如果您不与 C 库链接,ld则将期望_start. 您的脚本非常接近,但您需要某种方法来区分您需要哪个入口点来完全自动化任何源文件的过程。
例如,以下是使用您的方法对源文件(包括printf. 它被转换为nasm使用objconv如下:
生成目标文件:
gcc -fno-asynchronous-unwind-tables -s -c struct_offsetof.c -o s3.obj
Run Code Online (Sandbox Code Playgroud)
用objconv转换为nasm格式的汇编文件
objconv -fnasm s3.obj
Run Code Online (Sandbox Code Playgroud)
(注:我的版本objconv添加了 DOS 行结尾——可能错过了一个选项,我刚刚运行了它dos2unix)
使用稍加修改的调用版本sed,调整内容:
sed -i -e 's/align=1//g' -e 's/[a-z]*execute//g' -e \
's/: *function//g' -e '/default *rel/d' s3.asm
Run Code Online (Sandbox Code Playgroud)
(注意:如果没有标准库函数,并且使用ld,则通过在调用中添加以下表达式来更改main为)_startsed
-e 's/^main/_start/' -e 's/[ ]main[ ]*.*$/ _start/'
Run Code Online (Sandbox Code Playgroud)
(可能有更优雅的表达方式,这只是举例)
编译nasm(替换原始目标文件):
nasm -felf64 -o s3.obj s3.asm
Run Code Online (Sandbox Code Playgroud)
用于gcc链接:
gcc -o s3 s3.obj
Run Code Online (Sandbox Code Playgroud)
测试
$ ./s3
sizeof test : 40
myint : 0 0
mychar : 4 4
myptr : 8 8
myarr : 16 16
myuint : 32 32
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5671 次 |
| 最近记录: |