Make your own free website on Tripod.com

Lesson 9. Macros And Procedures.

Prev || Home

bar.gif (11170 bytes)

Procedures.
Definition of procedure
Syntax of a procedure
Macros.
Definition of a macro
Syntax of a macro
Macro libraries
Definition of procedure
A procedure is a collection of instructions to which we can direct the flow of
our program, and once the execution of these instructions is over control is
given back to the next line to process of the code which called on the
procedure.

Procedures help us to create legible and easy to modify programs.

At the time of invoking a procedure the address of the next instruction of the
program is kept on the stack so that, once the flow of the program has been
transferred and the procedure is done, one can return to the next line of the
original program, the one which called the procedure.


Syntax of a Procedure
There are two types of procedures, the intra segments, which are found on the
same segment of instructions, and the inter segments which can be stored on
different memory segments.

When the intra segment procedures are used, the value of IP is stored on the
stack and when the intra segments are used the value of CS:IP is stored.

To divert the flow of a procedure (calling it), the following directive is used:

CALL NameOfTheProcedure

The part which make up a procedure are:

Declaration of the procedure
Code of the procedure
Return directive
Termination of the procedure

For example, if we want a routine which adds two bytes stored in AH and AL each one, and keep the addition in the BX register:

Adding Proc Near ; Declaration of the procedure
Mov Bx, 0 ; Content of the procedure
Mov B1, Ah
Mov Ah, 00
Add Bx, Ax
Ret ; Return directive
Add Endp ; End of procedure declaration


On the declaration the first word, Adding, corresponds to the name of out
procedure, Proc declares it as such and the word Near indicates to the MASM that the procedure is intra segment. The Ret
directive loads the IP address stored on the stack to return to the original program, lastly, the Add Endp directive indicates
the end of the procedure.

To declare an inter segment procedure we substitute the word Near for the word FAR.

The calling of this procedure is done the following way:

Call Adding

Macros offer a greater flexibility in programming compared to the procedures,
nonetheless, these last ones will still be used.

Definition of a Macro
A macro is a group of repetitive instructions in a program which are codified
only once and can be used as many times as necessary.

The main difference between a macro and a procedure is that in the macro the
passage of parameters is possible and in the procedure it is not, this is only
applicable for the MASM - there are other programming languages which do allow it. At the moment the macro is executed each
parameter is substituted by the name or value specified at the time of the call.

We can say then that a procedure is an extension of a determined program, while the macro is a module with specific functions
which can be used by different programs.

Another difference between a macro and a procedure is the way of calling each one, to call a procedure the use of a directive
is required, on the other hand the call of macros is done as if it were an assembler instruction.

Syntax of a Macro

The parts which make up a macro are:
Declaration of the macro
Code of the macro
Macro termination directive

The declaration of the macro is done the following way:

NameMacro MACRO [parameter1, parameter2...]

Even though we have the functionality of the parameters it is possible to create a macro which does not need them.

The directive for the termination of the macro is: ENDM

An example of a macro, to place the cursor on a determined position on the
screen is:

Position MACRO Row, Column
PUSH AX
PUSH BX
PUSH DX
MOV AH, 02H
MOV DH, Row
MOV DL, Column
MOV BH, 0
INT 10H
POP DX
POP BX
POP AX
ENDM

To use a macro it is only necessary to call it by its name, as if it were
another assembler instruction, since directives are no longer necessary as in
the case of the procedures. Example:

Position 8, 6
Macro Libraries
One of the facilities that the use of macros offers is the creation of
libraries, which are groups of macros which can be included in a program from a different file.

The creation of these libraries is very simple, we only have to write a file
with all the macros which will be needed and save it as a text file.

To call these macros it is only necessary to use the following instruction
Include NameOfTheFile, on the part of our program where we would normally write the macros, this is, at the beginning of our
program, before the declaration of the memory model.

Supposing the macros file was saved with the name of MACROS.TXT, the instruction Include would be used the following way:

;Beginning of the program
Include MACROS.TXT
.MODEL SMALL
.DATA
;The data goes here
.CODE
Beginning:
;The code of the program is inserted here
.STACK
;The stack is defined
End beginning
;Our program ends

Examples:

One of the simplest programs, but practical in a certain form, is one which
displays a chain of characters on screen. That is what the following program
does:

Program:

MODEL SMALL ; First we define the memory model, in this case small.
.CODE ; We declare the area which will contain the code.
Beginning: ; Beginning of the program label.
MOV AX,@DATA ; We are going to place the data segment address.
MOV DS,AX ; On DS, using AX as an intermediary.
MOV DX,OFFSET Chain ; We place the address in DX, inside the
; segment of the chain to display.
MOV AH,09 ; We will use the 09 function of the interruption.
INT 21H ; 21H To display the chain.
MOV AH,4CH ; Through the 4CH function of the interruption.
INT 21H ; 21H We will end our program.
.DATA ; We declare the data segment.
Chain DB 'Program message.$' ; Chain to display.
.STACK ; We declare the stack.
END Beginning ; End of our program.
A program very similar to this one has already been explained thus it does
not require any additional commentaries.

When a program is created it is not necessary to write the commentaries
which go after the quotation marks, though it is a recommendable technique
so that in case of errors or improvements to the code it may be easier to
find the desired part.

To assemble this program it first is saved in ASCII format with a valid
name, for example: program1.asm

To assemble it the MASM is used, the assembling command is: MASM program1

To link it and make it executable we type: link program1

Once these steps are finished, it is possible to execute it by typing:
program1 [ENTER]

To directly use the program on your computer save this file as ASCII or
text, take it to your PC, with an editor get rid of all these commentaries
from the beginning and assemble it.

This program displays the 16 characters corresponding to the hexadecimal
code in a descending order.

Program:
; Beginning of the program, we define the memory model
; to use and the code segment.
MODEL SMALL ; Memory model.
.CODE ; Code area.
Beginning: ; Beginning of the program label.

MOV AX, @DATA ; The DS register begins with the address given
MOV DS, AX ; by @DATA (Data segment).
MOV DX, OFFSET Title ; It obtains the address of the chain of characters.
MOV AH,09 ; We use the 09H function of the 21H interruption
INT 21H ; to display the chain whose address we obtained.
MOV CX,16 ; Counter of the characters to be shown.
MOV BX, OFFSET Chain ; It allows access to the chain where the values
; to display are.


Cycle: ; Label to generate a cycle.
MOV AL,CL ; It places the number to translate in AL and
; translates it
XLAT ; using the XLAT instruction
MOV DLAL ; It places the value to be displayed in DL through the
MOV AH,02 ; function 2 of the 21H interruption
INT 21H ; It displays the character
MOV DL,10 ; It jumps a line displaying the character 10
INT 21H ; It displays the character
MOV DL,13 ; It produces a carriage return displaying
; the character 13
INT 21H ; It displays the carriage return
LOOP Cycle ; It decreases CX by one and it jumps the Cycle
; as long as CX is not equal to zero
MOV AH,4C ; It uses the 4C function of the 21H interruption to
INT 21H ; end the program

; Beginning of the data segment
.DATA ; It defines the data segment
Title DB 13,10, 'Display the hexadecimal numbers from 15 to 1'
DB 13,10,'$' ; Chain to display at the beginning of the program
Chain DB '0123456789ABCDEF' ; Chain with the hexadecimal digits
; Declaration of the stack segment
.STACK
END Beginning ; Declaration of the end of the program
The XLAT looks for the chain or table located in BX, the AL register
contains the number of bytes, from the beginning address which the pointer
will go over it to search for data, the content of AL is replaced by the
byte where the pointer is found.

The assembling process is equal to the prior example.

On the following example most of the instructions seen in the tutorial are
used, their objective is to perform adding, subtracting, multiplying
operations as well as division of two quantities.

To access each one of the available options the menu is used and where the
available operations are presented.

Program:
.MODEL SMALL ; It defines the memory model
.DATA ; It defines the data segment

ErrorCAP DB 0 ; Error flag in the capture of the quantities
Quantity DB 0 ; Quantity on which it is operated. If it is 0 the quantity
; signals 1, and if it is 1 it signals 2.
QuantOneR DW 0 ; It will save the quantity of 1 converted into binary
QuantTwoR DW 0 ; It will save the quantity of 2 converted into binary
QuantOneN DB 6,0,6 DUR(?) ; Variable which stores the quantity of 1
QuantTwoN DB 6,0,6 DUR(?) ; Variable which stores the quantity of 2
Function DB 0 ; Variable which stores the option to perform
Results DB 13,10,'Result: $'
ResultsR DB 11 DUP(?)
Message DB 13,10,'Basic operations between two numbers'
DB 13,10,13,10,'$'
Question DB13,10,'Press:',13,10
DB ' 1 Multiplication ',13,10
DB ' 2 Division ',13,10
DB ' 3 Addition',13,10
DB ' 4 Subtraction ',13,10
DB ' 5 Exit ',13,10,'$'
Error DB 7,13,10,'Invalid selection (1-5)',13,10,'$'
Error1 DB 7,13,10,'Quantity 1 invalid. ',13,10,'$'
Error2 DB 7,13,10,'Quantity 2 invalid. ',13,10,'$'

Error3 DB 7,13,10,'Quantity out of range (65535) ',13,10,'$'
Error4 DB 7,13,10,'Intent of division by zero. ',13,10,'$'
QuantOneM DB 13,10,'Introduce quantity 1 (Less than 65535): $'
QuantTwoM DB 13,10,'Introduce quantity 2 (Less than 65535): $'

; Potencies table for binary/ASCII conversion

Potency DW 0001h, 000Ah, 0064h, 03E8h, 2710h
PotencyF DW $

.CODE ; It defines the code area
Begins: ; Beginning of the program label

Mov AH, 0Fh ; It obtains current video mode
INT 10h
Mov AH,00 ; It changes the video mode to the same prior
INT 10h ; with the finality that the screen is cleared
Mov AX, @Data ; It obtains the data segment address
Mov Ds, Ax ; It initializes DS with this address
Mov Dx, Offset Message ; It displays the program title
Call Print ; It calls a procedure
Mov Is, Offset ResultsR ; The ResultsR variable initializes
Add Si,11
Mov Al,'$'
Mov [Is], Al

ANOTHER:
Mov Dx,Offset Question ; It displays options menu
Call Print
Call ObtainKey ; It waits for the desired option to be pressed
Cmp Al, 49 ; It compares the selection with the ASCII l digit
Jae CONTINUE ; If the option is greater than 1 it jumps CONTINUE
Mov Dx, Offset Error ; It displays an error message
Call Print

Jmp ANOTHER ; It jumps ANOTHER to ask again
CONTINUE:
Cmp Al,53 ; It compares the selection with the ASCII 5 digit
Jbe ALLWELL ; If it is less than 5 it jumps ALLWELL, if not it
; continues to
Mov Dx,Offset Error ; If the option was greater than 5 it displays the
; error
Call Print
Jmp ANOTHER
ALLWELL:
Cmp Al,53 ; It compares the selection with the ASCII digit 5
Jnz CHECKALL ; If it is not the same it jumps to CHECKALL
Jmp FUNCTION5 ; If it is equal it jumps to FUNCTION5 to end
CHECKALL:
Mov Function,Al ; It saves the function number to perform
CAPCANT01:
Mov Dx, Offset QuantOneM ; Capture message of quantity 1
Call Print
Mov Ah,OAh ; It captures the quantity (up to 8 digits)
Mov Dx, Offset QuantOneN
INT 21h
Mov ErrorCap, O ; It assumes there are no errors and that it
Mov Quantity, O ; is operating on the quantity 1
Call Conv NUM ; It converts the quantity 1 into binary
Cmp ErrorCAP, 1 ; It verifies if there is no error
Jz CAPCANTO1 ; In case it is affirmative it returns to the
; capture.
Mov QuantOneR, Bx ; It saves the result of the conversion
CAPCANTO2:

Mov ErrorCAP, O ; It assumes there is no error
Mov Quantity, 1 ; It indicates to ConvNUM that it will work
; with the quantity of 2
Mov Dx, Offset QuantTwoM ; Capture of quantity of 2 message

Call Print
Mov Ah, OAh ; Capture of quantity 2
Mov Dx, Offset QuantTwoM
INT 21H
Call ConvNum ; It converts the quantity 2 into binary
Cmp ErrorCAP, 1 ; It verifies if there was any errors
Jz, CAPCANTO2 ; In case it is affirmative it returns to
; the capture
Mov QuantTwoR, Bx ; It stores the binary value of the quantity of 2

;The following part is the process of selection of the operation to be
;performed:

Mov Al, Function ; It loads the function the user selected in Al
Cmp Al, 31h ; It checks if it is 1
Jne FUNCTION2 ; If it is not it jumps to FUNCTION2
Call Multiply ; It multiplies the quantities
Jmp ANOTHER ; It returns to the main menu

FUNCTION2:
Cmp Al, 32h ; Checks if it is 2
Jne FUNCTION3 ; If it is not it jumps to FUNCTION3
Call Divide ; It divides the quantities
Jmp ANOTHER

FUNCTION3:
Cmp Al, 33h ; Checks if it is 3
Jne FUNCTION4 ; If it is not it jumps to FUNCTION4
Call Addition ; It adds the quantities
Jmp ANOTHER

FUNCTION4:
Cmp Al, 34h ; Checks if it is 4
Jne FUNCTION5 ; If it is not it jumps to FUNCTION5

Call Subtraction ; It subtracts the quantities
Jmp ANOTHER

FUNCTION5:
Mov Ax, 4000h ; This function ends the execution
INT 21h ; of the program
;Program procedures or routines
Multiply Proc Near ; Indicator of procedure beginning
Xor Dx,Dx ; Dx = 0
Mov Ax, QuantOneR ; First quantity
Mov Bx, QuantTwoR ; Second quantity
Mul Bx ; It multiplies
Call Conv ASCII ; It converts into ASCII
Mov Dx, Offset Results ; It prints the result message
Call Print
Mov Dx, Offset ResultsR ; It prints the result
Call Print
Ret ; It returns to the main program
Multiply Endp ; End of procedure indicator

Divide Proc Near
Mov Ax, QuantOneR ; It loads the quantity 1 (dividend)
Mov Bx, QuantTwoR ; It loads the quantity 2 (divider)
Cmp Bx, 0 ; It checks the divider is not zero
Jnz DIVIDE1 ; If it is not zero it jumps to DIVIDE01
Mov Quantity, 3 ; There was an error so it displays the message and
; returns to the program
Call ThereWasError
Ret


DIVIDE01:
Div Bx ; It performs the division
Xor Dx, Dx ; Dx = 0. The residue is not used.
Call Conv ASCII ; It converts into ASCII the result
Mov Dx, Offset Results ; It displays the message of the result
Call Print
Mov Dx, Offset ResultsR ; It displays the result
Call Print
Ret
Subtract Endp

Print Proc Near
mov Ah,09 ; It uses the 9 function of the 21h interruption
INT 21h ; to display a chain
Ret
Print Endp

ObtainKey Proc Near
Mov ah, 0 ; It uses the 16h interruption to
INT 16h ; read a key
Ret
ObtainKey Endp

ConvNum Proc Near
Mov Dx, 0Ah ; The multiplier is 10
Cmp Quant, 0 ; Verifies if the quantity is 1
Jnz CONVNUM01 ; It was not, then it is quantity 2 and jumps
Mov Di, Offset QuantOneN + 1 ; Number of bytes read of quantity 1
Mov Cx, [D1]
Mov S1 Offset QuantOneN + 2 ; Quantity 1
Jmp CONVNUM02
CONVNUM01:
Mov D1, OffsetQuantTwoN + 1 ; Number of bytes read of quantity 2
Mov Cx, [D1]

Mov Is, Offset QuantTwoN + 2 ; Quantity 2
CONVNUM02:
Xor Ch, Ch, CH = 0
Mov D1, Offset Potency ; Potency table address
Dec Is
Add Is, Cx
Xor Bx, Bx
Std
CONVNUM3:
Lodsb ; It loads the byte whose address is DS:SI in AL
Cmp Al, "0" ; It compares the byte with the digit 0
Jb CONVNUM04 ; If it is smaller it is invalid and jumps
Cmp Al, "9" ; It compares the byte with the digit 9
Ja CONVNUM04 ; If it is larger it is invalid and jumps
Sub Al, 30h ; It converts the digit from ASCII to binary
Cbw ; It converts the word
Mov Dx, [Di] ; It obtains the potency to be used to multiply
Mul Dx ; It multiplies the number
Jc CONVNUM05 ; If there is cartage it jumps ( it was larger than 65535 )
Add Bx, Ax ; It adds the result to BX
Jc CONVNUM05 ; If there is cartage it jumps
Add Di, 2 ; It goes to the next potency of 10
Loop CONVNUM03 ; It jumps until CX is equal to 0
Jmp CONVNUM06
CONVNUM04:
Call TherewasERROR ; It means the number was larger than 65535
Jmp CONVNUM06
CONVNUM5:
Mov Cantidad, 2
Call TherewasERROR
CONVNUM06:
Cld ; It returns the address flag to its normal
Ret ; state
ConvNum Endp

ConvASCII Proc Near
Push Dx
Push Ax ; It saves the result of the stack
Mov Is, Offset ResultsR ; Initializes the ResultsR variable
Mov Cx, 10 ; surrounding it with asterisks
Mov Al, '*'
ConvASCII01:
Mov [Is], Al
Inc Is
Loop ConvASCII01
Pop Ax
Pop Bx
Mov Bx, Ax ; Low word of the quantity
Mov Ax, Dx ; High word of the quantity
Mov Is, Offset ResultsR ; Chain where the result is kept
Add Is, 11
Mov Cx, 10 ; Divider = 10
OBTAINDIGIT:
Dec Is
Xor Dx, Dx ; Dx will contain the residue
Div Cx ; It divides the high word
Mov Di, Ax ; It saves the quotient in DI
Mov Ax, Bx ; It loads the high word in AX
Div Cx ; DX contains the register of the division
Mov Bx, Ax ; It saves the quotient
Mov Ax, Di ; It returns the high word
Add Dl, 30h ; It converts the residue in ASCII
Mov [Is], Dl ; It stores it
Or Ax, Ax ; If the high word is not zero
Jnz OBTAINDIGIT ; it jumps to OBTAINDIGIT
Or Bx, Bx ; If the low word is not zero
Jnz OBTAINDIGIT ; it jumps to OBTAINDIGIT
Ret
ConvASCII Endp

TherewasERROR Proc Near
Cmp quantity, 0 ; Is it quantity 1?
Jnz THEREWASERROR02 ; no
Mov Dx, Offset Error1
Call Prit
Mov ErrorCap, 1 ; It turns on the error flag
Jmp THEREWASERROR05
THEREWASERROR02:
Cmp Quantity, 1 ; Is it quantity 2?
Jnz THEREWASERROR03 ; no
Mov Dx, Offset Error2
Call Print
Mov ErrorCAP, 1
Jmp THEREWASERROR05
THEREWASERROR03:
Cmp Quantity, 2 ; Is it an out of range quantity?
Jnz THEREWASERROR04 ;no
Mov Dx, Offset Error3
Call print
Mov ErrorCAP, 1
Jmp THEREWASERROR05
THEREWASERROR04:
Mov Dx, Offset Error4 ; Division by zero error
Call Print
Mov ErrorCAP, 1
THEREWASERROR05:
Ret
TherewasERROR Endp

.STACK
End Begin


Mov Dx, Offset Results ; It displays the message of the result
Call Print
Mov Dx, Offset ResultsR ; It displays the result
Call Print
Ret
Divide Endp

Addition Proc Near
Xor Dx, Dx ; Dx = 0 just in case there is cartage
Mov Ax, QuantOneR ; Quantity 1
Mov Bx, QuantTwoR ; Quantity 2
Add Ax, Bx ; It performs the addition
Jnc ADDCONV ; If there was no cartage it jumps to ADDCONV
Adc Dx,0 ; There was
ADDCONV:
Call ConvASCII ; It converts the result into ASCII
Mov Dx, Offset Results ; It displays the message of the result
Call Print
Ret
Addition Endp

Subtract Proc Near
Xor Dx, Dx ; Dx = 0 in case there is cartage
Mov Ax, QuantOneR ; Ax = quantity 1
Mov Bx, QuantTwoR ; Bx = quantity 2
Sub Ax, Bx ; It performs the subtraction
Jnc SUBCONV ; If there is no cartage it jumps to SUBCONV
Sbb Dx,0 ; There is cartage
SUBCONV:
Call ConvASCII ; Converts the result into ASCII

bar.gif (11170 bytes)

Prev || Home