_llmul
これは、質問で見た非常に役立つ情報のためのコードです。関係なく、_llmul
32 ビット マシンで 64 ビットの整数乗算を実行するヘルパー関数です。
関数のソース コードは次のようになります。
// 64 bit integer helper routines
//
// These functions always return the 64-bit result in EAX:EDX
// ------------------------------------------------------------------------------
// 64-bit signed multiply
// ------------------------------------------------------------------------------
//
// Param 1(EAX:EDX), Param 2([ESP+8]:[ESP+4]) ; before reg pushing
//
procedure __llmul;
asm
push edx
push eax
// Param2 : [ESP+16]:[ESP+12] (hi:lo)
// Param1 : [ESP+4]:[ESP] (hi:lo)
mov eax, [esp+16]
mul dword ptr [esp]
mov ecx, eax
mov eax, [esp+4]
mul dword ptr [esp+12]
add ecx, eax
mov eax, [esp]
mul dword ptr [esp+12]
add edx, ecx
pop ecx
pop ecx
ret 8
end;
PUSH
これにより、2 つの演算の後、オペランドが と にあることが明らかに[ESP+16]:[ESP+12]
なり[ESP+4]:[ESP]
ます。
[ESP+8]
関数の戻りアドレスが表示されます。
MUL
関数の設計全体は、32 ビットのオペランドを操作する場合、演算が 64 ビットの結果を返すという事実に依存していますEDX:EAX
。したがって、この関数は基本的に、2 つの 32 ビット数字として扱われるオペランドに対して長い乗算を実行します。
オペランドをH1:L1
とH2:L2
でH
表し、 は上位 32 ビットをL
表し、 は下位 32 ビットを表します。次に、最初の 2 つの乗算はH1*L2
とH2*L1
です。結果の上位部分 inEDX
は、64 ビットの結果に収まらないため無視されます。最後の掛け算はL1*L2
、最初の 2 つの掛け算の低い部分と組み合わせた高い部分です。明らかに適合しないため、H1*H2
試みさえされていません。この関数はオーバーフローを無視します。