2011-03-06 28 views
4

TASM(winXP上)で私のasmコードをコンパイルするのに使用しましたが、今は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のオプションを逃したと思いますか? はところで、私はコンパイル後

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

変数名を理解するためにイタリア語(おそらく)を知る必要がありますか? –

+0

@アーメンTsirunyan:アップ、私は完全に忘れてしまった。 :)編集 – BlackBear

+0

gdbは__before__命令を実行するので、表示された命令を実行するには 'stepi'または 'next'を実行する必要があることに注意してください。それでもなお、blの値は変更されているはずです。 – BatchyX

答えて

6

GDBは、8ビットまたは16ビットのエイリアス化されたレジスタを認識しません。それは常にあなたがeax, ebx、などを使用する必要がありますなど、al, bl, ax, bxのための0を出力します:

(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

+0

はい、Matthewのトリックはうまくいくはずです – Jester

1

私はそれはあなたが指摘してきた問題だかどうかわからないんだけど、私は1つを参照してくださいあなたのコードでかなり明白な問題です。 x86では、movではなく、はフラグに影響します。あなたのコード:

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

あなたはzフラグがアルの内容を反映するために更新されます[esi]からalをロードするときと仮定しているようです。それはではなく、ケースです。あなただけロードされた値がゼロであるかどうかをテストする、明示的なテストを追加する必要がありますするには:

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

にレジスタが以前に変更されている必要がありますが、フラグはないは反映して更新されている必要があります値。

nasmが正しい命令を生成したかどうかについては、コードを逆アセンブルして、実際に何があるかを確認します。今は、問題がnasmかgdbのどちらであるかを推測するのは難しいです。もちろん、ディスアセンブラにはバグがないことは保証されていませんが、このコードで問題が発生するのはちょっと驚きです。

+0

私の質問をobjdumpの出力で更新しました – BlackBear

+0

objdumpからの出力はmovのものがmovのようにアセンブルされていると思われるので、nasmは正常に動作しました。 OTOHの場合、objdumpから出力される出力は、その前のソースコードと一致しません。 –

+0

これは等価なので二次的な問題です。 – BlackBear

0

フラグはmovによって変更されないので、34行目のjzは意味を持ちません。最初のxorのコードに従えば、それがフラグを変更する唯一の命令なので、コードが34行目のjzに達すると、それはジャンプします(xorはゼロになっているためです)。これはalまたはblの変化しない値を説明するものではありませんが、xorのためにjzが常に実行されることを考慮した最適化が行われた可能性があります。

6

Jester has the right answer、およびアップ投票に値します。

しかし、私はコメントのために長すぎる何かを追加したいと思います:あなたは次のように追加することで、必要に応じて任意のdisplayが起こる直前に実行され、hook-stop hookを使用して、サブレジスタを表示するにはgdbを教えることができます.gdbinitファイルに:

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

(他のレジスタでは明らかに拡張されています)。 display $blなどは期待どおりに動作します。

+0

素敵なトリックです。共有のためのハンクス! –

+0

トリックありがとう、それは私を助ける! :) – BlackBear

関連する問題