Хорошо, так как вы никогда не использовали отладчик, я покажу вам, как. Сначала скомпилируйте с nasm -f elf -g hello.asm
. Переключатель -g
помогает отладчику, поэтому вы можете устанавливать точки останова и т. Д. Теперь запустите его, набрав gdb ./hello -q
и набрав break 34
. Это говорит gdb
остановиться на строке 34. Запустите программу (введите run emi
(emi - мое имя: P)). Вы должны увидеть что-то вроде этого:
blackbear@blackbear-laptop:~$ gdb ./hello -q
Reading symbols from /home/blackbear/hello...done.
(gdb) break 34
Breakpoint 1 at 0x80480a9: file hello.asm, line 34.
(gdb) run emi
Starting program: /home/blackbear/hello emi
Hello,
Breakpoint 1, _start () at hello.asm:34
34 pop ecx ; Get name
(gdb)
Хорошо, давайте посмотрим, что такое ecx
, набрав display (char *) $ecx
:
(gdb) display (char *) $ecx
1: (char *) $ecx = 0xbffff63e "/home/blackbear/hello"
Вы можете использовать step
для продолжения одной инструкцией:
(gdb) step
35 mov edx, $ ; Beginning of line
1: (char *) $ecx = 0xbffff654 "emi"
Хорошо, вот и мы. ecx
указывает на мое имя, поэтому проблема не в этом. Теперь нам не нужно больше смотреть ecx
, поэтому использование undisplay
gdb
больше не покажет. Но нам нужно проверить edx
:
(gdb) undisplay
Delete all auto-display expressions? (y or n) y
(gdb) display $edx
2: $edx = 7
(gdb) step
36 sub edx, ecx ; Get length of name
2: $edx = 134512810
(gdb) step
37 int 80h
2: $edx = 1208257110
Ммм, думаю, ты этого не ожидал, верно? :) Проблема, кажется, здесь: mov edx, $
. Я не понимаю, что $
(никогда не использовал NASM), не могли бы вы объяснить?
EDIT
Хорошо понял. Вы не поняли, что сказал учебник. $
представляет текущее его местоположение, фактически:
36 sub edx, ecx ; Get length of name
11: $edx = 134512810
(gdb) display (void *) $edx
12: (void *) $edx = (void *) 0x80480aa
(gdb) display (void *) $eip
13: (void *) $eip = (void *) 0x80480af
сейчас edx
содержит адрес инструкции mov edx, $
. длиной 5 байтов (код операции (1 байт) + адрес (4 байта)), поэтому eip - edx = 5
.
Чтобы получить длину аргумента, вы можете использовать что-то вроде strlen()
, но я не могу вам здесь помочь, NASM не мой ассемблер. :)