2017-02-19 3 views
1

Waskann nicht in der folgenden 8086 Assembler-Code

ich mit Array eine Reihe von negativen und positiven Zahlen zu drucken, ich versuche zu tun, ich versuche mit Array negative Zahlen angezeigt werden soll.

, was das Problem ist

Ich bin negative Zahlen zu drucken, nicht in der Lage.

Eingang:

2,-3,-4,5,2,9 

Ausgang:

2-,529 

Mein 8086 Assembly Code:

.model small 
.stack 100h 
.data     
    elements db 2,-3,-4,5,2,9,'#' 
.code 

    mov ax, @data 
    mov ds, ax 

    mov al, 03h 
    mov ah, 0 
    int 10h  
    mov si, 0 
    ;lea si, elements 

dis: 

    cmp elements[si], '#' 
    je exit 

    mov dl, elements[si] 
    add dl, 48 
    mov ah, 02h 
    int 21h  
    inc si 
    loop dis 
exit:  
    mov ah, 04ch 
    int 21h  
end 

Hinweis: Ich bin ein Anfänger in der Montage.

+1

Alas DOS fehlt eine Funktion für ganze Zahlen Druck, so dass Sie es selbst müssen implementieren, indem einzelne Zeichen zu drucken. Du bist ein Anfänger in Assembler, und das ist fair. Mein Vorschlag ist, dass Sie damit beginnen, diese Funktion in einer Sprache zu implementieren, in der Sie sich wohler fühlen, obwohl Sie nur eine grundlegende 'putchar'-Funktion und keine Bibliotheksunterstützungsfunktionen verwenden. Dies sollte als ausgezeichneter Ausgangspunkt und Referenz für die Umsetzung der Montageäquivalent dienen. – doynax

Antwort

0

Diese Anweisung

add dl, 48 

48 auf den Wert in dl (set vom elements Array), ist es zur Karte auf den entsprechenden ASCII-digit (ASCII "0" == 48) gespeichert hinzufügt. Wenn dl negativ ist, ist das Ergebnis weniger als 48 und würde auf ein ASCII-Zeichen außerhalb des Ziffernbereichs abgebildet. Zum Beispiel bei der Verarbeitung von -3:

mov dl, -3 
add dl, 48 

in dl enthalten führen. Dies mappt auf ASCII - (Minus/Strich), so dass was ausgegeben werden soll.

Unter der Annahme, dass jeder Wert in elements eine einzige Ziffer steht für (0-9), ob der Wert in elements negativ testen musst, nehmen Sie ihren absoluten Wert, dann hinzufügen, dass bis 48 an dem richtigen ASCII-Wert zu gelangen für die Ziffer. Dann müssen Sie ein Minuszeichen (ASCII 45) gefolgt von der neu berechneten ASCII-Ziffer ausgeben.

0

Wie Sie Anfänger sind, werde ich nur Ihren Code "reparieren", um die falsche Sache richtig zu machen (nicht zu tun, um neuen Code zu schreiben, die richtige Sache überhaupt tun, da das zu viele Änderungen wäre).

.model small 
.stack 100h 
    ; array terminator changed to -128, because signed bytes values can be -128 to +127 
    ; so this new terminator allows for array with values -127 to +127 
ARRAY_TERMINATOR EQU  -128 
    ; the old '#' is value 35, which makes weird possible range: [-128, +34] U [+36, +127] 
.data 
    elements db 2,-3,-4,5,2,9,ARRAY_TERMINATOR 

.code 
    mov ax, @data 
    mov ds, ax 

    mov ax, 03h ; ax = 3 <=> ah = 0 (set mode), al = 3 (text mode) 
    int 10h  ; set default 80x25 text mode (clears screen) 
    xor si,si  ; si = 0 (common x86 assembly idiom how to set zero) 
     ; but it also destroy flags, so in certain cases the "mov r?,0" is needed. 

display_loop:  ; use meaningful label names, when possible 
     ; using short labels saves time while writing, but wastes time 
     ; while reading + debugging, which you will do lot more often! 

    ; load value first, so you can also compare it from register (faster/shorter) 
    mov dl, [elements+si] ; it doesn't hurt anything, when dl = -128 at end 
     ; also I would rather put address label inside brackets, the "elements[]" 
     ; way evokes false feeling, that it is array access from C. It is NOT. 
     ; works like that for byte arrays, but already for WORD you need si*2! 

    ; now it's possible to compare for terminator against register dl 
    cmp dl, ARRAY_TERMINATOR 
    je exit 

    add dl, '0' ; you can use ASCII '0' formatting of value 48 to better tell 
     ; source reader, what you are trying to do, which is adding ASCII digit '0' 
     ; try to write source to reflect your human intentions, you can write 
     ; value 48 in many ways: 48, 30h, '0', 32+16, 3*16 ... 
     ; All of them will compile into the same 48, but each tells different story 
     ; to the reader of the source. +48 is arithmetic, +'0' is conversion to ASCII 
    mov ah, 02h 
    int 21h 
     ; the code above will display correct digit only for values 0-9 
     ; any other value will be mangled into some other ASCII character 
     ; check ASCII table to get idea what happens for other values (10+48 = ':') 

    inc si 
    jmp display_loop ; don't use loop without initializing "cx" 
     ; and don't use "loop" either, do rather "dec cx" "jnz loop" 
     ; "loop" instruction is artifically slowed down to support some legacy code 
     ; Any way, in this case you don't want to loop per cx count, but until 
     ; array terminator is hit, so use "jmp" instead to jump every time 

    ; to fix the output the inner part of loop would have to: 
    ; display char '-' when value is negative (for example for value -123). 
    ; convert absolute value into digit characters in base-10 (decimal) formatting 
    ; which involves dividing the value by 10 until zero and remembering remainders 
    ; For example |-123| = +123 => would produce remainders: 3, 2 and 1 
    ; Then you add '0' to each remainder, and display them in reversed order. 
    ; display ', ' characters (for start even after last number, when works, improve) 
    ; (logic to avoid last comma requires often some thought and more code 
    ; one usual way is to display first number without comma, and rest of array 
    ; starts by displaying comma, then number) 

exit: 
    mov ah, 04ch 
    int 21h 
end 

(Aber zumindest habe ich einige „Übersicht“, was die Zahlen getan werden müsste in erwarteter Weise anzuzeigen ... wie auch immer, darauf zu achten, zuerst an die kleinen Details, die ich in Ihrem ersten geändert Version)

2

Ihr Programm hat zwei Hauptprobleme:

  1. Sie verwenden die loop Anweisung ohne die Zähler CX vorher registrieren initialisiert zu haben!Glücklicherweise hat Ihr Code eine zusätzliche Abbruchbedingung oben auf dem CX Register, das wahrscheinlich Null ist, um damit zu beginnen. Und dann zu denken, dass Sie diese Anweisung in diesem Programm nicht einmal brauchen.

  2. Sie testen nie, ob die Zahl, die Sie aus dem Array gelesen haben, positiv oder negativ ist.

Hier ist eine komplette Lösung mit zusätzlichen wichtigen Anmerkungen:

xor si, si   ;Same as "mov si,0" 
dis: 
    mov bl, elements[si] 
    cmp bl, '#' 
    je exit 
    test bl, bl   ;Same as "cmp bl, 0" 
    jns IsPositive 
    mov dl, "-"   ;First display a minus sign 
    mov ah, 02h 
    int 21h 
    neg bl    ;Turn the negative number into a positive number 
IsPositive: 
    mov dl, "0" 
    add dl, bl   ;Change the value [0,9] into character ["0","9"] 
    mov ah, 02h 
    int 21h  
    inc si 
    jmp dis    ;Unconditionally jump back. Don't use "loop" 
exit:  
    mov ax, 4C00h  ;Always use the full AX, the API defines it that way! 
    int 21h 
+1

Hatte das gleiche Problem heute mit jemandem automatisch die 'LOOP' Anweisung zu verwenden, wenn beauftragt, eine Schleife zu schreiben. Es ist einfach zu ähnlich! – Fifoernik