AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Division großer Zahlen in Assembler - Hilfe beim Verständnis
Thema durchsuchen
Ansicht
Themen-Optionen

Division großer Zahlen in Assembler - Hilfe beim Verständnis

Ein Thema von AlphaBug · begonnen am 29. Okt 2004
Antwort Antwort
AlphaBug

Registriert seit: 2. Mär 2004
Ort: hinterm Transistor 246 gleich links
46 Beiträge
 
Delphi 6 Enterprise
 
#1

Division großer Zahlen in Assembler - Hilfe beim Verständnis

  Alt 29. Okt 2004, 11:38
Hi

Kann man mir bitte mal Teile des nachfolgenden Assembler-Code (auch gerne den Ganzen) aus der System.pas erklären ?

Es ist ja soweit ersichtlich, dass dort eine Division zweier 64-Bit-Integer durchgeführt wird, aber ich verstehe den Sinn einiger Befehlsfolgen nicht.
Ich habe zwar eine komplette Referenz aller (Intel-)Assembler-Befehle mit Erklärungen, an deren Verständnis es nicht hakt, aber Ich bin kein Assembler-Profi und kein Mathematik-Spezi.
Die Prozedur "__lldiv" ist ja eine Software-Umsetzung für Divisionen von 64-Bit-Integern auf 32-Bit-CPUs. Demnach müsste sie sich ja auf größere Zahlen erweitern lassen. Natürlich müssten die Zahlen dann in einem Array gespeichert werden (imho), z.B. einem array [0..3] of DWORD für 128-Bit-Zahlen.

Also bei mir hapert es jetzt an drei Stellen:
1. am Verständnis einiger Assembler-Befehle
2. am Verständnis einiger Assembler-Befehlsfolgen
3. an der Erweiterung auf größere Zahlen in Array-Form

Ich suche also nach einer allgemeinen Erklärung des Ablaufs dieser Prozedur,
und, wenn dann noch nötig, nach Hilfe für eine Erweiterung.
Ich suche NICHT nach einer Bibliothek, die mir das Lernen abnimmt.
Ich hoffe, man kann mir weiterhelfen:

1.:
Was sagt mit diese Zeile:
        mov ebx,20[esp] Ich kenne nur solche Befehle:
Delphi-Quellcode:
        mov ebp,ecx
        mov ecx,64
2:
Warum werden hier die Register edx, esi und edi um 1 über das Carry hinweg rotiert:
Delphi-Quellcode:
@__lldiv@xloop:
        shl eax,1
        rcl edx,1
        rcl esi,1
        rcl edi,1
Das waren wahrscheinlich nur die ersten Fragen...

Delphi-Quellcode:
// ------------------------------------------------------------------------------
// 64-bit signed division
// ------------------------------------------------------------------------------

//
// Dividend = Numerator, Divisor = Denominator
//
// Dividend(EAX:EDX), Divisor([ESP+8]:[ESP+4]) ; before reg pushing
//
//

procedure __lldiv;
asm
        push ebp
        push ebx
        push esi
        push edi
        xor edi,edi

        mov ebx,20[esp] // get the divisor low dword
        mov ecx,24[esp] // get the divisor high dword

        or ecx,ecx
        jnz @__lldiv@slow_ldiv // both high words are zero

        or edx,edx
        jz @__lldiv@quick_ldiv

        or ebx,ebx
        jz @__lldiv@quick_ldiv // if ecx:ebx == 0 force a zero divide
        // we don't expect this to actually
        // work

@__lldiv@slow_ldiv:
// Signed division should be done. Convert negative
// values to positive and do an unsigned division.
// Store the sign value in the next higher bit of
// di (test mask of 4). Thus when we are done, testing
// that bit will determine the sign of the result.
        or edx,edx // test sign of dividend
        jns @__lldiv@onepos
        neg edx
        neg eax
        sbb edx,0 // negate dividend
        or edi,1

@__lldiv@onepos:
        or ecx,ecx // test sign of divisor
        jns @__lldiv@positive
        neg ecx
        neg ebx
        sbb ecx,0 // negate divisor
        xor edi,1

@__lldiv@positive:
        mov ebp,ecx
        mov ecx,64 // shift counter
        push edi // save the flags
//
// Now the stack looks something like this:
//
// 24[esp]: divisor (high dword)
// 20[esp]: divisor (low dword)
// 16[esp]: return EIP
// 12[esp]: previous EBP
// 8[esp]: previous EBX
// 4[esp]: previous ESI
// [esp]: previous EDI
//
        xor edi,edi // fake a 64 bit dividend
        xor esi,esi

@__lldiv@xloop:
        shl eax,1 // shift dividend left one bit
        rcl edx,1
        rcl esi,1
        rcl edi,1
        cmp edi,ebp // dividend larger?
        jb @__lldiv@nosub
        ja @__lldiv@subtract
        cmp esi,ebx // maybe
        jb @__lldiv@nosub

@__lldiv@subtract:
        sub esi,ebx
        sbb edi,ebp // subtract the divisor
        inc eax // build quotient

@__lldiv@nosub:
        loop @__lldiv@xloop
//
// When done with the loop the four registers values' look like:
//
// | edi | esi | edx | eax |
// | remainder | quotient |
//
        pop ebx // get control bits
        test ebx,1 // needs negative
        jz @__lldiv@finish
        neg edx
        neg eax
        sbb edx,0 // negate

@__lldiv@finish:
        pop edi
        pop esi
        pop ebx
        pop ebp
        ret 8

@__lldiv@quick_ldiv:
        div ebx // unsigned divide
        xor edx,edx
        jmp @__lldiv@finish
end;
Delphi 4ever !
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es 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

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz