是否有Divmod *不*限于字词(< = 65535)? [英] Is there a DivMod that is *not* Limited to Words (<=65535)?

查看:174
本文介绍了是否有Divmod *不*限于字词(< = 65535)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Delphi中,DivMod函数的声明是

 程序DivMod(红利:红利主义;除数:Word; 
var Result,Remainder:Word);

因此,除数,结果和余数不能超过65535,这是一个相当严重的限制。为什么是这样?为什么不能脱钩是

 程序DivMod(红利:红衣主教;除数:红衣主教; 
var结果,剩余:红衣主教);

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

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

适应红衣主教?最初尝试的速度是多少?

  procedure DivModInt(const Dividend:integer; const除数:integer; out result:integer; out余数:整数); 
begin
result:=派息div除数;
余数:=股利除数;
结束

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

解决方案

这样的过程是可能的。我没有足够的测试代码,但我觉得没问题:

 程序DivMod32(Dividend,Divisor:Cardinal; var Quotient,剩余:红衣主教); 
asm
PUSH EBX
MOV EBX,EDX
XOR EDX,EDX
DIV EBX
MOV [ECX],EAX
MOV EBX,剩余
MOV [EBX],EDX
POP EBX
结束;






更新: / p>

更高效:

 功能DivMod32(股息,除数:红衣主教; var Remainder:Cardinal):红衣主教; 
asm
PUSH EBX
MOV EBX,EDX
XOR EDX,EDX
DIV EBX
MOV [ECX],EDX
POP EBX
结束;






更新2:



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

 程序DivMod32(const Dividend:Cardinal; const Divisor:Cardinal; 
输出结果:Cardinal;剩余部分:红衣主教);
begin
result:=派息div除数;
余数:=股利除数;
结束

生成代码

 code> 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:余数:=股息mod除数;
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实现时间缩短了约三倍,但是60%是一个合理的估计。


In Delphi, the declaration of the DivMod function is

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

Thus, the divisor, result, and remainder cannot be grater than 65535, a rather severe limitation. Why is this? Why couldn't the delcaration be

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

The procedure is implemented using assembly, and is therefore probably extremely fast. Would it not be possible for the code

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

to be adapted to cardinals? How much slower is the naïve attempt

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

that is not (?) limited to 16-bit integers?

解决方案

Such a procedure is possible. I have not tested the code enough, but I think it's OK:

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;


Updated:

even more efficient:

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;


Updated 2:

You can see the assembly code generated by Delphi compiler in the Disassembly (or CPU) window. Eg, the procedure

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

generates code

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

This code is linear (contains no jumps) and modern processors (with long instruction pipeline) are very efficient in executing linear code. So though my DivMode32 implementation is about 3 times shorter, 60% is a reasonable estimate.

这篇关于是否有Divmod *不*限于字词(< = 65535)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆