L05 IntroductionToProcedures
L05 IntroductionToProcedures
INTRODUCTION TO PROCEDURES
•1 A procedure is a unit of code designed to perform a particular sub-task of some main task. It is written out only
once in some module, but can be used many times.
•1 Improves code readability because the code does not need to be laid out as one long sequence.
•2 Allows code to be reused because it can be written once and called from more than one place in the code.
•1 Allows tasks to be broken down into simpler components because procedures can be written for certain
tasks (procedures can also call other procedures).
PROCEDURE_NAME PROC
.
.
.
PROCEDURE_NAME ENDP
A NEAR procedure is defined in the same code segment from which it is called, and a FAR procedure is
ordinarily defined in a separate code segment. Note if none of the operands NEAR or FAR follows the PROC
directive, then the procedure is by default a NEAR procedure.
•3 A procedure may be invoked by a JMP instruction if it does not return control to the caller:
JMP PROCEDURE_NAME
2
•5 IP get the offset address of the first instruction of the procedure (this transfers control to the procedure)
Note: A procedure may have zero, one, or more RET instructions. A procedure will have no RET instruction in those
programming situations where we don’t want to return control to the caller.
.MODEL SMALL
.STACK 0400H
.DATA
. . .
.CODE
MAIN PROC
MOV AX , @DATA ; Initialize DS
MOV DS , AX ;
. . .
CALL SUB1
. . .
CALL SUB2
. . .
MOV AX , 4C00H ; Return to DOS
INT 21H
MAIN ENDP
SUB1 PROC
. . .
RET
SUB1 ENDP
SUB2 PROC
. . .
CALL SUB3
. . .
RET
SUB2 ENDP
SUB3 PROC
. . .
RET
SUB3 ENDP
END MAIN
3
Note: If the entry point is specified in the END directive, the procedures may appear in any order.
•1 Syntax of PUSH:
PUSH source
Where source is either imm8, imm16, imm32, segment register, 16- or 32-bit general purpose register. If
source is imm8, then the value is zero or sign extended to 16-bits.
•2 Syntax of POP:
POP destination
Where destination is either mem16, mem32, segment register, 16- or 32-bit general purpose register.
Thus only words or double-words are pushed or popped from the stack. An 8-bit immediate value pushed in the
stack is zero- or sign- extended to 16-bits.
Note: (a) Since the stack is used by the system to store addresses during procedure calls, and to store
addresses and the values of the flags during interrupts, it is necessary that to every PUSH instruction in
your program there is a corresponding POP instruction.
(b) To preserve the FLAGS register the instructions PUSHF and POPF are used.
To preserve the EFLAGS register the instructions PUSHFD and POPFD are used.
(c) PUSHA pushes the 16-bit general purpose registers in the order AX, CX, DX, BX, SP, BP, SI,
and DI. POPA pops the 16-bit general purpose registers in the reverse order of PUSHA.
PUSHAD pushes the 32-bit general purpose registers in the order EAX, ECX, EDX, EBX, ESP,
EBP, ESI,
EDI.
POPAD pops the 32-bit general-purpose registers in the reverse order of PUSHAD.
(d) USES directive: The PROC directive may have the form:
procedure_name PROC USES RegisterList
where:
RegisterList is a list of registers that are used by the procedure and which must be preserved. The
registers in the list are separated by spaces. Including a register in this list will cause the assembler
to automatically generate the necessary PUSH instruction to save the register value, and then to
generate the necessary POP instruction to restore the value of that register before control is returned
to the caller.
Example:
DISPLAY PROC USES AX BX CX
. . .
RET
DISPLAY ENDP
5
EXAMPLES
•3 Procedures should normally be general and not specific, i.e., a procedure must be written such that it can be used
by passing to it different parameters.
•2 Example3:
DISPLAY_CHAR PROC
PUSH AX
MOV AH , 02H
INT 21H
POP AX
RET
DISPLAY_CHAR ENDP
Note: In this procedure the AX register is not pushed and then popped (i.e., it is not preserved) because the
procedure returns a value to the calling program in the AL register. This procedure will be invoked by a call of the
form:
. . .
CALL READ_CHAR
. . .
7
high address
byte 200 ¬ SP
byte 199
byte 198
. stack segment
.
.
byte 1
byte 0 ¬ SS
low address
Notice that the SP register is initialized to point one byte beyond the stack. The reason is that when a PUSH
instruction:
PUSH Operand16
is executed the value in the SP register is automatically decremented by 2 and then the value of the word operand is
pushed into the stack at the new word pointed to by SP:
(SP) ¬ (SP) - 2
(Word at Top of Stack) ¬ (Operand16)
In the above example, the first word to be pushed into the stack will be stored at bytes 198 and 199. The state of the
stack after pushing one word is then:
high address
byte 200
byte 199 XX
byte 198 XX ¬ SP
. stack segment
.
.
byte 1
byte 0 ¬ SS
low address
· (SP) ¬ (SP) - 2
· (Word at top of Stack) ¬ (IP)
i.e., the offset address of the statement after the CALL statement is stored in the stack.
· (IP) ¬ offset address of first executable statement in the called procedure.
Since the logical address CS:IP now refers to the first executable statement in the called NEAR
procedure, program execution continues with the execution of the procedure statements.
When a RET instruction is executed in the procedure the following sequence of events occurs:
Since now the logical address CS:IP refers to the statement, in the calling program, after the CALL
statement, program execution continues from that statement.
Note: For a NEAR procedure call the value of CS is not pushed in the stack, because both the calling program and
the called procedure are in the same code segment; the value of CS does not change.