The way we entered the address of the message we wanted to print was a bit cumbersome. It took three lines and it isn't the easiest thing to remember.
mov dx,OFFSET MyMessage mov ax,SEG MyMessage mov ds,ax
We can replace all this with just one line. This makes the code easier to read and it easier to remember.
mov dx,OFFSET MyMessage
To make this work at the beginning of your code add these lines:
mov ax,@data mov ds,ax
Note: for A86 you need to change the first line to:
mov ax,data
This is because all the data in the segment has the same SEG
value. Putting this in DS saves us reloading this every time we want to use another thing in the same segment.
We are going to use interrupt 16h
, function 00h
to read the keyboard. this gets a key from the keyboard buffer. If there isn't one, it waits until there is. It returns the SCAN
code in AH and the ASCII translation in AL.
xor ah,ah ; function 00h - get character int 16h ; interrupt 16h
All we need to worry about for now is the ascii value which is in AL.
Note: XOR
performs a Boolean Exclusive OR. It is commonly used to erase a register or variable.
The problem is that we have the key that has been pressed in ah. How do we display it? We can't use function 9h because for that we need to have already defined the string which has to end with a dollar sign. this is what we do instead:
; after calling function 00h of interrupt 16h mov dl,al ; move al (ascii code) into dl mov ah,02h ; function 02h of interrupt 21h int 21h ; call interrupt 21h If you want to save the value of AH then push AX before and pop it afterwards.
In assembly there is a set of commands for control flow like in any other language. Firstly the most basic command:
jmp label
All this does it to move to the label specified and start executing the code there. For example:
jmp ALabel . . . ALabel:
What do we do if we want to compare something? We have just got a key from the user but we want to do something with it. Lets print something out if it is equal to something else. How do we do that? It is easy. We use the jump on condition commands.
Firstly you compare the operand with the data and then use the correct command.
cmp ax,3 ; is AX = 3? je correct ; yes
Here is a list of them:
JA | Jumps if the first number was above the second number |
---|---|
JAE | same as above, but will also jump if they are equal |
JB | jumps if the first number was below the second |
JBE | Same as above, but will also jump if they are equal |
JNA | jumps if the first number was NOT above (JBE) |
JNAE | jumps if TDe first number was NOT above or TDe same as (JNB) |
JNB | jumps if the first number was NOT below (JAE) |
JNBE | jumps if the first number was NOT below or the same as (JA) |
JZ | jumps if the two numbers were equal |
JE | same as JZ, just a different name |
JNZ | jumps if the two numbers are NOT equal |
JNE | same as above |
JC | jump if carry flag is set |
Note: the jump can only be a maximum of 127 bytes in either direction.
CMP
: compare a value
Syntax:
CMP register or variable, value jxx destination
An example of this is:
cmp al,'Y' ; compare the value in al with Y je ItsYES ; if it is equal then jump to ItsYES
Every instruction takes up a certain amount of code space. You will get a warning if you try and jump over 127 bytes in either direction from the compiler. You can solve this by changing a sequence like this:
cmp ax,10 ; is AX 10? je done ; yes, lets finish
to something like this:
cmp ax,10 ; is AX 10? jne notdone ; no it is not jmp done ; we are now done notdone:
This solves the problem but you may want to think about reordering your code or using procedures if this happens often.
Now we are going to look at a program which demonstrates input, output and control flow.
; a program to demonstrate program flow and input/output .model tiny .stack 100h .code org 100h start: mov dx,OFFSET Message ; display a message on the screen mov ah,9 ; using function 09h int 21h ; of interrupt 21h mov dx,OFFSET Prompt ; display a message on the screen mov ah,9 ; using function 09h int 21h ; of interrupt 21h jmp First_Time Prompt_Again: mov dx,OFFSET Another ; display a message on the screen mov ah,9 ; using function 09h int 21h ; of interrupt 21h First_Time: mov dx,OFFSET Again ; display a message on the screen mov ah,9 ; using function 09h int 21h ; of interrupt 21h xor ah,ah ; function 00h of int 16h ; interrupt 16h gets a character mov bl,al ; save to bl mov dl,al ; move al to dl mov ah,02h ; function 02h - display character int 21h ; call DOS service cmp bl,'Y' ; is al=Y? je Prompt_Again ; if yes then display it again cmp bl,'y' ; is al=y? je Prompt_Again ; if yes then display it again theEnd: mov dx,OFFSET GoodBye ; print goodbye message mov ah,9 ; using function 9 int 21h ; of interrupt 21h mov ah,4Ch ; terminate program int 21h .DATA CR equ 13 ; enter LF equ 10 ; line-feed Message DB "A Simple Input/Output Program$" Prompt DB CR,LF,"Here is your first prompt.$" Again DB CR,LF,"Do you want to be prompted again? $" Another DB CR,LF,"Here is another prompt!$" GoodBye DB CR,LF,"Goodbye then." end start