2 Byte und 1 Byte addieren



  • Hallo,
    in der Schule machen wir jetzt "Low-Level"-Programmierung, um uns auf Assembler vorzubereiten. Die Beschränkunen sind unter anderem: Zeilenorientierung, nur Shortint (= signed char) als Datentyp, keine Funktionen.
    Aufgabe ist nun ein einfaches Fakultät-Programm zu schreiben.

    Code: http://pastebin.com/UzDgAcrg

    Blöd ist nur, dass die Resultate für Eingabe > 5 zu hoch sind.
    Meine Idee war, "result" in "result1" und "result128" aufzuteilen, wobei das Gesamtergebnis dann ist:
    result1 * 128 + result128

    Daraus folgt dann das nächste Problem, dass ich keine Multiplikation mehr anwenden kann. Das könnte ich durch eine for-Schleife mit mehreren Addition ersetzen. (5*5 = 5+5+5+5+5)

    Und hier komme ich dann zu dem Punkt, an dem ich nicht mehr weiter weiß: Wie soll ich die Variablen addieren?



  • na iterativ, wie sonst? 😡



  • Wurstinator schrieb:

    Daraus folgt dann das nächste Problem, dass ich keine Multiplikation mehr anwenden kann. Das könnte ich durch eine for-Schleife mit mehreren Addition ersetzen. (5*5 = 5+5+5+5+5)

    Und hier komme ich dann zu dem Punkt, an dem ich nicht mehr weiter weiß: Wie soll ich die Variablen addieren?

    Hast du in der Schule nicht "mit Hand" multiplizieren gelernt? Doch? Gut. Genau so kannst du das im Combudda auch machen.
    Ist wesentlich effizienter als 5+5+5+5+5.

    Und... "short int" hat üblicherweise >= 16 Bit.
    Mir ist zumindest bislang kein System untergekommen wo "short int" weniger als 16 Bit gehabt hätte.



  • @ husbaer: Nun, bei uns hat es eben nur 8 Bit.

    "Mit Hand" multiplizieren... wenn ich mich richtig erinnere, geht das so:
    321 * 44 = 1*44*1 + 2*44*10 + 3*44*100 = 44 + 880 + 13200 = 14124

    In meinem geplanten Code wäre das:
    input = 44
    result1 = 65
    result128 = 2

    Und wie soll ich mit dieser Technik hier multiplizieren?



  • Und warum 128?
    Bei 8 Bit kommen 256 zusammen.



  • Wie gesagt, es ist Signed.



  • Das betrifft aber nur das MSB.



  • Wurstinator schrieb:

    @ husbaer: Nun, bei uns hat es eben nur 8 Bit.

    Sehr seltsam.

    "Mit Hand" multiplizieren... wenn ich mich richtig erinnere, geht das so:
    321 * 44 = 1*44*1 + 2*44*10 + 3*44*100 = 44 + 880 + 13200 = 14124

    ...

    Und wie soll ich mit dieser Technik hier multiplizieren?

    Naja, Beispiel 2*44*10.
    10 ist bloss ne Stellenverschiebung.
    Und 2
    44 kannst du weiter unterteilen.
    Das ist 2*4*1 + 2*4*10.
    Jetzt hast du ein Verfahren wo du bloss noch folgendes können musst:
    * Einstellige Zahlen multiplizieren
    * Zweistellige Resultate (4*4 = 16) in zwei einzelne Stellen aufteilen (16 -> 1 6)
    * N-stellige Zahlen um eine fixe Anzahl von Stellen verschieben
    * N-stellige Zahlen addieren

    Alles relativ einfache Punkte. Der Zusammenbau zu einem fertigen Multiplizierprogramm ist nicht mehr ganz einfach, aber durchaus noch hinzubekommen.

    Achja...

    Als Stellenwertigkeit kannst du dabei 10 nehmen, dann nennt man das ganze Spiel BCD (Binary Coded Decimals). Oder du nimmst 8 (2^3). Dann wird das Zerlegen in einzelne Stellen einfacher (Shift statt Division/Modulo). Dafür müsstest du bei der Eingabe/Ausgabe jedes mal umrechnen.
    16 geht leider nimmer vernünftig, denn 15*15 ist 225, und 225 passt nimmer in dein "signed byte".
    Ich würde vermutlich wirklich 10 nehmen, also BCD.

    Was bei der Aufgabe allerdings gewaltig nervt, ist dass Funktionen verboten sind. Natürlich kann man das alles ohne Funktionen schreiben, aber es ist bäh. Wenn ich das machen müsste, würde ich den Code erstmal ganz normal mit Funktionen runterschreiben (aber halt ohne Rekursionen), und dann die Funktionsaufrufe mit Hand "inlinen". Trotzdem immer noch extrem bäh.



  • DirkB schrieb:

    Das betrifft aber nur das MSB.

    Hä?
    8 Bit signed mit two's complement hat nen Wertebereich von -128 bis +127.
    Soweit hat der OP schon Recht.



  • Ein Assembler sollte multiplizieren können. So sellten braucht man das ja nicht...

    Ansonsten würde ich die Multiplikation einfach so implementieren:

    int x = 3, y = 4, r = 0;
    lbl: r += x; --y; if (y) goto lbl;
    

    Funktioniert aber nur für y > 0.

    Übrigens kannst du dir trotzdem Funktionen machen: einfach ein Stück Code mit Label versehen und dort hinspringen. Nur der Rücksprung wird etwas schwierig, es sei denn man kann mit goto auch an eine Adresse statt an ein Label springen.



  • @ husbaer: Danke für die ausführliche Antwort, aber ich kann mir trotzdem noch nicht vorstellen, wie du das meinst.

    Abgesehen davon ist "N-stellige Zahlen addieren" ja wieder das Anfangsproblem.
    Ich hatte diese Idee: http://pastebin.com/4AgeGjmY
    Natürlich müsste ich es dann eben, wie du gesagt hast, noch "inlinen".
    Klappt das so oder habe ich einen Denkfehler?

    @ Asm_Pr0gger: Klar bietet er Multiplikation an, aber nur für einzelne Bytes.



  • Dein Code sollte so funktionieren.

    Nur wie willst du damit z.B. 30*30 multiplizieren? Selbst wenn die CPU ein Carry- bzw. Overflow-Flag hat, reicht das nur für ein zusätzliches Bit, und für 900 (30*30) brauchst du halt 10 Bit.

    Oder kann die CPU zwei 8 Bit zahlen multiplizieren, und als Ergebnis eine 16 Bit Zahl (aufgeteilt in zwei 8-Bit Zahlen) ausspucken?



  • Habs geschafft 😃
    http://pastebin.com/ZXurynZu
    Ich erwarte nicht, dass sich jemand den Code durchliest 😉

    @ hustbaer: 30*30 = 30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30+30 = for-Schleife

    Oder verstehe ich dich falsch?



  • Ja, du verstehst mich falsch.
    30*30 = 0*0*1 + 3*0*10 + 3*0*10 + 3*3*100


Anmelden zum Antworten