Adding two numbers to make a two digit number

女生的网名这么多〃 提交于 2019-12-04 07:07:29

问题


I want to add two predetermined values together and produce the result. What my code is doing at the moment is it is adding 16 and 6 together which should print out 22. However it is printing out 2... I'm not really sure how to correct this...

Here is the code:

data    segment                         ; data segment. Keyword db means define byte. You can also define word (dw)
        numA    db  16                  ;Define first variable
        numB    db  06                  ;Define second variable
        StrMsg  db 'The answer is $'    ;return message to the user
        leng    db 1                    ;length of the charachters - this value will be overwritten
data    ends

                                        ; stack segment
stack1  segment stack       
        db  100 dup(?)                  ; This is the stack of 100 bytes
stack1  ends


code    segment
        assume  cs:code, ds:data, ss:stack1

start: 
                                        ;Perform initialization 
        mov ax, data                    ;Put the starting address of the data segment into the ax register (must do this first)
        mov ds, ax                      ;Put the starting address of the data segment into the ds register (where it belongs)

        mov ax, stack1                  ;Put the starting address of the stack into the ax register (must do this first)
        mov ss, ax                      ;Put the starting address of the stack segment into the ss register (where it belongs)

mov al, numA        ;move numA to ax
    add al, numB        ;ax contains numa + numb
    mov dl, al          ;move result to dl for display                      

    lea dx, StrMsg      ;load message to display the result to the user
    mov ah, 9h          ;display string subroutine 
    int 21h             ;interrupt for MS-DOS routine   

    add dl, 30h         ;Add 30h for ASCII table offset 
    mov ah, 2h          ;Store interrupt code in ah to display results in dl
    int 21h             ;display character in dl as translated by ascii code

mov ah, 4ch                     ;Set up code to specify return to dos
        int 21h                         ;Interpt number 21 (Return control to dos prompt)

code    ends

end     start

回答1:


If you really only want to get a two-digit-decimal-number (as the title suggests), you can use AAM:

data    segment                         ; data segment. Keyword db means define byte. You can also define word (dw)
        numA    db  16                  ;Define first variable
        numB    db  06                  ;Define second variable
        StrMsg  db 'The answer is $'    ;return message to the user
        leng    db 1                    ;length of the charachters - this value will be overwritten
data    ends

                                        ; stack segment
stack1  segment stack
        db  100 dup(?)                  ; This is the stack of 100 bytes
stack1  ends


code    segment
        assume  cs:code, ds:data, ss:stack1

start:
                        ;Perform initialization
    mov ax, data        ;Put the starting address of the data segment into the ax register (must do this first)
    mov ds, ax          ;Put the starting address of the data segment into the ds register (where it belongs)

    mov ax, stack1      ;Put the starting address of the stack into the ax register (must do this first)
    mov ss, ax          ;Put the starting address of the stack segment into the ss register (where it belongs)

    lea dx, StrMsg      ;load message to display the result to the user
    mov ah, 9h          ;display string subroutine
    int 21h             ;interrupt for MS-DOS routine

    mov al, numA        ;move numA to al
    add al, numB        ;al contains numa + numb

    lea di, StrMsg      ; Place for target string (The old value of StrMsg isn't used anymore)
    aam                 ; AL => AH (first dec. digit) AL (second dec. digit) (unpacked BCD)
    or ax, 3030h                 ; Convert both digits to ASCII
    mov BYTE PTR [di], ah        ; Store first digit
    mov BYTE PTR [di+1], al      ; Store second digit
    mov BYTE PTR [di+2], '$'     ; Store termination character for 'int 21h fn 09h'

    lea dx, StrMsg      ;load message to display the result to the user
    mov ah, 9h          ;display string subroutine
    int 21h             ;interrupt for MS-DOS routine

    mov ah, 4ch         ;Set up code to specify return to dos
    int 21h             ;Interpt number 21 (Return control to dos prompt)

code    ends

end     start

If you also want to get a three-digit-decimal-number, you can isolate the digits by two divisions. First divide by 100 and you get the first digit as result. Then divide the remainder by 10 and you get the second digit while the third digit is in the remainder:

data    segment                         ; data segment. Keyword db means define byte. You can also define word (dw)
        numA    db  16                  ;Define first variable
        numB    db  06                  ;Define second variable
        StrMsg  db 'The answer is $'    ;return message to the user
        leng    db 1                    ;length of the charachters - this value will be overwritten
data    ends

                                        ; stack segment
stack1  segment stack
        db  100 dup(?)                  ; This is the stack of 100 bytes
stack1  ends


code    segment
        assume  cs:code, ds:data, ss:stack1

start:
                        ;Perform initialization
    mov ax, data        ;Put the starting address of the data segment into the ax register (must do this first)
    mov ds, ax          ;Put the starting address of the data segment into the ds register (where it belongs)

    mov ax, stack1      ;Put the starting address of the stack into the ax register (must do this first)
    mov ss, ax          ;Put the starting address of the stack segment into the ss register (where it belongs)

    lea dx, StrMsg      ;load message to display the result to the user
    mov ah, 9h          ;display string subroutine
    int 21h             ;interrupt for MS-DOS routine

    mov al, numA        ;move numA to ax
    add al, numB        ;ax contains numa + numb
    mov dl, al          ;move result to dl for display

    lea di, StrMsg      ; Place for target string (The old value of StrMsg isn't used anymore)
    call al2dec

    lea dx, StrMsg      ;load message to display the result to the user
    mov ah, 9h          ;display string subroutine
    int 21h             ;interrupt for MS-DOS routine

    mov ah, 4ch         ;Set up code to specify return to dos
    int 21h             ;Interpt number 21 (Return control to dos prompt)

al2dec PROC             ; Args: AL register to convert, DS:DI pointer to target string
    mov bl, 100
    xor ah, ah          ; Clear AH for division
    div bl              ; AL = AX / BL remainder AH
    or al, 30h          ; Convert result to ASCII
    mov BYTE PTR [di], al        ; Store as first digit

    shr ax, 8           ; Shift remainder into AL, clear AH
    mov bl, 10
    div bl              ; AL = AX / BL remainder AH
    or al, 30h          ; Convert result to ASCII
    mov BYTE PTR [di+1], al      ; Store as second digit

    or ah, 30h          ; Convert remainder to ASCII
    mov BYTE PTR [di+2], ah      ; Store as third digit

    mov BYTE PTR [di+3], '$'     ; Store at last termination character for 'int 21h fn 09h'
    ret
al2dec ENDP             ; DS:DI contains string with decimal digits

code    ends

end     start

If you're disturbed by the leading zeroes, you can isolate the digits in reversed order by repeatedly dividing by 10. This is also the most used method, if you want to convert bigger numbers:

al2dec PROC                         ; Args: AL register to convert, DS:DI pointer to target string
    mov bl, 10                      ; Base 10 -> divisor
    xor cx, cx                      ; CX=0 (number of digits)

  al2dec_loop_1:                    ; 1st loop
    xor ah, ah                      ; Clear AH for division (don't forget it!)
    div bl                          ; AL = AX / BL   Remainder AH
    push ax                         ; Push remainder for LIFO in Loop_2
    add cl, 1                       ; Equivalent to 'inc cl'
    test al, al                     ; AL = 0?
    jnz al2dec_loop_1               ; No: once more
  al2dec_loop_2:                    ; 2nd loop
    pop ax                          ; Get back pushed digits
    or ah, 00110000b                ; Conversion to ASCII
    mov BYTE PTR [di], ah                    ; Store only AH to [DS:DI] (DI is a pointer to a string)
    add di, 1
    loop al2dec_loop_2              ; Until there are no digits left

    mov BYTE PTR [di], '$'                   ; Store termination character for 'int 21h fn 09h'
    ret                             ; Ret: DS:DI contains decimal '$'-terminated ASCII-String
al2dec ENDP


来源:https://stackoverflow.com/questions/26678900/adding-two-numbers-to-make-a-two-digit-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!