ADD: Add the contents of one number to another
Syntax:
This adds operand2 to operand1. The answer is stored in operand1. Immediate data cannot be used as operand1 but can be used as operand2.ADD operand1,operand2
SUB: Subtract one number from another
Syntax:
This subtracts operand2 from operand1. Immediate data cannot be used as operand1 but can be used as operand2.SUB operand1,operand2
MUL: Multiplies two unsigned integers (always positive)
IMUL: Multiplies two signed integers (either positive or
negitive)
Syntax:
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.MUL register or variable IMUL register or variable
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:
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.DIV register or variable IDIV register or variable
This is how a procedure is defined:
It is equally easy to run a procedure all you need to do is this:PROC AProcedure . . ; some code to do something . ret ; if this is not here then your computer will crash ENDP 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.call AProcedure
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
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).
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
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
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
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.
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:
These two examples are for macros that take away the boring job of pushing and popping certain registers:Name_of_macro macro ; ; a sequence of instructions ; 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 macro push ax push bx push cx push dx endm RestoreRegs macro pop dx pop cx pop bx pop ax endm
This example shows how you can use a macro to save typing in. This macro simply prints out a message to the screen.SaveRegs ; some other instructions RestoreRegs
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:
Where name is the name of a local variable or label.LOCAL name
Syntax:
This is an example that adds the first and second parameters and puts the result in the third:Name_of_Macro macro par1,par2,par3 ; ; commands go here ; endm
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