Binary GCD in Assembler
-
Nabend allerseits,
vorweg, hierbei handelt es sich nicht um x86-Assembler, sondern um einen
Assembler fuer eine CPU die selbst gebaut worden ist.Wir muessen mit Hilfe dieses Assemblers ein Programm schreiben, welches
2 Brueche addieren/subtrahieren + kuerzen kann. Und genau hier kommt der
binary gcd zum Einsatz.Das Problem:
Irgendwie laeuft es nicht richtig und ich brauch Hilfe von euch, den Fehler
zu finden :).Hier der Quellcode:
bgcd: st r0, #bgcd_u //get bgcd_u's address ld r0, (r0) //load bgcd_u (first value) st r1, #bgcd_v //get bgcd_v's address ld r1, (r1) //load bgcd_v (second value) //** now lets check whether one of them is zero //** if(r0 == 0 || r1 == 0) return v | u; jz #bgcd_zero, r0 jz #bgcd_zero, r1 //** let shift := lg K, where K is the greatest power of 2 //** deviding both u and v //** for (shift = 0; ((u | v) & 1) == 0; ++shift) { //** u >>= 1; //** v >>= 1; //** } st r2, #0 //shift counter st r3, #1 bgcd_for: or r4, r0, r1 //r4 = (u | v) and r4, r4, r3 //r4 & 1 (odd number)? jz #bgcd_for_end, r4 sar r0, r0 //r4 != 0 => r0 >>= 1; r1 >>= 1; sar r1, r1 add r2, r2, r3 //increase shift counter jmp #bgcd_for //** while ((u & 1) == 0) //** u >>= 1; bgcd_for_end: bgcd_while_u: and r4, r0, r3 jnz #bgcd_while_u_end, r4 sar r0, r0 jmp #bgcd_while_u bgcd_while_u_end: st r6, #0x8000 //** from here on, u is always odd //** do { bgcd_do: //** while ((v & 1) == 0) /* Loop X */ //** v >>= 1; bgcd_while_v: and r4, r1, r3 jnz #bgcd_while_v_end, r4 sar r1, r1 jmp #bgcd_while_v bgcd_while_v_end: //** now u and v are both odd, so diff(u, v) is even //** let u = min(u, v), v = diff(u, v)/2 //** if (u < v) { //** v -= u; //** } bgcd_if: //if(bgcd_u < bgcd_v) sub r4, r0, r1 jz #bgcd_else, r4 //zero means bgcd_u == bgcd_v and r4, r4, r6 jz #bgcd_else, r4 //zero means bgcd_u > bgcd_v sub r1, r1, r0 //bgcd_v -= bgcd_u jmp #bgcd_end_if //** else { //** int diff = u - v; //** u = v; //** v = diff; //** } bgcd_else: sub r4, r0, r1 //r4 = bgcd_u - bgcd_v st r0, r1 //bgcd_u = bgcd_v st r1, r4 //bgcd_v = r4 bgcd_end_if: //** v >>= 1; sar r1, r1 //** } while (v != 0); bgcd_do_while: jnz #bgcd_do, r1 //v != 0 => repeat loop st r5, r2 //** return u << shift; bgcd_while_shift: jz #bgcd_end, r2 //shift counter is zero sal r0, r0 //left shift bgcd_u sub r2, r2, r3 //decrease shift counter jmp #bgcd_while_shift //and repeat loop bgcd_end: st r6, #bgcd_result //get bgcd_result's address st (r6), r0 //save result //jmp r7 //and return halt bgcd_zero: st r2, #0 or r2, r0, r1 //if r0 == 0 result is r1 and vice versa st r3, #bgcd_result //get bgcd_result's address st (r3), r2 //save result //jmp r7 //and return halt //********************end bgcd****************************************** .org 0x00ff //bgcd vars .dw bgcd_u 30 .dw bgcd_v 10 .dw bgcd_result 0
Irgendwo muss der Wurm drinne sein. Ich bekomme folgende Werte (hex):
u | v | result -------------------------------- 30 10 5 (hier fehlt 1 linksshift zum korrekten Erg.) 5 5 2 (hmmm...hier passt gar nichts) 10 10 5 (hier fehlt 1 linksshift) 100 100 19 (hier fehlen 2 linksshifts)
Wo liegt mein Fehler?
gruss
v R[edit]
Quelle fuer den Source: http://en.wikipedia.org/wiki/Binary_GCD_algorithm
[/edit][edit2]
Auf dem Forentreffen haben Jester, Shade und ich einen Interpreter fuer den
Assemblierten Code geschrieben. Bei Interesse, kann ich euch den Assembler +
den Interpreter (fuer diesen auch den Source) zukommen lassen. Hab leider
keinen Webspace, deswegen kann ich das nur auf Anfrage zuschicken
[/edit2]
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum Rund um die Programmierung in das Forum Assembler verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Danke an schnitzl. Im Label bgcd_for: darf es nicht jz sondern muss jnz heissen.
gruss
v R