views:

242

answers:

1

Hi there...

I'm currently learning Windows/DOS assembly. I'm just making a small program that adds two base 10 integers, and outputs the solution to standard output. Here is my current code:

org 100h


MOV al,5
ADD al,3

mov dx,al

mov ah,9
int 21h

ret

I'm confused as to why when that is compiled, I get the error:

error: invalid combination of opcode and operands

Because theoretically, all I'm doing is putting 5 into the AL register, adding three to it, taking the content of the AL register and putting it into the DX register for output, and then displaying it.

Any help would be appreciated, thanks!

+5  A: 

DX is a 16-bit register, but AL is an 8-bit.

Load AL into DL, and set DH to 0.

But that won't do what you want; function 9 [displays a null-terminated string]. You're telling it to display a string that starts at offset 9 of the data segment, which is probably going to be garbage.

You'll need to convert your answer into a series of digits first, and then call function 9.

There is some example code for converting the contents of a register to a string available. Copied here for reference, written by a user with the alias Bitdog.

; ------ WDDD = Write a Decimal Digit Dword at the cursor & a CRLF ------
;
; Call with,    DX:AX = Dword value to print
; Returns,  CF set on error, if DX:AX > 655359 max#
;    (see WDECEAX.inc for larger number prints)
align 16
WDDD:   CMP DX,10
    JB WDDDok
    STC  ;CF=set
    RET  ;error DX:AX exceeded max value
WDDDok: PUSH    AX
    PUSH BX
    PUSH CX
    PUSH DX
    XOR CX,CX ; clear count register for push count
    MOV BX,10
WDDDnz: DIV BX ; divide DX:AX by BX=10
    PUSH DX ; put least siginificant number (remainder) on stack
    XOR DX,DX ; clear remainder reciever for next divide
    OR AX,AX ; check to see if AX=number is divided to 0 yet
    LOOPNE WDDDnz ; get another digit? count the pushes
    MOV AH,2 ; function 2  for interupt 21h write digit
    NEG CX ; two's compliment, reverse CX
    MOV BL,48 ; '0'
WDDDwr: POP DX ; get digit to print, last pushed=most significant
    ADD DL,BL ; convert remainder to ASCII character
    INT 21h ; print ascii interupt 21h ( function 2 in AH )
    LOOP WDDDwr ; deincrement CX, write another, if CX=0 we done
    MOV DL,13 ; CR carriage return (AH=2 still)
    INT 21h
    MOV DL,10 ; LF line feed
    INT 21h
    POP DX
    POP CX
    POP BX
    POP AX
    CLC  ;CF=clear, sucess
    RET

; A divide error occurs if DX has any value
; when DIV trys to put the remainder into it
; after the DIVide is completed.
; So, DX:AX can be a larger number if the divisor is a larger number.
lavinio