Some instructions that you need to know

This is just a list of some basic assembly instructions that are very important and are used often.

ADD: Add the contents of one number to another

Syntax:

ADD operand1,operand2
This adds operand2 to operand1. The answer is stored in operand1. Immediate data cannot be used as operand1 but can be used as operand2.

SUB: Subtract one number from another

Syntax:

SUB operand1,operand2
This subtracts operand2 from operand1. Immediate data cannot be used as operand1 but can be used as operand2.

MUL: Multiplies two unsigned integers (always positive)
IMUL: Multiplies two signed integers (either positive or negitive)
Syntax:

MUL register or variable
IMUL register or variable
This multiples AL or AX by the register or variable given. AL is multiplied if a byte sized operand is given and the result is stored in AX. If the operand is word sized AX is multiplied and the result is placed in DX:AX.

On a 386, 486 or Pentium the EAX register can be used and the answer is stored in EDX:EAX.

DIV: Divides two unsigned integers (always positive)
IDIV: Divides two signed integers (either positive or negitive)
Syntax:

DIV register or variable
IDIV register or variable
This works in the same way as MUL and IMUL by dividing the number in AX by the register or variable given. The answer is stored in two places. AL stores the answer and the remainder is in AH. If the operand is a 16 bit register than the number in DX:AX is divided by the operand and the answer is stored in AX and remainder in DX.

Introduction to Procedures

In assembly a procedure is the equivalent to a function in C or Pascal. A procedure provides a easy way to encapsulate some calculation which can then be used without worrying how it works. With procedures that are properly designed you can ignore how a job is done.

This is how a procedure is defined:

PROC AProcedure
.
. 		; some code to do something 
.
ret		; if this is not here then your computer will crash 
ENDP AProcedure
It is equally easy to run a procedure all you need to do is this:
call AProcedure
This next program is an example of how to use a procedure. It is like the first example we looked at, all it does is print "Hello World!" on the screen.
Listing 3: SIMPPROC.ASM

; This is a simple program to demonstrate procedures. It should
; print Hello World! on the screen when ran.

.model tiny 
.code 
org 100h

Start: 

call Display_Hi 	; Call the procedure
mov ax,4C00h 		; return to DOS
int 21h 		

Display_Hi PROC 

mov dx,OFFSET HI 
mov ah,9 
int 21h 

ret
Display_Hi ENDP 

HI DB "Hello World!" 	; define a message

end Start

Procedures that pass parameters

Procedures wouldn't be so useful unless you could pass parameters to modify or use inside the procedure. There are three ways of doing this and I will cover all three methods: in registers, in memory and in the stack.

There are three example programs which all accomplish the same task. They print a square block (ASCII value 254) in a specified place.

The sizes of the files when compiled are: 38 for register, 69 for memory and 52 for stack (in bytes).

In registers

The advantages of this is that it is easy to do and is fast. All you have to do is to is move the parameters into registers before calling the procedure.
Listing 4: PROC1.ASM

; this a procedure to print a block on the screen using 
; registers to pass parameters (cursor position of where to 
; print it and colour).

.model tiny 
.code
org 100h

Start: 

mov dh,4 	; row to print character on
mov dl,5 	; column to print character on
mov al,254 	; ascii value of block to display
mov bl,4 	; colour to display character

call PrintChar 	; print our character
mov ax,4C00h 	; terminate program 
int 21h

PrintChar PROC NEAR

push bx 	; save registers to be destroyed
push cx

xor bh,bh 	; clear bh - video page 0
mov ah,2 	; function 2 - move cursor
int 10h 	; row and col are already in dx

pop bx 		; restore bx

xor bh,bh 	; display page - 0
mov ah,9 	; function 09h write char & attrib
mov cx,1 	; display it once
int 10h 	; call bios service

pop cx 		; restore registers

ret 		; return to where it was called
PrintChar ENDP

end Start

Passing through memory

The advantages of this method is that it is easy to do but it makes your program larger and can be slower.

To pass parameters through memory all you need to do is copy them to a variable which is stored in memory. You can use a variable in the same way that you can use a register but commands with registers are a lot faster.

Listing 5: PROC2.ASM 

; this a procedure to print a block on the screen using memory
; to pass parameters (cursor position of where to print it and
; colour).

.model tiny 
.code
org 100h

Start: 

mov Row,4 	; row to print character
mov Col,5 	; column to print character on
mov Char,254 	; ascii value of block to display
mov Colour,4 	; colour to display character

call PrintChar 	; print our character
mov ax,4C00h 	; terminate program 
int 21h

PrintChar PROC NEAR

push ax cx bx 	; save registers to be destroyed

xor bh,bh 	; clear bh - video page 0
mov ah,2 	; function 2 - move cursor
mov dh,Row
mov dl,Col
int 10h 	; call Bios service 

mov al,Char 
mov bl,Colour
xor bh,bh 	; display page - 0
mov ah,9 	; function 09h write char & attrib 
mov cx,1 	; display it once
int 10h 	; call bios service

pop bx cx ax 	; restore registers

ret 		; return to where it was called
PrintChar ENDP

; variables to store data

Row db 		? 
Col db 		?
Colour db 	?
Char db 	?

end Start

Passing through Stack

This is the most powerful and flexible method of passing parameters the problem is that it is more complicated.
Listing 6: PROC3.ASM

; this a procedure to print a block on the screen using the 
; stack to pass parameters (cursor position of where to print it
; and colour).

.model tiny 
.code
org 100h

Start: 

mov dh,4 	; row to print string on
mov dl,5 	; column to print string on
mov al,254 	; ascii value of block to display
mov bl,4 	; colour to display character
push dx ax bx 	; put parameters onto the stack 

call PrintString ; print our string

pop bx ax dx 	;restore registers
mov ax,4C00h 	;terminate program 
int 21h

PrintString PROC NEAR

push bp 	; save bp
mov bp,sp 	; put sp into bp
push cx 	; save registers to be destroyed

xor bh,bh 	; clear bh - video page 0
mov ah,2 	; function 2 - move cursor
mov dx,[bp+8] 	; restore dx
int 10h 	; call bios service

mov ax,[bp+6] 	; character
mov bx,[bp+4] 	; attribute
xor bh,bh 	; display page - 0
mov ah,9 	; function 09h write char & attrib 
mov cx,1 	; display it once
int 10h 	; call bios service

pop cx 		; restore registers
pop bp 

ret 		; return to where it was called
PrintString ENDP

end Start

This shows the stack for a procedure with two parameters

To get a parameter from the stack all you need to do is work out where it is. The last parameter is at BP+2 and then the next and BP+4.

What are "Memory Models"?

We have been using the .MODEL directive to specify what type of memory model we use, but what does this mean?

Syntax:
.MODEL MemoryModel

Where MemoryModel can be SMALL, COMPACT, MEDIUM, LARGE, HUGE, TINY or FLAT.

Tiny
This means that there is only one segment for both code and data. This type of program can be a .COM file.
Small
This means that by default all code is place in one segment and all data declared in the data segment is also placed in one segment. This means that all procedures and variables are addressed as NEAR by pointing at offsets only.
Compact
This means that by default all elements of code are placed in one segment but each element of data can be placed in its own physical segment. This means that data elements are addressed by pointing at both at the segment and offset addresses. Code elements (procedures) are NEAR and variables are FAR.
Medium
This is the opposite to compact. Data elements are NEAR and procedures are FAR.
Large
This means that both procedures and variables are FAR. You have to point at both the segment and offset addresses.
Flat
This isn't used much as it is for 32 bit unsegmented memory space. For this you need a DOS extender. This is what you would have to use if you were writing a program to interface with a C/C++ program that used a DOS extender such as DOS4GW or PharLap.

Macros (in Turbo Assembler)

Note: All code examples given are for macros in Turbo Assembler.

Macros are very useful for doing something that is done often but for which a procedure can't be used. Macros are substituted when the program is compiled to the code which they contain.

This is the syntax for defining a macro:

Name_of_macro macro 
;
;	a sequence of instructions 
;
endm
These two examples are for macros that take away the boring job of pushing and popping certain registers:
SaveRegs macro

push ax
push bx
push cx
push dx

endm

RestoreRegs macro

pop dx
pop cx
pop bx
pop ax

endm
Notice that the registers are popped in the reverse order to they were pushed. To use a macro in you program you just use the name of the macro as an ordinary instruction:
SaveRegs

; some other instructions

RestoreRegs
This example shows how you can use a macro to save typing in. This macro simply prints out a message to the screen.
OutMsg macro SomeText
local PrintMe,SkipData

jmp SkipData

PrintMe db SomeText,'$'

SkipData:

push ax dx cs 

mov dx,OFFSET cs:PrintMe
mov ah,9
int 21h

pop cs dx ax

endm

The only problems with macros is that if you overuse them it leads to you program getting bigger and bigger and that you have problems with multiple definition of labels and variables. The correct way to solve this problem is to use the LOCAL directive for declaring names inside macros.

Syntax:

LOCAL name 
Where name is the name of a local variable or label.

Macros with parameters

Another useful property of macros is that they can have parameters. The number of parameters is only restricted by the length of the line.

Syntax:

Name_of_Macro macro par1,par2,par3
;
; commands go here
;
endm
This is an example that adds the first and second parameters and puts the result in the third:
AddMacro macro num1,num2,result

push ax 	; save ax from being destroyed
mov ax,num1 	; put num1 into ax
add ax,num2 	; add num2 to it
mov result,ax 	; move answer into result
pop ax 		; restore ax

endm 

Return to Table of Contents