装配(或NASM)恼人的问题

时间:2011-03-06 19:50:00

标签: linux assembly gdb nasm

我曾经用TASM编译我的asm代码(在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) 

我无法理解为什么albl没有改变 我确定我的代码 是正确的,但是......我想我错过了一些NASM的选项? BTW我用

编译
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 个答案:

答案 0 :(得分:6)

请注意,GDB不知道8位或16位别名寄存器。它将始终为al, bl, ax, bx等打印0。您应该使用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 :(得分:6)

Jester has the right answer,值得投票。

但是,我想添加一些评论太长的内容:如果您愿意,可以教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等将按照您的预期运作。

答案 2 :(得分:1)

我不确定这是你注意到的问题,但我在你的代码中看到了一个相当明显的问题。在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上。当然,反汇编程序也不保证也没有错误,但是看到代码问题这么简单,我会有点惊讶。

答案 3 :(得分:0)

标志不会被mov修改,因此第34行的jz没有意义。如果你遵循初始xor中的代码,这是修改标志的唯一指令,那么当代码到达第34行的jz时它就会跳转(因为xor将它保持为零) 。这并不能解释al或bl的非变化值,但可能会进行一些优化,考虑到因为xor而总是执行jz。