2016-06-06 16 views
3

Ich bin neu in Assembly und der Kurs, den ich folge verwendet EMU8086. Ich schrieb diesen Code, um Testing und den ASCII-Code von 50 zu drucken, der Nummer 2 ist, aber druckt nur Testing und ignoriert den Rest. Was ist los mit dir?Fehler beim Drucken einer Zeichenfolge aus Assembly-Code

.model tiny 
.code 

org 100h 


main proc 

    mov ah, 09h 
    mov dx, offset msg 
    int 21h 
    mov ah, 4ch 
    mov dx ,0 
    mov dl, 2 
    add dl, 48 
    int 21h  

endp 

msg db "Testing$" 

end main 

Nachdem die Kommentare von @ 500 zu lesen - Interner Serverfehler, ich meinen Code auf diese aktualisiert:

.model tiny 
.code 

org 100h 


main proc 

    mov ah, 09h 
    mov dx, offset msg 
    int 21h 
    mov dl, 2 
    add dl, 48 
    int 21h  

endp 

msg db "Testing$" 

end main 

Es ist immer noch nicht funktioniert, so was ist los?

+0

Wenn ah = 4-Kanal für int 21h , Sie bitten das Programm zu beenden - der Wert von dl wird höchstwahrscheinlich von dieser Anfrage vollständig ignoriert. –

+0

@ 500-InternalServerError ich habe diese Codezeile entfernt und funktioniert immer noch nicht – Kordy

+0

Aktualisiere die Frage mit dem, wie der Code jetzt aussieht, dann. Im Allgemeinen benötigen Sie einen weiteren Interrupt (ah = 09h oder einen anderen), um etwas anderes ausgeben zu können. Der 'Testing $' String wird durch '$' beendet. –

Antwort

1

Das DOS unterbrechen INT 21h/AH=9h nimmt keinen Zeichenwert zu drucken, es dauert, die zu Beginn eines $ terminierte String Offset-Speicher zu drucken.

DOS 1+ - WRITE STRING auf die Standardausgabe

AH = 09h

DS: DX -> '$' - terminierten String

Return:

AL = 24h (das '$' beendet die Zeichenkette trotz offizieller Dokumente, die angeben, dass nichts zurückgegeben wird) (mindestens DOS 2.1-7.0 und NWDOS)

Wenn Sie ein einzelnes Zeichen mit INT 21h/AH = 9h ausdrucken möchten, müssen Sie den Wert in einen Puffer verschieben, der mit einem $ Zeichen abgeschlossen ist. Dann übergeben Sie die Adresse dieses Puffers in INT 21h/AH = 9h. Basierend auf dem zweiten Beispiel so etwas wie dies funktionieren sollte:

.model tiny 
.code 
org 100h 

main proc 
    mov ah, 09h    ; DOS Interrupt ah=9h print $ terminated string 
    mov dx, offset msg  ; Address of msg 
    int 21h     ; Int 21h/ah=9h Print msg 
    mov outchar, 48+2  ; Move ASCII val for `2` to outchar buffer 
    mov dx, offset outchar ; Address of the $ terminated outchar buffer in DX 
    int 21h     ; AH is still 9h, so this prints $ terminated string 

    mov ax, 4c00h   ; Exit program with return value 0 
    int 21h  
endp 

msg db "Testing$"   ; msg string 
outchar db ?, "$"   ; output buffer for single character terminated with $ 

end main 

Statt mov outchar, 48+2 könnten Sie einfach den ASCII-Wert wie folgt verwenden:

mov outchar, '2' 

Alternativ Sie es mit einem einzigen Anruf machen könnte zu INT 21h/AH = 9h, indem Sie das gewünschte Zeichen in die Mitte eines Ausgabepuffers stellen:

main proc 
    mov outchar, '2' ; Place the ASCII value for '2' in the output buffer 
    mov ah, 09h   
    mov dx, offset msg 
    int 21h    ; Print $ terminated string starting at `msg` 
    mov ax, 4c00h 
    int 21h    ; Exit with error code 0 
endp 

msg  db "Testing" 
outchar db ?, "$" 

Der Grund dieser Arbeiten ist, weil INT 21h/AH = 9h blind alles gedruckt wird es ab Offset findet msg, bis er einen $ Abschluss Charakter findet. Wir machen die Ersetzung des Zeichens bei outchar effektiv zuerst, so dass, wenn INT 21h/AH = 9h ausgeführt wird, Testing2$ im Speicher auftreten wird.

Sobald es erreicht die $ er den Druck zu stoppen, so dass die Ausgabe aussehen würde:

Testing2


Sie haben auch die Möglichkeit, mit zwei verschiedenen DOS (INT 21h) unterbricht. Während INT 21h/AH = 9h druckt eine $ terminierten String, INT 21h/AH=2h zeigt ein einzelnes Zeichen:

DOS 1+ - WRITE CHARACTER auf die Standardausgabe

AH = 02h

DL = Zeichen zu schreiben

Rückgabe: AL = letzte Zeichenausgabe (trotz der offiziellen Dokumente, die nichts zurückgegeben wird) (mindestens DOS 2.1-7.0)

Sie könnten Ihr Programmcode die msg Zeichenfolge anzuzeigen, wie Sie getan haben, aber dann kann man INT 21h/AH = 2h verwenden, um ein einzelnes Zeichen anzuzeigen. Der Code könnte dann wie folgt aussehen:

.model tiny 
.code 
org 100h 

main proc 
    mov ah, 09h    ; DOS Interrupt ah=9h print $ terminated string 
    mov dx, offset msg  ; Address of msg 
    int 21h     ; Int 21h/ah=9h Print msg 
    mov ah, 02h    ; DOS interrupt ah=2h print single character 
    mov dl, '2'    ; DL = ASCII value of character to print 
    int 21h     ; Int 21h/ah=2h print single character in DL 

    mov ax, 4c00h   ; Exit program with return value 0 
    int 21h  
endp 

msg db "Testing$"   ; msg string 

end main 
1

Ihr zweiter Code fast in Ordnung ist, haben Sie vergessen nur die Servicenummer in ahint 21h zu sagen, was zu tun ist:

.model tiny 
.code 

org 100h 


main proc 

    mov ah, 09h 
    mov dx, offset msg 
    int 21h 

    mov ah, 2   ;<==== AH=2 : INT 21H WILL DISPLAY CHARACTER IN DL. 
    mov dl, 2 
    add dl, 48 
    int 21h  

endp 

msg db "Testing$" 

end main