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
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