Delphi 是否有一个DivMod*不*限于单词(<;=65535)?
在Delphi中,DivMod函数的声明是Delphi 是否有一个DivMod*不*限于单词(<;=65535)?,delphi,integer,word,Delphi,Integer,Word,在Delphi中,DivMod函数的声明是 procedure DivMod(Dividend: Cardinal; Divisor: Word; var Result, Remainder: Word); 因此,除数、结果和余数不能大于65535,这是一个相当严重的限制。为什么会这样?为什么不能用delcaration呢 procedure DivMod(Dividend: Cardinal; Divisor: Cardinal; var Result, Remainder: Car
procedure DivMod(Dividend: Cardinal; Divisor: Word;
var Result, Remainder: Word);
因此,除数、结果和余数不能大于65535,这是一个相当严重的限制。为什么会这样?为什么不能用delcaration呢
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位整数?这样的过程是可能的。我还没有对代码进行足够的测试,但我认为还可以:
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%是一个合理的估计。非常感谢。与使用div和mod运算符(至少在我的i7系统上)的简单方法相比,您的ASM代码只需要大约60%的时间。(这不是很奇怪吗?Delphi编译器不应该创建高效的代码吗?)。Serg(ab)使用的是两条线都需要相同的除法,并且他可以同时得到商和余数。还要注意,由于方法签名的不同,公平比较要求您与第一个进行比较,而不是第二个。与Delphi创建的19条指令相比,手工编写的ASM代码中有8条指令。删除额外分区的3-4条指令,您将减少到8条指令,而不是15条指令。由于安装/拆卸代码不同,您留下的指令大部分不同。在D2010中,其中4条指令实际上被添加到了他的代码中(EBP操作和RET)。现在,如果您从生成的代码中删除额外的除法,我们只有3条指令的优势-而且,据我所知,区别来自Serg更巧妙地选择了他的寄存器(其中2条被Serg切掉,根本不接触ESI)。他之所以能够做到这一点,是因为他比编译器更了解您代码的意图——它可能以一种更安全的方式进行操作,因为它不知道您的意图是什么。我将它与过程进行了比较。可以在这里找到x64版本:您接受的答案没有回答标题中的问题。也许你可以编辑标题,使它更接近你真正想要的答案。