2

次のコードは期待どおりに動作しません。

.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 のようにフラットではないために発生すると推測されます。何とかこれをエミュレートできますか?

4

1 に答える 1

2

それはメモリモデルについてではありません。

ガス構文では、 ndisasmで行われた逆アセンブルをチェックすることで確認できるように、メモリアドレスからの読み取りをmov ecx, hello_world意味します。 hello_world

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_worldmov 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

ちなみに、メモリアドレスをレジスタにロードする別の方法はです。leaecx, 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
于 2013-02-20T16:26:38.057 に答える