Introduction to Procedures
Introduction to Procedures
Statement Purpose:
Student will know about the built-in functions and user defined functions that can be employed in programs to make development faster and make programs modular.
Activity Outcomes:
This lab teaches you the following topics:
- Understand how to call built-in functions in Assembly?
- Understand how to create your own function in assembly
- Arguments passing
- What are stack frames?
- How stack frame are created and destroyed?
- Recursive procedure and their
Instructor Note:
As pre-lab activity, read Chapter 5 from the book (Assembly Language for X86 processors, KIP
- IRVINE., 7th Edition (2015), Pearson), and also as given by your theory instructor.
Introduction
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.
The advantages of using procedures are:
- Improves code readability because the code does not need to be laid out as one long
- Allows code to be reused because it can be written once and called from more than one place in the
- Allows tasks to be broken down into simpler components because procedures can be written for certain tasks (procedures can also call other procedures).
- Modular code facilitates
A procedure is always enclosed within some code segment. A procedure is defined as:
PROCEDURE_NAME PROC
.
.
.
PROCEDURE_NAME ENDP
where PROCEDURE_NAME is any valid identifier.
The PROC directive usually includes one of the operands NEAR or FAR. Example:
PROCEDURE_NAME PROC FAR
..
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.
Built-In vs. User Defined
Students will be introduced to built-in procedures included in Irvine32 Library. They just need to call those procedures. Students will make their own procedures as well and call them at various places of their programs.
A procedure is invoked by a CALL instruction that can be direct or indirect. A direct procedure call has the format:
CALL PROCEDURE_NAME
In an indirect near procedure call, the operand for the CALL instruction is either a 16-bit general- purpose register or a memory word containing the offset address of the procedure.
Activities:
Activity 1:
Write a program that displays the same string in four different colors, using a loop. Call the SetTextColor procedure from the book’s link library. Any colors may be chosen, but you may find it easiest to change the foreground color.
Solution:
INCLUDE Irvine32.inc
.data
str1 BYTE “This line is displayed in color”,0
.code
main PROC
mov eax, black + (white * 16) ; black on white background mov ecx,4 ; loop counter
L1: call SetTextColor mov edx, OFFSET str1
call WriteString
call Crlf
add eax,2 ; add 2 to foreground color loop L1
exit main ENDP END main
Activity 2:
Write a program that clears the screen, locates the cursor near the middle of the screen, prompts the user for two integers, adds the integers, and displays their sum.
Solution:
INCLUDE Irvine32.inc
.data
val1 SDWORD ? val2 SDWORD ?
str1 BYTE “Enter first integer: “,0 str2 BYTE “Enter second integer: “,0 str3 BYTE “The sum is: “,0
.code
main PROC
call ClrScr
; Input the first integer
mov dh,10 mov dl,20 call Gotoxy
mov edx, OFFSET str1
call WriteString call ReadInt mov val1,eax
; Input the second integer
mov dh,12 mov dl,20 call Gotoxy
mov edx, OFFSET str2 call WriteString
call ReadInt
add eax,val1
; Display the sum
mov dh,14 mov dl,20 call Gotoxy
mov edx, OFFSET str3 call WriteString
call WriteInt call Crlf
call Crlf
exit main ENDP END main
Activity 3:
Create two procedures:
- SetColor receives two BYTE parameters: forecolor and It calls the SetTextColor procedure from the Irvine32 library.
- WriteColorChar receives three byte parameters: char, forecolor, and backcolor. It displays a single character, using the color attributes specified in forecolor and It calls the SetColor procedure, and it also calls WriteChar from the Irvine32 library. Both SetColor and WriteColorChar must contain declared parameters. Write a short test program that test both procedures. Be sure to create PROTO declarations for SetColor and WriteColorChar.
Solution:
INCLUDE Irvine32.inc
SetColor PROTO forecolor: BYTE, backcolor: BYTE
WriteColorChar PROTO char:BYTE,forecolor:BYTE, backcolor: BYTE
.data
.code
main PROC
INVOKE WriteColorChar, ‘A’, white, blue INVOKE WriteColorChar, ‘B’, blue, white INVOKE WriteColorChar, ‘C’, green, black INVOKE WriteColorChar, ‘D’, yellow, gray
INVOKE SetColor, lightGray, black call Crlf
exit
main ENDP
WriteColorChar PROC USES eax,
char:BYTE,forecolor:BYTE, backcolor: BYTE,
INVOKE SetColor, forecolor, backcolor mov al,char
call WriteChar
ret WriteColorChar ENDP
SetColor PROC USES eax,
forecolor: BYTE, backcolor: BYTE
movzx eax,backcolor shl eax,4
add al,forecolor call SetTextColor
ret SetColor ENDP
END main
Activity 4:
Write a wrapper procedure for the link library’s DumpMem procedure, using stack parameters. The name can be slightly different, such as DumpMemory. The following is an example of how it should be called:
INVOKE DumpMemory,OFFSET array,LENGTHOF array,TYPE array
Write a test program that calls your procedure several times, using a variety of data types.
Solution
INCLUDE Irvine32.inc
DumpMemory PROTO, address: DWORD, units: DWORD, unitType:DWORD
.data
array DWORD 1,2,3,4,5,6,7,8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh array1 WORD 0,9,8,7,6,5,4,3,2,1
array2 BYTE ‘1’,’2′,’3′,’4′,’5′
.code
main PROC
INVOKE DumpMemory,OFFSETarray,LENGTHOFarray,TYPE array INVOKE DumpMemory, OFFSET array1,LENGTHOF array1,TYPE array1 INVOKE DumpMemory, OFFSET array2,LENGTHOF array2,TYPE array2
exit main ENDP
; DumpMemory PROC USES esi ebx ecx,
address: DWORD, ; starting address
units: DWORD, ; number of units
unitType:DWORD ; unit size
;
; Wrapper procedure for the link library’s DumpMem procedure
; Receives: nothing
; Returns: nothing
;
mov esi, address mov ecx, units mov ebx, unitType call DumpMem
ret
DumpMemory ENDP
END main
Activity 5:
Write a non-recursive version of the Factorial procedure that uses a loop. Write a short program that interactively tests your Factorial procedure. Let the user enter the value of n. If overflow occurs in your loop when calculating each factorial value, your program should display an error message. If no overflow occurs, display the calculated factorial.
Solution:
INCLUDE Irvine32.inc
.data
msgInput BYTE “Enter the value of n to calculate ”
BYTE “the factorial (-1 to quit): “,0 msgOutput BYTE “The factorial is: “,0
.code
main PROC
L1:
mov edx,OFFSET msgInput ; message to display call WriteString
call ReadInt ; get an integer from the user call Crlf
cmp eax, 0 ; is n less than 0 jl quit
call FactorialIterative ; EAX = factorial(n)
jc failed ; CF=1 if overflow occurred
push eax ; save the factorial
mov edx,OFFSET msgOutput call WriteString
pop eax ; restore the factorial
call WriteDec ; and display it
failed:
call Crlf call Crlf loop L1
quit: exit
main ENDP
; FactorialIterative PROC USES ecx edx
;
; Calculates a factorial non-recursively
; Receives: eax = value of n to calculate factorial
; Returns: if the result is valid, CF=0 and eax = calculated factorial
; If overflow occurred, CF=1 and EAX is unknown.
;
.data
factorialError BYTE “Error: Calculated value cannot ”
BYTE “fit into 32 bits”,0
.code
.IF eax == 0 || eax == 1 ; special cases
mov eax, 1 ; factorial == 1
jmp end_factorial ; quit procedure
.ENDIF
mov ecx, eax ; ecx = counter
Factorial_loop:
dec ecx ; ecx = n – 1
mul ecx ; eax = n * (n – 1)
jc error ; exit if overflow occurred
error:
cmp ecx, 1 ; is counter > 1?
ja Factorial_loop ; if true, keep looping jmp end_factorial
mov edx,OFFSET factorialError call WriteString
stc ; CF=1 indicates error
end_factorial:
ret FactorialIterative ENDP END main
Home Activities:
Home Task 1:
Write a program that compares the runtime speeds of both the recursive Factorial procedure and the non-recursive Factorial procedure written for the preceding programming exercise. Use the GetMseconds procedure from the book’s link library to measure and display the number of milliseconds required to call each Factorial procedure several thousand times in a row.
NOTE: A nested loop is used because the running time of a single loopis less than a millisecond
Home Task 2:
Write a recursive implementation of Euclid’s algorithm for finding the greatest common divisor (GCD) of two integers. Note: we will only test this procedure with nonnegative integers.
Home Task 3:
Write a procedure named ShowParams that displays the address and hexadecimal value of the 32-bit parameters on the runtime stack of the procedure that called it. Input to the procedure will be a single integer that indicates the number of parameters to display.
Home Task 4:
Write a program that draws an 8 X 8 chess board, with alternating colored and white squares. Each square is 2 characters wide and 1-character high. You can use the SetTextColor and Gotoxy procedures from the Irvine32 library. Avoid the use of global variables, and use declared parameters in all procedures. Use short procedures that are focused on a single task.
Home Task 5:
Write a program that draws an 8 X 8 chess board, with alternating colored and white squares. Each square is 2 characters wide and 1-character high. You can use the SetTextColor and Gotoxy procedures from the Irvine32 library. Avoid the use of global variables, and use declared parameters in all procedures. Use short procedures that are focused on a single task.
Home Task 6:
Write a program that draws an 8 X 8 chess board, with alternating colored and white squares. Each square is 2 characters wide and 1 character high. You can use the SetTextColor and Gotoxy procedures from the Irvine32 library. Every 500 milliseconds, change the color of the colored squares and redisplay the board. Continue until you have shown the board 16 times, using all possible 4-bit background colors. (The white squares remain white throughout.