そのチュートリアルを使用することに賛成してください、それはとても良いです:)
そこにいくつかの問題があります:
- あなたの価値観はそうではなく、そうなる
st(0)
でしょst(7)
う。レジスター番号は固定されており、常に一番上にありますが、バレルが回転します。何かをロードすると、それはになります。後で何か他のものをロードすると、バレルが回転し、以前持っていたものがに移動し、現在の値が入力されます。st(1)
st(0)
st(0)
st(0)
st(1)
st(0)
- アセンブラが、やなどの適切なサイズの命令を生成することを確認してください
fld
。fst
invoke
マクロが浮動小数点引数をに渡す方法を知っていることを確認してくださいprintf
- FPUスタックをクリーンアップしていません(ここでの動作には影響しません。これは一般的な問題です)
デバッガーを使用してコードをシングルステップで実行することをお勧めします。これにより、何が起こっているかを確認でき、を使用しようとして混乱する必要もありませんprintf
。
更新:Linuxでgdbを使用し、動作するコードを使用したサンプルセッション(わかりやすくするために編集):
$ cat > div.s
.intel_syntax noprefix
.globl main
.data
num1: .double 48.6
num2: .double 17.1
fmt: .string "%g\n"
.text
main:
sub esp, 16
fld qword ptr [num1] # st(0)=48.6
fld qword ptr [num2] # st(0)=17.1, st(1)=48.6
fdivp # st(0)=st(1)/st(0), one item popped
fstp qword ptr [esp+4] # store as argument and pop
mov dword ptr [esp], offset fmt
call printf
add esp, 16
ret
$ gcc -masm=intel -m32 -g div.s -o div
$ ./div
2.84211
$ gdb ./div
GNU gdb (GDB) 7.3.50.20111117-cvs-debian
(gdb) br main
Breakpoint 1 at 0x80483c4: file div.s, line 11.
(gdb) r
Starting program: div
Breakpoint 1, main () at div.s:11
11 sub esp, 16
(gdb) n
main () at div.s:12
12 fld qword ptr [num1] # st(0)=48.6
(gdb)
13 fld qword ptr [num2] # st(0)=17.1, st(1)=48.6
(gdb) info float
=>R7: Valid 0x4004c266666666666800 +48.60000000000000142
R6: Empty 0x00000000000000000000
R5: Empty 0x00000000000000000000
R4: Empty 0x00000000000000000000
R3: Empty 0x00000000000000000000
R2: Empty 0x00000000000000000000
R1: Empty 0x00000000000000000000
R0: Empty 0x00000000000000000000
(gdb) n
14 fdivp # st(0)=st(1)/st(0), one item popped
(gdb) info float
R7: Valid 0x4004c266666666666800 +48.60000000000000142
=>R6: Valid 0x400388ccccccccccd000 +17.10000000000000142
R5: Empty 0x00000000000000000000
R4: Empty 0x00000000000000000000
R3: Empty 0x00000000000000000000
R2: Empty 0x00000000000000000000
R1: Empty 0x00000000000000000000
R0: Empty 0x00000000000000000000
(gdb) n
15 fstp qword ptr [esp+4] # store as argument and pop
(gdb) info float
=>R7: Valid 0x4000b5e50d79435e4e16 +2.842105263157894584
R6: Empty 0x400388ccccccccccd000
R5: Empty 0x00000000000000000000
R4: Empty 0x00000000000000000000
R3: Empty 0x00000000000000000000
R2: Empty 0x00000000000000000000
R1: Empty 0x00000000000000000000
R0: Empty 0x00000000000000000000
(gdb) n
16 mov dword ptr [esp], offset fmt
(gdb) info float
R7: Empty 0x4000b5e50d79435e4e16
R6: Empty 0x400388ccccccccccd000
R5: Empty 0x00000000000000000000
R4: Empty 0x00000000000000000000
R3: Empty 0x00000000000000000000
R2: Empty 0x00000000000000000000
R1: Empty 0x00000000000000000000
=>R0: Empty 0x00000000000000000000
gdb
次に実行される命令を出力することに注意してください。FPUスタックトップは矢印でマークされています。これは常にst(0)
定義によるものです。その後に、昇順で他の人が続き、必要に応じてラップアラウンドします。最初のダンプは、矢印でマークされているため48.6
にロードされていることを示しています。他の場所は空です。st(0)
次に、矢印が移動した(バレルが回転した)ため、再び17.1
ロードされています。st(0)
今48.6
ですst(1)
。FDIVP
除算を実行し、スタックから1つのアイテムを削除するため、結果は結果にst(0)
なり、残りは空になります。次に、 as引数をFSTP
格納し、スタックから削除するため、すべてのレジスタが空になります。st(0)
printf