这是_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
操作之后,操作数将在[ESP+16]:[ESP+12]
和中找到[ESP+4]:[ESP]
。
在[ESP+8]
您将找到函数的返回地址。
该函数的整个设计依赖于这样一个事实,即在MUL
对 32 位操作数进行操作时,该操作在EDX:EAX
. 因此,该函数本质上是对被视为两个 32 位数字的操作数执行长乘法。
让我们用 where 表示操作数H1:L1
,H2:L2
其中H
表示高 32 位,L
表示低 32 位。那么前两个乘法是H1*L2
和H2*L1
。结果的高部分 inEDX
被忽略,因为它不适合 64 位结果。最后的乘法是L1*L2
与前两个乘法的低部分相结合的高部分。H1*H2
甚至没有尝试过,因为显然它不适合。此函数忽略溢出。