
09.06.2012, 13:00
|
 |
Начинающий
|
|
Регистрация: 16.11.2008
Адрес: Российская Федерация!! :)
Сообщения: 165
Версия Delphi: Delphi 2010
Репутация: 1272
|
|
Про программные скобки.
Код:
procedure DivMod(Dividend: UInt64; Divisor: UInt64;
var Result, Remainder: UInt64); overload;
{$IF DEFINED(CPUX64) and NOT DEFINED(PUREPASCAL_X64)}
asm
MOV R10,RDX
MOV RAX,RCX
XOR EDX,EDX
DIV R10
MOV [R8],RAX
MOV [R9],RDX
end;
{$ELSEIF DEFINED(CPUX86) and NOT DEFINED(PUREPASCAL)}
// Merged from system __lludiv and __llumod
asm
PUSH EBX
PUSH ESI
PUSH EDI
PUSH EAX
PUSH EDX
//
// Now the stack looks something like this:
//
// 40[esp]: Dividend(high dword)
// 36[esp]: Dividend(low dword)
// 32[esp]: divisor (high dword)
// 28[esp]: divisor (low dword)
// 24[esp]: return EIP
// 20[esp]: previous EBP
// 16[esp]: previous EBX
// 12[esp]: previous ESI
// 8[esp]: previous EDI
// 4[esp]: previous EAX Result ptr
// [esp]: previous EDX Remainder ptr
//
MOV EBX,28[ESP] // get the divisor low word
MOV ECX,32[ESP] // get the divisor high word
MOV EAX,36[ESP] // get the dividend low word
MOV EDX,40[ESP] // get the dividend high word
OR ECX,ECX
JNZ @DivMod64@slow_ldiv // both high words are zero
OR EDX,EDX
JZ @DivMod64@quick_ldiv
OR EBX,EBX
JZ @DivMod64@quick_ldiv // if ecx:ebx == 0 force a zero divide
// we don't expect this to actually
// work
@DivMod64@slow_ldiv:
MOV EBP,ECX
MOV ECX,64 // shift counter
XOR EDI,EDI // fake a 64 bit dividend
XOR ESI,ESI //
@DivMod64@xloop:
SHL EAX,1 // shift dividend left one bit
RCL EDX,1
RCL ESI,1
RCL EDI,1
CMP EDI,EBP // dividend larger?
JB @DivMod64@nosub
JA @DivMod64@subtract
CMP ESI,EBX // maybe
JB @DivMod64@nosub
@DivMod64@subtract:
SUB ESI,EBX
SBB EDI,EBP // subtract the divisor
INC EAX // build quotient
@DivMod64@nosub:
LOOP @DivMod64@xloop
//
// When done with the loop the four registers values' look like:
//
// | edi | esi | edx | eax |
// | remainder | quotient |
//
JMP @DivMod64@finish
@DivMod64@quick_ldiv:
DIV EBX // unsigned divide
MOV ESI,EDX
XOR EDX,EDX
XOR EDI,EDI
@DivMod64@finish:
POP EBX
POP ECX
MOV [EBX],ESI
MOV [EBX+4],EDI
MOV [ECX],EAX
MOV [ECX+4],EDX
POP EDI
POP ESI
POP EBX
end;
{$ELSE PUREPASCAL}
begin
Result := Dividend div Divisor;
Remainder := Dividend mod Divisor;
end;
{$IFEND}
Вырезал из System.Math .
Можете объяснить, как этот кусочек работает? И для какой он х32 или х64 или для обоих сразу.
|