|
Antwort |
Registriert seit: 13. Aug 2003 1.111 Beiträge |
#1
beim Übersetzen eines C Quelltextes tritt noch ein GleitkommadivisionsFehler auf...
Wissen die Assembler Profis mehr? Vielen Dank schonmal !!
Delphi-Quellcode:
type Var128 = packed record DW : array[0..3] of DWORD; end; function xMulDiv64(operant, multiplier, divider : int64) : int64; stdcall; var quotient : Var128; // // Declare 128bit storage // struct{ // unsigned long DW[4]; // }var128, quotient; // // Change semantics for intermediate results for Full Div // // by renaming the vars // #define REMAINDER quotient // #define QUOTIENT edi begin asm mov eax, dword ptr[operant+4] xor eax, dword ptr[multiplier+4] xor eax, dword ptr[divider+4] pushfd end; // Take absolute values because algorithm is for unsigned only operant := ABS(operant); multiplier := ABS(multiplier); divider := ABS(divider); asm // First check divider for 0 mov eax, dword ptr[divider+4] or eax, dword ptr[divider] jnz @@dividerOK div eax @@dividerOK: lea edi,[var128] // edi = &var128 // Check multiplier for 1 or 0 xor eax, eax cmp eax, dword ptr[multiplier+4] jnz @@startMUL cmp eax, dword ptr[multiplier] jnz @@multiNotNUL xor edx, edx popfd // cleanup stack jmp @@done @@multiNotNUL: // Set result HI part to 0 xor eax,eax mov dword ptr[edi+12], eax mov dword ptr[edi+8], eax mov eax, 1 cmp eax, dword ptr[multiplier] jnz @@smallMUL // Multiplier is 1 so just copy operant to result mov eax, dword ptr[operant+4] mov dword ptr[edi+4], eax mov eax, dword ptr[operant] mov dword ptr[edi], eax jmp @@startDIV @@smallMUL: // Test for 32/32 bit multiplication xor eax, eax mov ecx, dword ptr[operant+4] or ecx, eax //;test for both hiwords zero. jnz @@startMUL // Do 32/32 bit multiplication mov ecx, dword ptr[multiplier] mov eax, dword ptr[operant] mul ecx mov dword ptr[edi+4], edx mov dword ptr[edi], eax jmp @@startDIV @@startMUL: // Check signs // Multiply: var128 = operant * multiplier mov eax, dword ptr[multiplier] // eax = LO(multiplier) mul dword ptr[operant] // edx:eax = eax * LO(operant) mov dword ptr[edi], eax // var128.DW0 = eax mov ecx, edx // ecx = edx mov eax, dword ptr[multiplier] // eax = LO(multiplier) mul dword ptr[operant+4] // edx:eax = eax * HI(operant) add eax, ecx // eax = eax + ecx adc edx, 0 // edx = edx + 0 + carry mov ebx, eax mov ecx, edx mov eax, dword ptr[multiplier+4] mul dword ptr[operant] add eax, ebx mov dword ptr[edi+4], eax adc ecx, edx pushfd mov eax, dword ptr[multiplier+4] mul dword ptr[operant+4] popfd adc eax, ecx adc edx, 0 mov dword ptr[edi+8], eax mov dword ptr[edi+12], edx @@startDIV: // Divide: var128 = var128 / divider // // Test divider = 32bit value mov eax, dword ptr[divider+4] cmp eax, 0 jnz @@fullDIV mov ecx, dword ptr[divider] cmp ecx, 1 jz @@applySign // Start 128/32 bit division mov eax, dword ptr[edi+12] xor edx, edx div ecx mov dword ptr[quotient+12], eax mov eax, dword ptr[edi+8] div ecx mov dword ptr[quotient+8], eax mov eax, dword ptr[edi+4] div ecx mov dword ptr[quotient+4], eax mov eax, dword ptr[edi] div ecx mov dword ptr[quotient], eax // Copy the quotient to the result storage (var128) mov eax, dword ptr[quotient+12] mov dword ptr[edi+12], eax mov eax, dword ptr[quotient+8] mov dword ptr[edi+8], eax mov eax, dword ptr[quotient+4] mov dword ptr[edi+4], eax mov eax, dword ptr[quotient] mov dword ptr[edi], eax // To sign correction and return jmp @@applySign @@fullDIV: // Full 128/64 bit division xor eax, eax mov dword ptr[quotient+12], eax mov dword ptr[quotient+8], eax mov dword ptr[quotient+4], eax mov dword ptr[quotient], eax mov ecx, 128 @@loop1: // Compute REMAINDER:QUOTIENT = REMAINDER:QUOTIENT shl 1 shl dword ptr[edi], 1 rcl dword ptr[edi+4], 1 rcl dword ptr[edi+8], 1 rcl dword ptr[edi+12], 1 rcl dword ptr[quotient], 1 rcl dword ptr[quotient+4], 1 rcl dword ptr[quotient+8], 1 rcl dword ptr[quotient+12], 1 // Test (REMAINDER >= Divider) xor eax, eax cmp dword ptr[quotient+12], eax ja @@iftrue jb @@iffalse cmp dword ptr[quotient+8], eax ja @@iftrue jb @@iffalse mov eax, dword ptr[quotient+4] cmp eax, dword ptr[divider+4] ja @@iftrue jb @@iffalse mov eax, dword ptr[quotient] cmp eax, dword ptr[divider] jb @@iffalse @@iftrue: // Remainder = remainder - divider mov eax, dword ptr[divider] sub dword ptr[quotient], eax mov eax, dword ptr[divider+4] sbb dword ptr[quotient+4], eax xor eax, eax sbb dword ptr[quotient+8], eax sbb dword ptr[quotient+12], eax // Quotient = quotient +1 add dword ptr[edi], 1 adc dword ptr[edi+4], 0 adc dword ptr[edi+8], 0 adc dword ptr[edi+12], 0 @@iffalse: // Loop size = 101 bytes, is less than 127 so loop is possible loop @@loop1 @@applySign: // Correct the sign of the result based on the stored combined sign popfd jns @@storeRes not dword ptr[edi+12] not dword ptr[edi+ 8] not dword ptr[edi+ 4] not dword ptr[edi] add dword ptr[edi], 1 adc dword ptr[edi+ 4], 0 adc dword ptr[edi+ 8], 0 adc dword ptr[edi+12], 0 @@storeRES: // Get low order qword from var128 mov edx, dword ptr[edi+4] mov eax, dword ptr[edi] @@done: // result is returned in edx:eax END; end;
Delphi-Quellcode:
/*
* Source file: MulDiv64.cpp * Author: Richard van der Wal * Contact: [email]R.vdWal@xs4all.nl[/email] * * Description: * Implementation for MulDiv64 and MulShr64 * * $Log: $ */ /* * MulDiv64 * Multiplies an operant by a multiplier and divides the result by a divider * Used for scaling 64 bit integer values * Xscaled = Xstart * Multiplier / Divider * Uses 128 bit intermediate result */ #define ABS64(num) (num >=0 ? num : -num) // __int64 _stdcall MulDiv64(__int64 operant, __int64 multiplier, __int64 divider) { // Declare 128bit storage struct{ unsigned long DW[4]; }var128, quotient; // Change semantics for intermediate results for Full Div // by renaming the vars #define REMAINDER quotient #define QUOTIENT edi // Save combined sign on stack _asm{ mov eax, dword ptr[operant+4] xor eax, dword ptr[multiplier+4] xor eax, dword ptr[divider+4] pushfd } // Take absolute values because algorithm is for unsigned only operant = ABS64(operant); multiplier = ABS64(multiplier); divider = ABS64(divider); _asm{ // First check divider for 0 mov eax, dword ptr[divider+4] or eax, dword ptr[divider] jnz dividerOK div eax dividerOK: lea edi,[var128] // edi = &var128 // Check multiplier for 1 or 0 xor eax, eax cmp eax, dword ptr[multiplier+4] jnz startMUL cmp eax, dword ptr[multiplier] jnz multiNotNUL xor edx, edx popfd // cleanup stack jmp done multiNotNUL: // Set result HI part to 0 xor eax,eax mov dword ptr[edi+12], eax mov dword ptr[edi+8], eax mov eax, 1 cmp eax, dword ptr[multiplier] jnz smallMUL // Multiplier is 1 so just copy operant to result mov eax, dword ptr[operant+4] mov dword ptr[edi+4], eax mov eax, dword ptr[operant] mov dword ptr[edi], eax jmp startDIV smallMUL: // Test for 32/32 bit multiplication xor eax, eax mov ecx, dword ptr[operant+4] or ecx, eax ;test for both hiwords zero. jnz startMUL // Do 32/32 bit multiplication mov ecx, dword ptr[multiplier] mov eax, dword ptr[operant] mul ecx mov dword ptr[edi+4], edx mov dword ptr[edi], eax jmp startDIV startMUL: // Check signs // Multiply: var128 = operant * multiplier mov eax, dword ptr[multiplier] // eax = LO(multiplier) mul dword ptr[operant] // edx:eax = eax * LO(operant) mov dword ptr[edi], eax // var128.DW0 = eax mov ecx, edx // ecx = edx mov eax, dword ptr[multiplier] // eax = LO(multiplier) mul dword ptr[operant+4] // edx:eax = eax * HI(operant) add eax, ecx // eax = eax + ecx adc edx, 0 // edx = edx + 0 + carry mov ebx, eax mov ecx, edx mov eax, dword ptr[multiplier+4] mul dword ptr[operant] add eax, ebx mov dword ptr[edi+4], eax adc ecx, edx pushfd mov eax, dword ptr[multiplier+4] mul dword ptr[operant+4] popfd adc eax, ecx adc edx, 0 mov dword ptr[edi+8], eax mov dword ptr[edi+12], edx startDIV: // Divide: var128 = var128 / divider // // Test divider = 32bit value mov eax, dword ptr[divider+4] cmp eax, 0 jnz fullDIV mov ecx, dword ptr[divider] cmp ecx, 1 jz applySign // Start 128/32 bit division mov eax, dword ptr[edi+12] xor edx, edx div ecx mov dword ptr[quotient+12], eax mov eax, dword ptr[edi+8] div ecx mov dword ptr[quotient+8], eax mov eax, dword ptr[edi+4] div ecx mov dword ptr[quotient+4], eax mov eax, dword ptr[edi] div ecx mov dword ptr[quotient], eax // Copy the quotient to the result storage (var128) mov eax, dword ptr[quotient+12] mov dword ptr[edi+12], eax mov eax, dword ptr[quotient+8] mov dword ptr[edi+8], eax mov eax, dword ptr[quotient+4] mov dword ptr[edi+4], eax mov eax, dword ptr[quotient] mov dword ptr[edi], eax // To sign correction and return jmp applySign fullDIV: // Full 128/64 bit division xor eax, eax mov dword ptr[REMAINDER+12], eax mov dword ptr[REMAINDER+8], eax mov dword ptr[REMAINDER+4], eax mov dword ptr[REMAINDER], eax mov ecx, 128 loop1: // Compute REMAINDER:QUOTIENT = REMAINDER:QUOTIENT shl 1 shl dword ptr[QUOTIENT], 1 rcl dword ptr[QUOTIENT+4], 1 rcl dword ptr[QUOTIENT+8], 1 rcl dword ptr[QUOTIENT+12], 1 rcl dword ptr[REMAINDER], 1 rcl dword ptr[REMAINDER+4], 1 rcl dword ptr[REMAINDER+8], 1 rcl dword ptr[REMAINDER+12], 1 // Test (REMAINDER >= Divider) xor eax, eax cmp dword ptr[REMAINDER+12], eax ja iftrue jb iffalse cmp dword ptr[REMAINDER+8], eax ja iftrue jb iffalse mov eax, dword ptr[REMAINDER+4] cmp eax, dword ptr[divider+4] ja iftrue jb iffalse mov eax, dword ptr[REMAINDER] cmp eax, dword ptr[divider] jb iffalse iftrue: // Remainder = remainder - divider mov eax, dword ptr[divider] sub dword ptr[REMAINDER], eax mov eax, dword ptr[divider+4] sbb dword ptr[REMAINDER+4], eax xor eax, eax sbb dword ptr[REMAINDER+8], eax sbb dword ptr[REMAINDER+12], eax // Quotient = quotient +1 add dword ptr[QUOTIENT], 1 adc dword ptr[QUOTIENT+4], 0 adc dword ptr[QUOTIENT+8], 0 adc dword ptr[QUOTIENT+12], 0 iffalse: // Loop size = 101 bytes, is less than 127 so loop is possible loop loop1 applySign: // Correct the sign of the result based on the stored combined sign popfd jns storeRes not dword ptr[edi+12] not dword ptr[edi+ 8] not dword ptr[edi+ 4] not dword ptr[edi] add dword ptr[edi], 1 adc dword ptr[edi+ 4], 0 adc dword ptr[edi+ 8], 0 adc dword ptr[edi+12], 0 storeRES: // Get low order qword from var128 mov edx, dword ptr[edi+4] mov eax, dword ptr[edi] done: } // result is returned in edx:eax }
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
|
Zitat |
Registriert seit: 13. Aug 2003 1.111 Beiträge |
#2
hmm .. weiss wirklich niemand, wie man den C ASM Quelltext nach Delphi übersetzt? .. hmmmm
*nochmal hochschieb*
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
|
Zitat |
Registriert seit: 6. Dez 2005 999 Beiträge |
#3
Interessant das diese Zeile ohne Fehler übersetzt wird, var128 ist ein type!
lea edi,[var128] // edi = &var128 Im C-Code gibt es zwei 128-Bit-Variable. Also mal versuchen mit
Delphi-Quellcode:
Im übrigen halte ich es für ziemlich gefährlich. mit den Flags auf dem Stack zu jonglieren.
type TVar128 = packed record
DW : array[0..3] of DWORD; end; ... var var128, quotient: TVar128; Gruß Gammatester |
Zitat |
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.033 Beiträge Delphi 12 Athens |
#4
erster Versuch,
!! hab irgendwie CombinedSign vergessen einzusetzen, also da wo es verwendet wird(werden sollte) (hab es nicht selber auf den Stack kopiert) nja, für den Anfang ... wenn ich nochmal etwas Zeit hab, schau ich wieder rein, aber eventuell findet ja noch wer "den" Fehler.
Delphi-Quellcode:
// Source file: MulDiv64.cpp
// Author: Richard van der Wal // Contact: [email]R.vdWal@xs4all.nl[/email] // // Description: Implementation for MulDiv64 and MulShr64 // // $Log: $ // Multiplies an operant by a multiplier and divides the result by a divider // Used for scaling 64 bit integer values // Xscaled = Xstart * Multiplier / Divider // Uses 128 bit intermediate result Function MulDiv64(Operant, Multiplier, Divider: Int64): Int64; StdCall; Type TVar128 = Array[0..3] of LongWord; Var Remainder, Quotient: TVar128; CombinedSign: LongWord; Begin // Save combined sign CombinedSign := Int64Rec(Operant).Hi xor Int64Rec(Multiplier).Hi xor Int64Rec(Divider).Hi; // Take absolute values because algorithm is for unsigned only If Operant < 0 Then Operant := -Operant; If Multiplier < 0 Then Multiplier := -Multiplier; If Divider < 0 Then Divider := -Divider; ASM // First check Divider for 0 MOV EAX, DWORD PTR [&Divider+4] OR EAX, DWORD PTR [&Divider+0] JNZ @DividerOK DIV EAX @DividerOK: LEA EDI, [&Quotient] // EDI := @Quotient // Check multiplier for 1 or 0 XOR EAX, EAX CMP EAX, DWORD PTR [&Multiplier+4] JNZ @StartMUL CMP EAX, DWORD PTR [&Multiplier+0] JNZ @MultiNotNUL XOR EDX, EDX JMP @Done @MultiNotNUL: // Set result HI part to 0 XOR EAX, EAX MOV DWORD PTR [EDI+12], EAX MOV DWORD PTR [EDI+ 8], EAX MOV EAX, 1 CMP EAX, DWORD PTR [&Multiplier+0] JNZ @SmallMUL // Multiplier is 1 so just copy operant to result MOV EAX, DWORD PTR [&Operant+4] MOV DWORD PTR [EDI+4], EAX MOV EAX, DWORD PTR [&Operant+0] MOV DWORD PTR [EDI+0], EAX JMP @StartDIV @SmallMUL: // Test for 32/32 bit multiplication XOR EAX, EAX MOV ECX, DWORD PTR [&Operant+4] OR ECX, EAX // test for both hiwords zero. JNZ @StartMUL // Do 32/32 bit multiplication MOV ECX, DWORD PTR [&Multiplier+0] MOV EAX, DWORD PTR [&Operant+0] MUL ECX MOV DWORD PTR [EDI+4], EDX MOV DWORD PTR [EDI+0], EAX JMP @StartDIV @StartMUL: // Check signs // Multiply: Quotient = operant * multiplier MOV EAX, DWORD PTR [&Multiplier+0] // EAX = LO(multiplier) MUL DWORD PTR [&Operant+0] // EDX:EAX = EAX * LO(operant) MOV DWORD PTR [EDI+0], EAX // Quotient[0] = EAX MOV ECX, EDX // ECX = EDX MOV EAX, DWORD PTR [&Multiplier+0] // EAX = LO(multiplier) MUL DWORD PTR [&Operant+4] // EDX:EAX = EAX * HI(operant) ADD EAX, ECX // EAX = EAX + ECX ADC EDX, 0 // EDX = EDX + 0 + carry MOV EBX, EAX MOV ECX, EDX MOV EAX, DWORD PTR [&Multiplier+4] MUL DWORD PTR [&Operant+0] ADD EAX, EBX MOV DWORD PTR [EDI+4], EAX ADC ECX, EDX pushfd MOV EAX, DWORD PTR [&Multiplier+4] MUL DWORD PTR [&Operant+4] popfd ADC EAX, ECX ADC EDX, 0 MOV DWORD PTR [EDI+ 8], EAX MOV DWORD PTR [EDI+12], EDX @StartDIV: // Divide: Quotient = Quotient / Divider // // Test Divider = 32bit value MOV EAX, DWORD PTR [&Divider+4] CMP EAX, 0 JNZ @FullDIV MOV ECX, DWORD PTR [&Divider+0] CMP ECX, 1 JZ @ApplySign // Start 128/32 bit division MOV EAX, DWORD PTR [EDI+12] XOR EDX, EDX DIV ECX MOV DWORD PTR [EDI+12], EAX MOV EAX, DWORD PTR [EDI+8] DIV ECX MOV DWORD PTR [EDI+8], EAX MOV EAX, DWORD PTR [EDI+4] DIV ECX MOV DWORD PTR [EDI+4], EAX MOV EAX, DWORD PTR [EDI+0] DIV ECX MOV DWORD PTR [EDI+0], EAX // Copy the Quotient to the result storage MOV EAX, DWORD PTR [EDI+12] MOV DWORD PTR [EDI+12], EAX MOV EAX, DWORD PTR [EDI+ 8] MOV DWORD PTR [EDI+ 8], EAX MOV EAX, DWORD PTR [EDI+ 4] MOV DWORD PTR [EDI+ 4], EAX MOV EAX, DWORD PTR [EDI+ 0] MOV DWORD PTR [EDI+ 0], EAX // To sign correction and return JMP @ApplySign @FullDIV: // Full 128/64 bit division XOR EAX, EAX MOV DWORD PTR [&Remainder+12], EAX MOV DWORD PTR [&Remainder+ 8], EAX MOV DWORD PTR [&Remainder+ 4], EAX MOV DWORD PTR [&Remainder+ 0], EAX MOV ECX, 128 @Loop1: // Compute Remainder:Quotient = Remainder:QUOTIENT shl 1 SHL DWORD PTR [EDI+ 0], 1 RCL DWORD PTR [EDI+ 4], 1 RCL DWORD PTR [EDI+ 8], 1 RCL DWORD PTR [EDI+12], 1 RCL DWORD PTR [&Remainder+ 0], 1 RCL DWORD PTR [&Remainder+ 4], 1 RCL DWORD PTR [&Remainder+ 8], 1 RCL DWORD PTR [&Remainder+12], 1 // Test (Remainder >= Divider) XOR EAX, EAX CMP DWORD PTR [&Remainder+12], EAX JA @IfTrue JB @IfFalse CMP DWORD PTR [&Remainder+ 8], EAX JA @IfTrue JB @IfFalse MOV EAX, DWORD PTR [&Remainder+ 4] CMP EAX, DWORD PTR [&Divider+4] JA @IfTrue JB @IfFalse MOV EAX, DWORD PTR [&Remainder+ 0] CMP EAX, DWORD PTR [&Divider+0] JB @IfFalse @IfTrue: // Remainder = Remainder - Divider MOV EAX, DWORD PTR [&Divider+0] SUB DWORD PTR [&Remainder+ 0], EAX MOV EAX, DWORD PTR [&Divider+4] SBB DWORD PTR [&Remainder+ 4], EAX XOR EAX, EAX SBB DWORD PTR [&Remainder+ 8], EAX SBB DWORD PTR [&Remainder+12], EAX // Quotient = Quotient +1 ADD DWORD PTR [EDI+ 0], 1 ADC DWORD PTR [EDI+ 4], 0 ADC DWORD PTR [EDI+ 8], 0 ADC DWORD PTR [EDI+12], 0 @IfFalse: // Loop size = 101 bytes, is less than 127 so loop is possible LOOP @Loop1 @ApplySign: // Correct the sign of the result based on the stored combined sign JNS @StoreRes NOT DWORD PTR [EDI+12] NOT DWORD PTR [EDI+ 8] NOT DWORD PTR [EDI+ 4] NOT DWORD PTR [EDI+ 0] ADD DWORD PTR [EDI+ 0], 1 ADC DWORD PTR [EDI+ 4], 0 ADC DWORD PTR [EDI+ 8], 0 ADC DWORD PTR [EDI+12], 0 @StoreRes: // Get low order qword from Quotient MOV EDX, DWORD PTR [EDI+4] MOV DWORD PTR [&Result+4], EAX MOV EAX, DWORD PTR [EDI+0] MOV DWORD PTR [&Result+0], EAX @Done: End; End;
Zitat:
Interessant das diese Zeile ohne Fehler übersetzt wird, var128 ist ein type!
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests |
Zitat |
Registriert seit: 13. Aug 2003 1.111 Beiträge |
#5
Hi Himitsu !
hab vielen Dank für Deine Hilfe. Läuft zwar jetzt ohne Abstürze, aber rechnet total falsch... irgendwie scheint der OriginalCode falsch zu sein ...
Delphi-Quellcode:
´
i2 := 6000000;
i3 := 5266; i4 := 5266; i := MulDiv64(i2, i3, i4); da kommt irgendwie 25769803782000000 raus .. hmmm ... naja ... trotzdem vielen Dank für Deine Mühe !!
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
|
Zitat |
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.033 Beiträge Delphi 12 Athens |
#6
hmmm
wie gesagt, ein paar Fehler sind bei mir auf jedenfall noch drin, vorallem da ich wohl irgendwie vergessen hab das Vorzeichen wieder einzurechnen hat denn schonmal wer versucht den Originalcode in einem C-Programm laufen zu lassen? Wenn nicht, vielleicht findet sich hier ja noch wer, der die Möglichkeit dazu hat ^^
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |