代码之家  ›  专栏  ›  技术社区  ›  Andreas Rejbrand

是否有一个divmod*不限于单词(<=65535)?

  •  4
  • Andreas Rejbrand  · 技术社区  · 16 年前

    在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位整数?

    1 回复  |  直到 16 年前
        1
  •  13
  •   kludg    16 年前

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

    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%是一个合理的估计。