簡體   English   中英

裝配(或NASM)惱人的問題

[英]Assembly (or NASM) annoying problem

我曾經用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>

請注意,GDB不知道8位或16位別名寄存器。 對於al, bl, ax, bxal, 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 'ô'

傑斯特有正確的答案 ,值得投票。

但是,我想添加一些評論太長的內容:你可以教gdb顯示子寄存器,如果你願意的話,可以使用在任何display發生之前運行的hook-stop鈎子 ,方法是添加以下內容:你的.gdbinit文件:

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

(以明顯的方式擴展到其他寄存器)。 display $bl等將按預期工作。

我不確定這是你注意到的問題,但我在你的代碼中看到了一個相當明顯的問題。 在x86,一個mov 影響標志。 你的代碼:

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

似乎假設當你從[esi]加載al時, z標志將被更新以反映al的內容。 事實並非如此。 要測試剛剛加載的值是否為零,您需要添加一個顯式測試:

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

寄存器中的值應該一改之前,但這些標志應該被更新,以反映價值。

至於nasm是否產生了正確的指令,我會反匯編代碼,看看究竟是什么。 現在,很難猜出問題出在nasm還是gdb上。 當然,反匯編程序也不能保證也沒有錯誤,但是看到代碼問題這么簡單,我會有點驚訝。

標簽不會被mov修改,因此第34行的jz沒有意義。 如果你遵循初始xor的代碼,那是修改標志的唯一指令,所以當代碼到達第34行的jz時,它就會跳轉(因為xor它保持為零)。 這並不能解釋al或bl的非變化值,但可能會進行一些優化,考慮到因為xor而總是執行jz。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM