我正在尝试作为一种爱好学习汇编语言,并且经常使用
这很可能是由于汇编语法错误导致的。我希望能够在不手动更正
所有步骤都可以在一个
运行此代码,我收到了`ld`警告:
这种方式生成的可执行文件会崩溃并显示分段错误信息。我将不胜感激您的帮助。
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
输出的情况下修复此问题。
编辑:
有人给了我一个提示,说我的问题在另一个问题中得到了解决;不幸的是,在测试那里描述的方法后,我无法生成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
这种方式生成的可执行文件会崩溃并显示分段错误信息。我将不胜感激您的帮助。
as
)而设计的,你为什么不使用它呢?它会“即插即用”。不幸的是,nasm
具有不同的语法。 - Jesternasm
做什么? - edmznasm -f elf
和ld -m elf_i386
(针对32位) 。所以我猜测您在objconv生成的代码方面可能遇到了混合32位和64位代码的问题。首先,您是要创建64位代码还是32位代码?你使用的是32位还是64位操作系统? - Michael Petch64
位二进制文件并在运行3.16.7-21-desktop
内核的 Suse Linux 上运行它。然而,您看到的错误是由运行nasm
生成的,因此链接器不是问题所在。我会纠正这个错误。感谢您的反馈。 - Alexander Cskanasm -felf64 csimpc.asm
。如果你使用了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位可执行文件。 - Michael Petch