![]() |
Division (Bit-Shifting) in ASSEMBLER
Hallo zusammen,
AUFGABENSTELLUNG: In folgenden 2 Beispielen (ASM) werden die Doppelworte <VARIABLE> dividiert; im Beispiel I durch den Wert 16 und im Beispiel II durch den Wert 512. Der Quotient soll jeweils in den Akkumulator geschoben werden. PROBLEM: Die Anweisungen im Einzelnen sind mir klar (habe meine Kommentare dahinter geschrieben), doch ich verstehe absolut nicht, WARUM dieses Schema funktioniert und WIE es (mathematisch) funktioniert. In den beiden Beispielen kann ich jeweils die Schritte 1 bis 4 leicht nachvollziehen, denn die Divisionen erfolgen hier durch das binäre Schieben der notwendigen Stellen nach rechts. Ab Schritt 5 verstehe ich NIX mehr. Ich kann weder das AND (in Beispiel I) deuten, noch das nach LINKS (!) Schieben. Wäre Euch sehr dankbar, wenn ihr mir bei diesem kleinen Problem helfen könntet.
Code:
BEISPIEL NUMERO I: DIVISION DURCH 16
VARIABLE DD (?) ; 32 BIT <ANWEISUNGEN> 1) MOV AX, WORD PTR [VARIABLE] ; LOW-WORD [VARIABLE] IN AX 2) MOV CL, 4 ; CL = 4 3) SHR AX, CL ; AX = AX DIV 16 4) MOV BX, WORD PTR [VARIABLE+2] ; HIGH-WORD [VARIABLE] IN BX 5) AND BL, 0FH ; BX AND 15 6) MOV CL, 4 ; CL = 4 7) SHL BL, CL ; BL = BL * 16 8) ADD AH, BL ; AH = AH + BL
Code:
BEISPIEL NUMERO II: DIVISION DURCH 512
VARIABLE DD (?); 32 BIT <ANWEISUNGEN> 1) MOV AX, WORD PTR [VARIABLE] ; LOW-WORD [VARIABLE] IN AX 2) MOV CL, 9 ; CL = 9 3) SHR AX, CL ; AX = AX DIV 512 4) MOV DX, WORD PTR [VARIABLE+2] ; HIGH-WORD [VARIABLE] IN DX 5) MOV CL, 7 ; CL = 7 6) SHL DX, CL ; DX = DX * 128 7) ADD AX, DX ; AX = AX + DX |
Re: Division (Bit-Shifting) in ASSEMBLER
Die Zahlen werden doch Binär gespeichert. (z.B. 01010100 = 84)
Wenn du jetzt die Bits verschiebst, dann entsteht ja ein anderer Wert. Da da die Binärwerte ja eine Potenz von 2 sind, kannst du als mit 2er-Potenzen multiplizieren und dividiern. (*2, *4, *8 ... | /2, /4 ...) Wenn also die Bit z.B. um 3 Stellen nach links geschogen werden, so wird also die Zahl darin mit 2^3 multipliziert. <<< mal 8 (2^3) 00000000 01010100 = 84 00000010 10100000 = 672 >>> durch 8 (2^3) 00000000 01010100 = 84 00000000 00001010 = 10 (10,5 - dabei wird abgerundet) |
Re: Division (Bit-Shifting) in ASSEMBLER
@himitsu:
Erst mal danke für Deine Antwort. Mir sind die Befehle im Einzelnen klar und ich weiss bereits, wie Multiplikationen und Divisionen mittels Shifting funktionieren. Das mit dem Nach-Rechts-Schieben des LOW-WORDs ist mir auch klar. Was ich nicht nachvollziehen kann, sind die Operationen mit den jeweiligen HIGH-WORDs in meinen eigenen Beispielen. |
Re: Division (Bit-Shifting) in ASSEMBLER
Da kann ich dir jetzt auch nicht weiterhelfen.
Hab seit Jahren nichts mehr mit ASM gemacht und die Unterlagen verstauben irgendwo im Keller |
Re: Division (Bit-Shifting) in ASSEMBLER
Egal, trotzdem danke.
Falls jemand dieses Schema kennt, immer her damit. :gruebel: |
Re: Division (Bit-Shifting) in ASSEMBLER
Ist das dein Code? Dann solltest du eigentlich wissen, was du da verzapft hast :mrgreen:
Zuerst: Seit 10 Jahren gibt es das Register EAX, sind schon 32 bit, dann sparst du dir das aufsplitten des Wertes auf AX und BX. So, dann mal zu deinem bisschen Code: Variante I ist keine echte 32bit-Division. Du schnappst dir die ersten 16 bits und dividierst sie korrekt durch 4 durch einen schnellen leftshift. So, das bedeutet ja, daß die untersten 4 bits rausgefallen sind und die oberen 4 bits durch Nullbits ersetzt wurden, du hast jetzt in AX also eine 12bit-Zahl. Dann schnappst du dir das höherwertige Word der Variable in BX, beachtest aber nur BL, dadurch ignorierst du die oberen 16 bits, du hast also nur ein Byte. Wir haben uns gemerkt, in AX sind die oberen 4 bits noch "frei", also suchst du dir aus BL die unteren 4 (0x0F), die oberen 4 werden auf 0 gesetzt (da du ja nach links shiftest, ist das AND eigentlich überflüssig). Jetzt shiftest du sie nach links, in BL stehen jetzt also in den Bits 0-3 (von rechts!!) lauter Nullen und in den Bits 4-7 die untersten 4 bits des High Words der Variable. Um diese 4 Bits in AH zu verfrachten, wo wir ja noch 4 "freie" Bits haben, führst du ein ADD aus (gleichbedeutend mit OR). Insgesamt hast du also die unteren 16+4=20 Bits der Variable genommen, die unteren 4 weggeschnippelt und aufrücken lassen, eine 20bit-Division durch 16. In Beispiel II sieht's genauso aus: Du teilst das Low-Word ganz normal. Da 512 binär 1000000000 (9 Nullen) ist, hast du jetzt in AX die oberen 9 Bits "frei". 16-9=7, also brauchst du noch die unteren 7 Bits des High-Words. Diese besorgst du dir, indem du (dismal das komplette Register, nicht nur das Low-Byte) um 7 nach links verschiebst und anschließend mit AX ein ADD (OR) ausführst. Du hast hier also auch keine 32bit-Division, sondern eine 16+7=23bit-Division durch 512. Aber wie gesagt, 32bit-Berechnungen musst du bei den Intel-Architekturen seit 10 Jahren (genauer: seit i486, bzw IA32) nicht mehr aufsplitten. Und DIV und MUL gibt's auch schon seit 'ner ganzen Weile ;-) Edit: 1. Links und Rechts korrigiert (Hey, ich Gymnasiast, ich muss nicht wissen was links und rechts ist). 2. Satz hinzugefügt. |
Re: Division (Bit-Shifting) in ASSEMBLER
Aaaaaaah, o.k., hab's gerafft.
Ich habe diesen Code nicht geschrieben, sondern ich sollte ihn jemanden erklären, aber irgendwie wusste ich bei den obigen Auszügen nicht genau, was sich der Autor dabei Krankes gedacht hat. Danke, danke, danke vielmals. :thuimb: :thuimb: :thuimb: |
Re: Division (Bit-Shifting) in ASSEMBLER
Bitte, bitte, bitte, gern geschehen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz