【发布时间】:2016-05-08 05:33:12
【问题描述】:
我正在尝试学习汇编语言作为一种爱好,我经常使用gcc -S 来生成汇编输出。这非常简单,但我无法编译程序集输出。我只是好奇这是否可以做到。我尝试使用-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;
}
使用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
这很可能是由于汇编语法损坏造成的。我希望我能够解决这个问题,而无需手动更正 gcc -S 的输出
编辑:
我收到了hint,表明我的问题已在另一个问题中得到解决;不幸的是,在测试了那里描述的方法后,我无法生成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
明显的解决方案:
我在清理objconv 的输出时出错。我应该跑了:
sed -i "s/align=1//g ; s/[a-z]*execute//g ; s/: *function//g; /default *rel/d" csimp.asm
所有步骤都可以压缩在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
运行此代码我收到ld 警告:
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080
以这种方式生成的可执行文件崩溃并显示分段错误消息。非常感谢您的帮助。
【问题讨论】:
-
输出是为 gnu 汇编器 (
as) 准备的,你有什么特别的理由不使用它吗?它会“正常工作”。不幸的是,nasm有不同的语法。 -
我不知道这个。我会试试的,谢谢你的回答。我很惊讶汇编语法不是通用的。
-
@NateEldredge 不幸的是,那里写的内容对我不起作用。我猜
C汇编转换不是那么简单。 -
你需要
nasm做什么? -
您的编辑没有显示您是如何编译和链接该 OBJCONV 代码的,但它应该可以与带有类似
nasm -felf64 csimpc.asm的 nasm 进行编译。如果您使用了nasm -felf csimpc.asm,-f elf会尝试生成 32 位输出。如果您尝试汇编 64 位代码,则需要-f elf64。如果在 64 位系统上,LD 通常会默认输出 64 位可执行文件。所以你应该从 LD 命令中删除-m elf_i386或使用ld -m elf_x86_64。带有-m elf_i386的 LD 正在尝试输出到 32 位可执行文件