Сборка (или NASM) раздражающая проблема - PullRequest
4 голосов
/ 06 марта 2011

Раньше я компилировал свой ASM-код с помощью TASM (на winXP), но у меня были некоторые проблемы, поэтому теперь я использую NASM (на Linux). Этот фрагмент показывает, что я пытаюсь сделать:

(gdb) list 35
30      xor ecx,ecx             # ecx is a counter
31      mov bl, ' '             # this is what I'm looking for
32  count_spaces:
33      mov al,[esi]            # grab a char
34      jz  spaces_counted      # is this the end?
35      inc esi                 # next char
36      cmp al,bl               # found one?
37      jne count_spaces        # nope, loop
38      inc ecx                 # yep, inc counter
39      jmp count_spaces        # and loop

Мне это кажется правильным, , но :

Breakpoint 1, main () at project1.asm:30
30      xor ecx,ecx
(gdb) display (char) $al
1: (char) $al = 0 '\000'
(gdb) display (char) $bl
2: (char) $bl = 0 '\000'
(gdb) next
31      mov bl, ' '
2: (char) $bl = 0 '\000'
1: (char) $al = 0 '\000'
(gdb) 
count_spaces () at project1.asm:33
33      mov al,[esi]
2: (char) $bl = 0 '\000'
1: (char) $al = 0 '\000'
(gdb) 

Я не могу понять, почему al и bl не изменились.
Я уверен, что мой код правильный , но .. Я думаю, что я пропустил некоторые варианты NASM? Кстати, я скомпилирован с

nasm -f elf -l project1.lst -o project1.o -i../include/ -g  project1.asm

После компиляции я разобрал вывод и получил:

 80483ec:   31 c9                   xor    %ecx,%ecx
 80483ee:   bb 20 00 00 00          mov    $0x20,%ebx

080483f3 <count_spaces>:
 80483f3:   8b 06                   mov    (%esi),%eax
 80483f5:   3d 00 00 00 00          cmp    $0x0,%eax
 80483fa:   74 0b                   je     8048407 <spaces_counted>
 80483fc:   46                      inc    %esi
 80483fd:   39 d8                   cmp    %ebx,%eax
 80483ff:   75 f2                   jne    80483f3 <count_spaces>
 8048401:   41                      inc    %ecx
 8048402:   e9 ec ff ff ff          jmp    80483f3 <count_spaces>

Ответы [ 4 ]

6 голосов
/ 07 марта 2011

Шут имеет правильный ответ и заслуживает повышенного голоса.

Но я хотел бы добавить кое-что, что слишком длинно для комментария: вы можете научить gdb для отображения подрегистров, если вы хотите, используя hook-stop hook , который запускается непосредственно перед тем, как произойдет любое display, добавив в ваш файл .gdbinit следующее:

define hook-stop
set $bl=($ebx & 0xff)
set $bh=(($ebx & 0xff00) >> 8)
set $bx=($ebx & 0xffff)
end

(расширять очевидным образом для других регистров).display $bl и т. Д. Будут работать так, как вы ожидаете.

6 голосов
/ 07 марта 2011

Обратите внимание, что GDB не знает о 8 или 16-битных регистрах с псевдонимами. Всегда будет печататься 0 для al, bl, ax, bx и т. Д. Вы должны использовать eax, ebx и т. Д .:

(gdb) info registers bl
Invalid register `bl'
(gdb) info registers bx
Invalid register `bx'
(gdb) info registers ebx
ebx            0xf7730ff4       -143454220
(gdb) p $bl
$1 = void
(gdb) p $bx
$2 = void
(gdb) p $ebx
$3 = -143454220
(gdb) p/x $bl
$4 = Value can't be converted to integer.
(gdb) p/x $bx
$5 = Value can't be converted to integer.
(gdb) p/x $ebx
$6 = 0xf7730ff4
(gdb) p (char) $bl
$7 = 0 '\0'
(gdb) p (char) $bx
$8 = 0 '\0'
(gdb) p (char) $ebx
$9 = -12 'ô'
1 голос
/ 06 марта 2011

Я не уверен, что это проблема, которую вы заметили, но я вижу одну довольно очевидную проблему в вашем коде.На x86 mov не влияет на флаги , а не .Ваш код:

33      mov al,[esi]            # grab a char
34      jz  spaces_counted      # is this the end?

Предполагается, что при загрузке al из [esi] флаг z будет обновлен в соответствии с содержанием al.Это не дело.Чтобы проверить, является ли значение, которое вы только что загрузили, нулевым, вам нужно добавить явный тест:

mov al, [esi]
test al, al
jz spaces_counted

Значение в , которое регистр должен был изменить раньше, но флаги должны not были обновлены, чтобы отразить значение.

Что касается того, выдал ли nasm правильные инструкции, я бы разобрал код, чтобы увидеть, что на самом деле там.Сейчас трудно угадать, связана ли проблема с nasm или с gdb.Конечно, дизассемблеры также не гарантированы без ошибок, но я был бы немного удивлен, увидев проблему с кодом так просто.

0 голосов
/ 06 марта 2011

Флаги не изменяются mov, поэтому jz в строке 34 не имеет смысла.Если вы следуете коду из начального xor, это единственная инструкция, которая изменяет флаги, поэтому, когда код достигает jz в строке 34, он просто скачет (потому что xor оставил его равным нулю).Это не объясняет неизменяющиеся значения al или bl, но, возможно, произошла некоторая оптимизация, учитывающая, что jz всегда выполняется из-за xor.

...