为什么要使用汇编程序?
没有充分的理由!
这是将您的 asm 代码直接翻译成 Delphi pascal:
procedure ExecuteAsm(Tab, Buf: PByte; Len: DWORD);
repeat
Buf^ := Tab[Buf^];
inc(Buf);
dec(Len);
until Len = 0;
end;
但是正如您现在所看到的,如果值 Len 为 0,那么程序应该会损坏程序内存。
...
这段代码看起来更好,因为while循环测试0值并且从不执行循环。
procedure ExecuteAsm(Tab, Buf: PByte; Len: cardinal);
begin
while Len > 0 do
begin
Buf^ := Tab[Buf^];
inc(Buf);
dec(Len);
end;
end;
但是,如果您仍然喜欢汇编程序,则必须保留 ebx/rbx 寄存器之类的...
procedure ExecuteAsm(Tab, Buf: Pointer; Len: DWORD);
asm
push ebx //rbx
//... your code
pop ebx //rbx
end;
编辑:添加 32 位和 64 位测试
因为 HeartWare 没有做 David Heffernan 的作业,所以我做了。
最初的测试做了大卫赫弗南,看看 HeartWares cmets。我只做了一点改动,又添加了两个测试用例。
这个指令很重要:{$O+} //打开编译器优化... :)
{$APPTYPE CONSOLE}
uses
Diagnostics;
{$O+} //Turn on compiler optimisation... :)
procedure _asm_GJ(Tab, Buf : PByte; Len : Cardinal);
// 32-bit eax edx ecx
// 64-bit rcx rdx r8
asm
{$IFDEF CPUX64 }
test Len, Len
jz @exit
@loop:
movzx rax, [Buf]
mov al, byte ptr[Tab + rax]
mov [Buf],al
inc Buf
dec Len
jnz @loop
{$ELSE }
test Len, Len
jz @exit
push ebx
@loop:
movzx ebx, [Buf]
mov bl,byte ptr[Tab + ebx]
mov [Buf], bl
inc Buf
dec Len
jnz @loop
pop ebx
{$ENDIF }
@exit:
end;
procedure _asm_HeartWare(Tab, Buf : PByte; Len : Cardinal);
// 32-bit EAX EDX ECX
// 64-bit RCX RDX R8
asm
{$IFDEF CPUX64 }
XCHG R8,RCX
JECXZ @OUT
XOR RAX,RAX
@LOOP:
MOV AL,[RDX]
MOV AL,[R8+RAX]
MOV [RDX],AL
INC RDX
DEC ECX
JNZ @LOOP
// LOOP @LOOP
{$ELSE }
JECXZ @OUT
PUSH EBX
XCHG EAX,EBX
XOR EAX,EAX
@LOOP:
MOV AL,[EDX+ECX-1]
MOV AL,[EBX+EAX]
MOV [EDX+ECX-1],AL
DEC ECX
JNZ @LOOP
// LOOP @LOOP
POP EBX
{$ENDIF }
@OUT:
end;
procedure _pas_normal(Tab, Buf: PByte; Len: Cardinal);
begin
while Len > 0 do begin
Buf^ := Tab[Buf^];
inc(Buf);
dec(Len);
end;
end;
procedure _pas_inline(Tab, Buf: PByte; Len: Cardinal); inline;
begin
while Len > 0 do begin
Buf^ := Tab[Buf^];
inc(Buf);
dec(Len);
end;
end;
var
Stopwatch: TStopwatch;
i: Integer;
x, y: array [0 .. 1023] of Byte;
procedure refresh;
begin
for i := low(x) to high(x) do
begin
x[i] := i mod 256;
y[i] := (i + 20) mod 256;
end;
end;
begin
{$IFDEF CPUX64 }
Writeln('64 bit mode');
{$ELSE }
Writeln('32 bit mode');
{$ENDIF }
refresh;
Stopwatch := TStopwatch.StartNew;
for i := 1 to 1000000 do
begin
_asm_HeartWare(PByte(@x), PByte(@y), SizeOf(x));
end;
Writeln('asm HeartWare : ', Stopwatch.ElapsedMilliseconds, 'ms');
refresh;
Stopwatch := TStopwatch.StartNew;
for i := 1 to 1000000 do
begin
_asm_GJ(PByte(@x), PByte(@y), SizeOf(x));
end;
Writeln('asm GJ : ', Stopwatch.ElapsedMilliseconds, 'ms');
refresh;
Stopwatch := TStopwatch.StartNew;
for i := 1 to 1000000 do
begin
_pas_normal(PByte(@x), PByte(@y), SizeOf(x));
end;
Writeln('pas normal : ', Stopwatch.ElapsedMilliseconds, 'ms');
refresh;
Stopwatch := TStopwatch.StartNew;
for i := 1 to 1000000 do
begin
_pas_inline(PByte(@x), PByte(@y), SizeOf(x));
end;
Writeln('pas inline : ', Stopwatch.ElapsedMilliseconds, 'ms');
Readln;
end.
结果...
包含...
几乎无话可说!数字说话...
Delphi编译器不错,嗯很好!
我已经测试了另一个 asm 优化程序,因为 HeartWare asm 优化不是真正的优化。