NASM和GDB:丢失第一条指令

3

我正在学习汇编语言,并发现以下内容令人惊讶。我从互联网上某个地方复制了一些“Hello World”代码。

section .text
    global  _start

_start:
    mov edx,len
    mov ecx,msg
    mov ebx,1
    mov eax,4
    int 0x80        ; interrupt for calling kernel

    mov eax,1
    int 0x80

section .data

msg db  'Hello, world!',0xa
len equ $ - msg

我用nasm -f elf -g hellow.asm编译和链接,然后使用ld hellow.o -o hellow。如果我现在将它加载到gdb中,我可以很好地列出代码并运行它。如果我在第一个mov指令上设置断点,程序不会停在那里。在生成的文件上运行ndisasm(ndisasm -b32 hellow),我得到了以下结果(我认为这部分是相关的):

0000007D  0000              add [eax],al
0000007F  00BA0E000000      add [edx+0xe],bh
00000085  B9A0900408        mov ecx,0x80490a0
0000008A  BB01000000        mov ebx,0x1
0000008F  B804000000        mov eax,0x4
00000094  CD80              int 0x80
00000096  B801000000        mov eax,0x1
0000009B  CD80              int 0x80

因此,指令未出现。

如果您能提供发生情况的提示或告诉我去哪里了解情况,我将不胜感激。

1个回答

2
你的指令在反汇编时出现问题,原因是起始点的对齐问题以及指令排列的方式。由于x86有可变长度的指令,反汇编器需要知道一个入口点。正确的清单更像是这样的:
00000080  BA0E000000      mov edx,0xe ; I think
00000085  B9A0900408      mov ecx,0x80490a0
...

实际问题似乎出在gdb上,可能与您设置断点的方式有关(此外,我无法回忆起gdb是否会在第一条指令之前中断,我需要检查一下)。


事实上,我通过在ndisasm中添加“同步点”来找到这些指令:ndisasm -b32 -s0X80 hellow。然后按照您的建议对指令进行解码。我推测我的二进制格式包含了起始点为80的信息,但是readelf表明_start位于08048080,除了以80结尾外,我认为这与我无关。 - kasterma
如果我没记错的话,在Linux/386上可执行文件的开头实际上是内存地址0x08048000。 - cthom06
1
如果我使用gcc进行链接,那么生成的可执行文件会更大,但是我可以在第一条指令上设置一个有效的断点。 - kasterma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接