4

在 Delphi 中,DivMod 函数的声明是

procedure DivMod(Dividend: Cardinal; Divisor: Word;
  var Result, Remainder: Word);

因此,除数、结果和余数不能大于 65535,这是一个相当严重的限制。为什么是这样?为什么不能声明

procedure DivMod(Dividend: Cardinal; Divisor: Cardinal;
  var Result, Remainder: Cardinal);

该过程是使用汇编实现的,因此可能非常快。代码不可能

    PUSH    EBX
    MOV     EBX,EDX
    MOV     EDX,EAX
    SHR     EDX,16
    DIV     BX
    MOV     EBX,Remainder
    MOV     [ECX],AX
    MOV     [EBX],DX
    POP     EBX

适应红衣主教?天真的尝试慢了多少

procedure DivModInt(const Dividend: integer; const Divisor: integer; out result: integer; out remainder: integer);
begin
  result := Dividend div Divisor;
  remainder := Dividend mod Divisor;
end;

那不是(?)仅限于 16 位整数?

4

1 回答 1

13

这样的程序是可能的。我没有对代码进行足够的测试,但我认为还可以:

procedure DivMod32(Dividend, Divisor: Cardinal; var Quotient, Remainder: Cardinal);
asm
        PUSH EBX
        MOV  EBX,EDX
        XOR  EDX,EDX
        DIV  EBX
        MOV  [ECX],EAX
        MOV  EBX,Remainder
        MOV  [EBX],EDX
        POP  EBX
end;

更新:

更高效:

function DivMod32(Dividend, Divisor: Cardinal; var Remainder: Cardinal): Cardinal;
asm
        PUSH EBX
        MOV  EBX,EDX
        XOR  EDX,EDX
        DIV  EBX
        MOV  [ECX],EDX
        POP  EBX
end;

更新2:

您可以在反汇编(或 CPU)窗口中看到 Delphi 编译器生成的汇编代码。例如,程序

procedure DivMod32(const Dividend: Cardinal; const Divisor: Cardinal;
                    out result: Cardinal; out remainder: Cardinal);
begin
  result := Dividend div Divisor;
  remainder := Dividend mod Divisor;
end;

生成代码

Unit1.pas.28: begin
0046CC94 55               push ebp
0046CC95 8BEC             mov ebp,esp
0046CC97 53               push ebx
0046CC98 56               push esi
0046CC99 8BF2             mov esi,edx
0046CC9B 8BD8             mov ebx,eax
Unit1.pas.29: result := Dividend div Divisor;
0046CC9D 8BC3             mov eax,ebx
0046CC9F 33D2             xor edx,edx
0046CCA1 F7F6             div esi
0046CCA3 8901             mov [ecx],eax
Unit1.pas.30: remainder := Dividend mod Divisor;
0046CCA5 8BC3             mov eax,ebx
0046CCA7 33D2             xor edx,edx
0046CCA9 F7F6             div esi
0046CCAB 8B4508           mov eax,[ebp+$08]
0046CCAE 8910             mov [eax],edx
Unit1.pas.31: end;
0046CCB0 5E               pop esi
0046CCB1 5B               pop ebx
0046CCB2 5D               pop ebp
0046CCB3 C20400           ret $0004

该代码是线性的(不包含跳转),现代处理器(具有长指令流水线)在执行线性代码方面非常有效。因此,尽管我的 DivMode32 实现要短约 3 倍,但 60% 是一个合理的估计。

于 2010-03-07T20:33:00.783 回答