以下代码无法按预期工作:
.intel_syntax noprefix
.arch i386
.data
hello_world:
.ascii "Hello world!\n"
hello_world_end:
.equ hello_world_len, hello_world_end - hello_world
.text
.global _start
_start:
mov ebx, 1
mov ecx, hello_world
mov edx, hello_world_len
mov eax, 4
int 0x80
mov ebx, 0
mov eax, 1
int 0x80
跑过时:
as test.s -o test.o
ld test.o -o test
./test
它什么也没输出。当我改变这一行时:
mov ecx, offset hello_world ; added offset
工作正常。我尝试使用--32 -march=i386
编译原始代码并链接到-m elf_i386
,但它仍然没有输出任何内容。
$ uname -a
Linux ubuntu 3.2.0-38-generic #60-Ubuntu SMP Wed Feb 13 13:22:43 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
我猜这是因为内存模型不像i386那样平坦。我能以某种方式模仿这个吗?
答案 0 :(得分:2)
这不是关于内存模型。
气体语法mov ecx, hello_world
表示读取内存地址 hello_world
,可以通过检查使用ndisasm完成的反汇编来确认:
00000000 BB01000000 mov ebx,0x1
00000005 8B0C25D4104000 mov ecx,[0x4010d4]
0000000C BA0D000000 mov edx,0xd
00000011 B804000000 mov eax,0x4
00000016 CD80 int 0x80
您想要的是存储hello_world
的内存地址。在气体中,实现这一目标的方法是mov ecx, offset hello_world
,可以从反汇编中确认:
00000000 BB01000000 mov ebx,0x1
00000005 B9D4104000 mov ecx,0x4010d4
0000000A BA0D000000 mov edx,0xd
0000000F B804000000 mov eax,0x4
00000014 CD80 int 0x80
顺便说一句,另一种将内存地址加载到寄存器的方法是lea
ecx, hello_world
。
其他一些汇编程序(例如NASM和YASM)具有不同的语法,这种差异可能会引起混淆,如小表所示:
gas NASM/YASM ndisasm disassembly
mov ecx,hello_world mov ecx,[hello_world] mov ecx,[0x4010d4]
mov ecx,[hello_world] mov ecx,[hello_world] mov ecx,[0x4010d4]
mov ecx,offset hello_world mov ecx,hello_world mov ecx,0x4010d4