0

これが私の短いアセンブリプログラムです:

; This code has been generated by the 7Basic
; compiler <http://launchpad.net/7basic>

extern printf

; Initialized data

      SECTION .data
f_0 dd 5.5
printf_f: db "%f",10,0

      SECTION .text

; Code

global main
  main:
push ebp
mov ebp,esp

push dword [f_0]
push printf_f
call printf
add esp,8

mov esp,ebp
pop ebp
mov eax,0
ret

プログラムが実行することになっているのは5.5を出力することですが、次のように出力します。

-4101885043414705786563701568963176764603483495211119243453355953219830430011006780068899468997203661787555969981250050126586203424320244681571103387315766489883301796219461838644670607029711305942610787622864198879363376953745160639821663444829839767678538571371627347101810056161000273217639447052410683392.000000

一体何が間違っているのですか?コードは2つの引数をにプッシュしてprintf()から呼び出しています。複雑なことは何もありません。


更新:私はこれを修正したと考えるのに少し時期尚早でした。コードを更新しました。

4

1 に答える 1

5

この命令push f_0は、メモリ内の5.5ではなくスタック上のf_0のアドレスをプッシュするため、printfルーチンは、アドレスと保存されたebp(スタック上の次の4バイト)を取得し、ビットをdoubleとして解釈して出力します。アウト。ご覧のとおり、これは非常に大きな数であることがわかります。

f_0から8バイトをロードし、それらをプッシュする必要があります。何かのようなもの

move eax, f_0
push dword ptr [eax+4]
push dword ptr [eax]

編集

fp64の値は8バイトであるため、8バイトをプッシュする必要があります。fp64は、printfが印刷方法を知っているすべてです。実際、fp64は、Cが関数に渡す方法または操作する方法を知っているすべてです。fp32値は、メモリからのロードとメモリへの保存のみが可能ですが、操作される前に常に暗黙的にfp64(またはそれ以上)に変換されます。fp32値をロードし、それをfp64に変換してスタックにプッシュする場合は、次を使用できます。

fld dword ptr [f_0]
sub esp, 8
fstp qword ptr [esp]

これは実際にfp32値をロードし、それをfp80(x87の内部形式)に変換してから、そのfp80値をfp64に変換し、スタックに格納します。

于 2010-09-12T04:12:38.497 に答える