Lab 5: Solutions¶
Example using a subprogram to calculate an average¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | ; include directives
global asm_main
%include "../lib/asm_io.inc"
segment .data
msg_int db "Enter an integer: ", 0
msg_avg db "The average of the registers is: ", 0
segment .bss
; RESX directives (writable data)
segment .text
asm_main: ; entry point (called from driver.c)
; instructions
enter 0,0 ; Initialize register EBP
pusha ; Push register contents to the stack
;
mov eax, msg_int
call print_string ; Get int
call read_int ; eg: EAX = 256 (0x0100)
mov ebx, eax ; copy to other registers
mov ecx, eax
mov edx, eax
shl ebx, 1 ; perform a left bit shift of 1 place
shl ecx, 2 ; perform a left bit shift of 2 places
shl edx, 3 ; perform a left bit shift of 3 places
;
call print_nl
;
; Example
; EAX = 00000100 EBX = 00000200 ECX = 00000400 EDX = 00000800
dump_regs 0 ; verify registers (debug)
;
call average ; Calculates the average, store in EAX
;
; Registers EBX, ECX, and EDX should be unchanged
; EAX contains the average: 256+512+1024+2048 / 4 = 960 (0x03C0)
;
; EAX = 00000027 EBX = 0000001F ECX = 0000002F EDX = 0000003F
dump_regs 2 ; verify registers (debug)
;
mov ecx, eax ; save the returned value in EAX
mov eax, msg_avg ; Move string to print
call print_nl
call print_string
mov eax, ecx ; Move avg to EAX to print
call print_int
call print_nl
;
popa ; Restore register data from the stack
mov eax, 0 ; flush EAX of data
leave ; restore the stack
ret ; Return from main back into C library wrapper
;---------------------------------------------------------------
; FUNCTION: average
; - Sums the values in EAX, EBX, ECX and EDX and then calculates
; the average. The remainder in EDX is discarded.
; - Returns the average returns the result in EAX.
;---------------------------------------------------------------
segment .bss
returnvalue resd 1 ; place in memory for the return value
segment .text
average:
push ebp ; save original EBP
mov ebp, esp ; set EBP = ESP
pusha ; save all (including new EBP)
add eax, ebx ; The sum of EAX and EBX
add eax, ecx ; The sum of EAX, EBX, and ECX
add eax, edx ; The sum of EAX, EBX, ECX, and EDX
mov edx, 0 ; Initialize for remainder
mov ecx, 4 ; Set the divisor
div ecx ; divide the sum to find the average
dump_regs 1 ; verify registers (debug)
; Place return value in EAX
mov [returnvalue], eax ; save return value in memory
popa ; restore all (including new EBP)
mov eax, [returnvalue] ; retrieve the saves return value
pop ebp ; restore original ebp
ret ; return
|