2 Zahlen Addieren



  • Hallo ich versuche gerade mit TASM 2 Zahlen zu Addieren

    Aber jetzt komme ich nicht weiter.

    Das Ergebniss aus 7+3 ist ja 10 diese 10 wird in bh gespeichert.
    Aber wie kann ich nun bh ausgeben ?

    Ich weiss nur wie ich z.b. aus Variablen mit

    mov ah,9h
    

    Text ausgeben kann aber wie das hier jetzt funktioniert hab ich leider kein Plan.

    .model small
    .stack 100h
    .data
    
    .code
    entrypoint:
    
            mov ah,7
            mov bh,3
    
            add bh,ah
    
    end entrypoint
    end
    


  • Deine Frage ist ja reichlich wage formuliert. Also mal sehen:
    Du benutzt wahrscheinlich (Borland) TASM, fuer den PC, um 16Bit RM DOS-Programme zu schreiben. Du weisst scheinbar, wie man "$"-Terminierte Strings mit Hilfe der DOS-Funktion 09 (ah=09h, int 21h) ausgibt. Nun willst du wissen, wie du eine vorzeichenlose Integer-Zahl in einen lesbaren String mit Ziffern umwandeln kannst, um sie mit zuvor genannter Funktion auf dem Schirm ausgeben zu koennen?

    int->string:
    Das Prinzip ist eigentlich immer das Gleiche, egal, welche Zahlenbasis (binaer, oct, dec, hex...) du verwenden willst:
    Dividiere deine Zahl wiederholt so lange durch die Basis (zB. 10 fuer dezimal), bis der Quotient 0 wird.
    Der x86-Befehl "div" fuehrt eine Division von ax, ax:dx oder eax:edx durch den Operanden, den Divisor durch (je nachdem, ob dieser 8, 16 oder 32Bit breit ist) und speichert den Quotient in ax (al, ax oder eax) und den Rest in dx (ah, dx oder edx).

    Der Rest jeder Division ist dann eine Stelle der Zahl (hier Werte von 0-9). Die musst du noch in ein lesbares Zeichen umwandeln, zB. fuer ASCII, indem du 30h dazu addierst (oder "veroderst") - siehe eine Tabelle des ASCII-Zeichensatzes.

    Bei diesem Vorgang kommen die Ziffern, wie du feststellen wirst, in umgekehrter Reihenfolge heraus, also zuerst die 1er-Stelle, dann 10er, usw.
    Du kannst also nun deinen String entweder direkt mit den berechneten Resten von hinten noch vorn befuellen, oder du parkst die Ziffern auf einem Stapel und "pop"st sie von dort in deinen String, um die Reihenfolge umzudrehen. Dazu bietet es sich an, den normalen x86-Stack zu benutzen und mit zu zaehlen, wie viele Ziffern du raufpackst.
    Am Ende noch das "$" an den String haengen und du kannst ihn mit Funktion 09h ausgeben.

    Natuerlich gibt es abhaengig von verschiedene Zahlen-Breiten, -Basen, und Zahl der Stellen noch verschiedenste Optimierungsmoeglichkeiten, aber das Prinzip ist wie gesagt das Gleiche.

    Hoffe das ist so weit klar geworden; sonst nochmal genauer fragen.



  • Muss ich dann bh durch 10 dividieren ?



  • Das geht (zumindest mittels div) nicht.
    Wenn du das Ergebnis der Addition, das ja in bh steht, ausgeben willst, musst du bh eben nach ax (Vorsicht, bh hat 8, ax 16Bit) kopieren. Dann klappt das mit der Division auch wie beschrieben.



  • Und was muss ich da jetzt wo dividieren ?

    .model small
    .stack 100h
    .data
    
    ergebniss DB 2
    
    .code
    entrypoint:
    
            mov ah,7
            mov bh,3
    
            add bh,ah
    
            mov ax,bh
    
            mov ah,9h
            int 21h
    
            mov ah,4ch
            int 21h
    
    end entrypoint
    end
    


  • Zuerst mal kannst du (wie ich angedeutet habe) ein 8Bit-Register (bh) nicht einfach per mov in ein 16Bit-Register (ax) kopieren. Wo soll die CPU auf diese Weise denn die fehlenden 8Bit herzaubern?

    Vielleicht schaust du dir dazu erstmal an, wie die 8,16 und 32Bit-Register beim x86 zusammenhaengen: click
    Dann mal kurz drueber nachdenken, wie man bh nach ax bekommt, wobei die oberen 8Bit von ax (ah) sinnvollerweise 0 gesetzt werden.
    Es gibt auch hier mehr als eine Moeglichkeit - seit AFAIR dem 486er sogar einen extra Befehl: movzx
    Mit diesem Befehl kannst du einfach Register geringerer Breite in Register groesserer Breite kopieren.

    Wie gesagt musst du dann die (16Bit-)Zahl, die du in Ziffern zerlegen willst (sie sollte in ax stehen), durch die Basis (10 fuer Dezimal-Zahlen) dividieren. Und zwar in einer Schleife, bis der Quotient 0 wird... habe ich auch schon geschrieben. Auf 0 pruefen kannst du allgemein mit dem Befehl cmp, oder bei Registern mit dem Befehl test. zB. "test al, al" setzt das Zero-Flag (zB. bedingte Spruenge jz/jnz), wenn al=0 ist.

    div akzeptiert als Operand (der Operand ist der Divisor!) nur Register oder "Variablen" im Speicher (hier reichen 8bit! - sonst musst du den Dividend auch anders verteilen - auf ax:dx oder eax:edx). Konstanten kannst du nicht als Operand angeben.



  • Ich hab nochmal etwas gegoogelt noch was gefunden.

    Nur eine Frage dazu hab ich:

    sub al,48 ; Hier wird ja was Konvertiert aber von was nach was

    int nach string ? string nach int ...

    Ich glaub ich kauf mir nachher mal ein Buch von den Tutorial aus dem FAQ fand ich das hier am besten:

    http://www.assembler.my100megs.com/ASMPage.pdf

    Ich glaub das Buch kauf ich einfach mal.

    Kennt das zufälligerweise wer ?

    Ansonsten teste ich es einfach mal. ^^

    .model small
    .stack 100h
    
    .data
    
       zahl1 db 10,13,"Zahl1: ","$"
    
       zahl2 db 10,13,"Zahl2: ","$"
    
       ausgabe db 10,13,"Ergebniss: ","$"
    
       eingabe1 db ?
       ergebniss db ?,'$'
    
    .code
    
    entrypoint:
    
            mov dx,@data
            mov ds,dx         
    
       mov dx,offset zahl1
    
       mov ah,09
       int 21h
    
            mov ah,01   ; tastatur eingabe die eingabe wird in al gespeichert
            int 21h
    
            sub al,48   ; al konvertieren   von int nach string ??
            mov eingabe1 ,al   ; tasten eingabe in der variable eingabe1 abspeichern
    
       mov dx,offset zahl2
    
       mov ah,09
       int 21h
    
            mov ah,01
            int 21h
    
            sub al,48
    
            ; die tasten eingabe von zahl2 steht in register al
            ; die eingabe von zahl2 braucht man nicht noch extra in eine variable schieben
            ; das macht man nur wenn man mehrere verschiedene zahlen addieren bzw. subtrahieren will
    
    add al,eingabe1  ; eingabe1 ist die zahl welche man bei zahl1 eingeben hat al ist für zahl2
    add al,48    ; al konvertieren
    
    mov ergebniss,al
    
               mov dx,offset ausgabe
               mov ah,09
               int 21h
    
               mov dx,offset ergebniss
               mov ah,09
               int 21h
    
               mov ah,4ch
               int 21h
    
    end entrypoint
    end
    


  • Das Buche kenne ich, ist ganz brauchbar für den Einstieg.
    Ich rate Dir zu NASM, weil dieser sozusagen freeware standard ist.



  • Ich hab mir das Buch auch erst gekauft. Bin zwar noch net ganz fertig, aber kann es auch empfehlen. Am Anfang wird kurz erklärt was Assembler ist und.. Dann gehts aber auch gleich mit Hallo-World los und dann wird das Programm immer Stück für Stück erklärt.

    Wenn du dir es bestellst würde ich aber darauf achten, das du dir gleich die 2. Auflage bestellst.
    Ansonsten viel Spaß mit dem Buch



  • Ok ty für die Antworten.



  • add schrieb:

    sub al,48 ; Hier wird ja was Konvertiert aber von was nach was

    int nach string ? string nach int ...

    Weder noch.

    In dem Code wird ein Zeichen von der Tastatur eingelesen und zum Schluss auch nur eins ausgegeben. In C waere das wohl ein "char".
    Wenn du dir mal eine ASCII-Tabelle ansiehst, sollte dir eigentlich recht schnell aufgehen, was da passiert. ... und dass dieser Code Probleme mit anderen Eingaben als jeweils einer Ziffer, sowie Endergebnissen >9 haben wird.



  • ...
    push ax
    push cx
    push dx
    mov ah,02
    mov dl,bh
    mov cl,4
    shr dl,cl
    add dl,30
    cmp dl,39
    jle ;(+3)
    add dl,07
    int 21
    mov dl,bh
    and dl,0f
    add dl,30
    cmp dl,39
    jle ;(zum int21)
    add dl,07
    int 21
    pop ax
    pop cx
    pop dx
    ...


Anmelden zum Antworten