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