NASM и GDB: потеря первой инструкции

Я изучаю ассемблер и обнаружил следующее удивительное. По сути, я скопировал какой-то код 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

Так и не появляется инструкция.

Я был бы очень признателен за подсказку о том, что происходит, или где можно узнать о том, что происходит.


person kasterma    schedule 22.11.2010    source источник


Ответы (1)


Причина, по которой ваша инструкция не отображается правильно при дизассемблировании, - это просто проблема выравнивания того, где она начинает дизассемблироваться и как инструкции падают. Поскольку x86 имеет инструкции переменной длины, дизассемблеру необходимо знать точку входа. Правильный список больше похож на:

00000080  BA0E000000      mov edx,0xe ; I think
00000085  B9A0900408      mov ecx,0x80490a0
...

Настоящая проблема связана с gdb, вероятно, с тем, как вы устанавливаете точку останова (плюс, я не могу вспомнить, задыхается ли gdb при прерывании перед первой инструкцией, мне нужно проверить).

person cthom06    schedule 22.11.2010
comment
Действительно, я нашел эти инструкции, добавив точку синхронизации в ndisasm: ndisasm -b32 -s0X80 hellow. Дальше инструкция расшифровывается как вы предлагаете. Я предполагаю, что мой двоичный формат содержит информацию о том, что начальная точка находится в 80, однако readelf предполагает, что _start находится в 08048080, что, кроме того, что заканчивается на 80, кажется мне не связанным. - person kasterma; 22.11.2010
comment
@kasterma IIRC начало исполняемого файла на самом деле является адресом памяти 0x08048000 в linux/386. - person cthom06; 22.11.2010
comment
Если я использую gcc для компоновки, я получаю гораздо больший исполняемый файл, но такой, в котором я могу поставить функционирующую точку останова на первой инструкции. - person kasterma; 23.11.2010