添加两个数字以形成两位数字

时间:2014-10-31 16:05:37

标签: assembly x86 dos x86-16

我想将两个预定值相加并产生结果。 我的代码目前正在做的是将16和6加在一起,这应该打印出来22.然而它打印出2 ...我真的不确定如何纠正这个......

以下是代码:

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 个答案:

答案 0 :(得分:1)

如果你真的只想获得一个两位数的十进制数字(如标题所示),你可以使用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

如果您还想获得一个三位十进制数,则可以将数字隔开两个分区。首先除以100,结果得到第一个数字。然后将余数除以10,得到第二个数字,而第三个数字在余数中:

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

如果你受到前导零的干扰,你可以通过重复除以10来反向排列数字。如果你想转换更大的数字,这也是最常用的方法:

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