Delphi 10.2 32bit
VCL
Hi,
die u.g. Methode Increment8_PAS soll aus Performance-Gründen nach
ASM übersetzt werden.
Der erste Versuch Increment8_OLD hat irgendwie nicht gepasst und Zugriffsfehler produziert.
Mit der Version Increment8_NEW läuft das Programm und liefert auch korrekte Ergebnisse.
Da ich aber nicht wirklich gut in
ASM bin, wäre es nett, wenn ein Assembler-Profi sich das nochmal ansieht
Vor allem wie und in welchen Registern die Parameter übergeben werden ist mir nicht so klar.
Vielen Dank für eure Mühe
Delphi-Quellcode:
type
TWorker =
class
FCount:
array[0..7]
of UInt32;
procedure Increment8_PAS(
var Value; Add: UInt32);
procedure Increment8_OLD(
var Value; Add: UInt32);
procedure Increment8_NEW(
var Value; Add: UInt32);
:
end;
procedure TWorker.Increment8_PAS(
var Value; Add: UInt32);
type
TData =
packed array[0..7]
of UInt32;
var
HiBits: UInt32;
Add8: UInt32;
Carry: Boolean;
procedure AddC(
var Value: UInt32;
const Add: UInt32;
var Carry: Boolean);
begin
if Carry
then
begin
Value := Value + 1;
Carry := (Value = 0);
// we might cause another overflow by adding the carry bit
end
else
Carry := False;
Value := Value + Add;
Carry := Carry
or (Value < Add);
// set Carry Flag on overflow
end;
begin
HiBits := Add
shr 29;
// Save most significant 3 bits in case an overflow occurs
Add8 := Add * 8;
Carry := False;
AddC(TData(Value)[0], Add8, Carry);
AddC(TData(Value)[1], HiBits, Carry);
AddC(TData(Value)[2], 0, Carry);
AddC(TData(Value)[3], 0, Carry);
AddC(TData(Value)[4], 0, Carry);
AddC(TData(Value)[5], 0, Carry);
AddC(TData(Value)[6], 0, Carry);
AddC(TData(Value)[7], 0, Carry);
if Carry
then
RaiseOverflowError;
end;
procedure TWorker.Increment8_ASM_OLD(
var Value; Add: UInt32);
asm
MOV ECX,EDX
LEA EDX,[EDX * 8]
SHR ECX,29
ADD [EAX].DWord[ 0],EDX
ADC [EAX].DWord[ 4],ECX
ADC [EAX].DWord[ 8],0
ADC [EAX].DWord[12],0
ADC [EAX].DWord[16],0
ADC [EAX].DWord[20],0
ADC [EAX].DWord[24],0
ADC [EAX].DWord[28],0
JC RaiseOverflowError
end;
procedure TWorker.Increment8_ASM_NEW(
var Value; Add: UInt32);
asm
LEA EAX,[ECX*8]
SHR ECX,29
ADD [EDX].DWord[00],EAX
ADC [EDX].DWord[04],ECX
ADC [EDX].DWord[08],0
ADC [EDX].DWord[12],0
ADC [EDX].DWord[16],0
ADC [EDX].DWord[20],0
ADC [EDX].DWord[24],0
ADC [EDX].DWord[28],0
JC RaiseOverflowError
end;