Показать сообщение отдельно
  #21  
Старый 09.06.2012, 13:00
Аватар для ined
ined ined вне форума
Начинающий
 
Регистрация: 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 или для обоих сразу.
Ответить с цитированием