2011-03-06 40 views
4

我用來編譯(在WinXP)我用TASM彙編代碼,但我有一些麻煩所以現在我使用NASM(在Linux上)。該片段展示了我想要做的事:大會(或NASM)惱人的問題

(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> 
+0

我是否需要了解意大利語(大概)以瞭解您的變量名? – 2011-03-06 19:53:55

+0

@Armen Tsirunyan:ups,我完全忘了那個。 :)編輯 – BlackBear 2011-03-06 19:57:49

+0

請注意,gdb顯示指令__before__執行它們,所以你需要'stepi'或'next'來執行顯示的指令。但是,bl的價值應該已經改變了。 – BatchyX 2011-03-06 20:47:33

回答

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 'ô' 
+0

謝謝,那麼問題只與gdb有關嗎?我的意思是,如果我使用@Matthew Slattery的技巧,我仍然可以使用bl和al? – BlackBear 2011-03-07 10:53:04

+0

是的,Matthew的訣竅應該可以工作 – Jester 2011-03-07 11:53:45

1

我不知道這是否是你已經注意到這個問題,但我看到一個在你的代碼中相當明顯的問題。在x86上,mov確實不是影響標誌。您的代碼:

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

似乎假定,當你從[esi]z標誌將被更新,以反映人的內容加載al。這是不是的情況。爲了測試你剛剛加載的值是否爲零,你需要添加一個明確的測試:

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

價值寄存器應該一改之前,但標誌應該已經更新,以反映價值。

至於是否NASM產生正確的指示,我拆開代碼,看看什麼是真正在那裏。現在,很難猜測問題是否存在於nasm或gdb中。當然,反彙編也不能保證沒有錯誤,但是如果看到代碼問題很簡單,我會有點驚訝。

+0

我使用objdump的輸出更新了我的問題 – BlackBear 2011-03-06 20:27:11

+0

objdump的輸出似乎表明mov被彙編爲mov,所以nasm的工作是正確的。 OTOH,你從objdump顯示的輸出不會匹配前面的源代碼。 – 2011-03-06 20:32:42

+0

這是一個次要的問題,因爲它們是等效的 – BlackBear 2011-03-06 20:50:26

0

標誌不能被MOV修改,所以在線路34上的JZ是沒有意義的。如果您從最初xor跟隨代碼,那就是修改標記的唯一指令,所以當代碼到達行34 JZ它只是跳轉(因爲xor離開它爲零)。這並不能解釋al或bl的非變化值,但可能會考慮到因爲xor而始終執行jz的某些優化。

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等,然後將按預期工作。

+0

好戲。 hank分享! – 2011-03-07 08:29:56

+0

謝謝你的訣竅,它會幫助我! :) – BlackBear 2011-03-07 10:51:44