预期下面的代码无法正常工作:
.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。 我能以某种方式效仿呢?
这不是内存模型。
在气体语法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