目的を達成するには、浮動小数点命令セットを使用する必要があります。あなたが役立つかもしれないいくつかの手順は以下のとおりです。
int main(void)
{
float res;
__asm {
push dword ptr 5; // fild needs a memory location, the trick is
fild [esp]; // to use the stack as a temp. storage
fild [esp]; // now st0 and st1 both contain (float) 5
add esp, 4; // better not screw up the stack
fadd st(0), st(0); // st0 = st0 + st0 = 10
fdivp st(1), st(0); // st0 = st1/st0 = 5/10 = 0.5
sub esp, 4; // again, let's make some room on the stack
fstp [esp]; // store the content of st0 into [esp]
pop eax; // get 0.5 off the stack
mov res, eax; // move it into res (main's local var)
add esp, 4; // preserve the stack
}
printf("res is %f", res); // write the result (0.5)
}
EDIT:
ハロルドが指摘したように、計算命令もあります
fild <int> - loads and integer into st0 (not an immediate
faddp - adds st0 to st1, and pop from reg stack (i.e. result in st0)
fdivp - divides st0 by st1, then pop from reg stack (again, result in st0)
は、ここで簡単な例スニペット(VS2010のインラインアセンブリ)です直接的に平方根、それはfsqrt
です。オペランドと結果はともにst0
です。
EDIT#2:あなたは本当にはっきり場合referenceが指定されていない私のようst0
即値にロードすることができれば
私は確認されませんでした。したがって、私はチェックして、小さなスニペットを行なったし、結果は次のとおりです。
[email protected]:
000357A8 00 00 add byte ptr [eax],al
000357AA 60 pushad
000357AB 41 inc ecx
は、だから私は、残念ながら、あなたがどこかに自分の番号を格納する必要があり、それを締結する必要があります。
float res = 5.0 * 3 - 1;
000313BE D9 05 A8 57 03 00 fld dword ptr [[email protected] (357A8h)]
000313C4 D9 5D F8 fstp dword ptr [res]
これらは357A8h
のバイトがありますメインメモリにロードして格納するときに使用します。もちろん、私が上で示唆したようにスタックを使用することは必須ではなく、実際にはあなたのデータセグメントや他の場所に定義された変数を持つこともできます。
EDIT#3:
は、アセンブリがビートに強い獣である、心配しないでください。)あなたのコードについて:
mov ecx, 169 ; the number with i wanna to root
sub esp, 100 ; i move esp for free space
push ecx ; i save value of ecx
add esp,4 ; push was move my ebp,then i must come back
fld ; i load from esp, then i should load ecx
fsqrt ; i sqrt it
fst ; i save it on ebp+100
add esp,100 ; back esp to ebp
あなたがfld
とfst
のオペランドを逃しています。あなたのコメントを見て、あなたがfld [esp]
とfst [esp]
を望んだとしたら、どうしてあなたはebp
について話しているのですか? ebp
は、スタックフレームの先頭を保持することになっています(ここでは、多くのものが混乱してはいけません)一方、esp
は、その終わりを保持しています。基本的にスタックフレームの最後で動作したいのは、スタックフレームの後にはジャンクがないからです。誰も気にしません。
平方根を計算して保存した後は、最後にadd esp, 4
にする必要があります。これは、push ecx
もsub esp, 4
をフードの下に置いて、値を押し込むためのスペースを確保しています。値を保存するときにはまだ部屋が必要です。部屋が既にpush
で作られているので、sub esp, 100
とadd esp, 100
を避けることもできます。
最後の1つの警告:整数と浮動小数点値は非常に異なる方法で表現されるため、両方の型を使用する必要がある場合は、選択した命令に注意してください。あなたが提案したコードは両方とも浮動小数点値で動作するfld
とfst
を使用しているので、結果は期待どおりになりません。例? 00 00 00 A9は169のバイト表現ですが、それは浮動小数点数+ 2.3681944047089408e-0043を表しています(そこにいる人々にとっては、実際には長い倍精度です)。
ので、最終的なコードは次のとおりです。
mov ecx, 169; // the number which we wanna root
push ecx; // save it on the stack
fild [esp]; // load into st0
fsqrt; // find the square root
fistp [esp]; // save it back on stack (as an integer)
// or fst [esp] for saving it as a float
pop ecx; // get it back in ecx
ところで、FPUコードとSSEコードの両方に平方根の命令があります。だからあなたは本当にこれを必要としません.. – harold
@harold、nasmアセンブリの平方根のための指示がありますか? CodeTableにはありません。あなたはそれを教えてくれますか? FSEコードの場合は –
SSE2の場合はFSQRT(D9 FA)、SSE2の場合はSQRTSS(F3 0F 51/r)、SSE2の場合はSQRTSD(F2 0F 51/r)(4パック浮動小数点または2パック2倍パックもあります)。ここでは、より完全なリファレンスです:http://siyobik.info/main/reference/ – harold