Turinys

Input and control flow

Making things easier

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.

Keyboard Input

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.

Printing a Character

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.

Control Flow

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:

Jump on Condition Instructions

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

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.

Example

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