1 ; Chapter 4 "Power Function"
     
2 ; 
     
3 ; Computes the value of 2^3 + 5^2, exits with value.
     
4 ; Demonstrates how functions work.
     
5 ;
     
6 ;    $ ./go.sh ch04.1_power_function
     
7 ;    Exited with code: 33
     
8 ;
     
9 
    10 section .data
    
11 
    12 section .text
    
13 
    14 ; Start - Call power twice, return result
    
15 ; ---------------------------------------------------------
    
16 global _start
    
17 _start:
    
18     push dword 3     ; second arg, push immediate value onto stack
    
19     push dword 2     ; first arg, pushed last!
    
20     call power
    
21 
    22     add esp, 8       ; move stack pointer back to "erase" args
    
23     push eax         ; save current answer on stack
    
24 
    25     push dword 2     ; second arg
    
26     push dword 5     ; first arg
    
27     call power
    
28 
    29     add esp, 8       ; move stack pointer back to "erase" args
    
30     pop ebx          ; put previous saved answer into ebx
    
31     add ebx, eax     ; add current answer to previous
    
32 
    33     ; exit! ebx contains answer and is "returned" as exit code
    
34     mov eax, 1       ; linux syscall 'exit'
    
35     int 0x80
    
36 
    37 ; power function
    
38 ; ---------------------------------------------------------
    
39 ; input:
    
40 ;   arg1 -> ebx   is the base number
    
41 ;   arg2 -> ecx   is the exponent to raise base by
    
42 ; output:
    
43 ;   answer in eax
    
44 ;
    
45 ; Note: We're not testing this function externally yet,
    
46 ;       but I *think* I have properly translated this
    
47 ;       global function directive (elf specific?) to NASM:
    
48 global power:function
    
49 power:
    
50     ; We move the stack pointer FORWARD to make room for 4 bytes
    
51     ; of space for a "local variable" in traditional C function
    
52     ; style. We point the base pointer register, ebp, to the
    
53     ; the current stack position so we can use it to reference
    
54     ; relative parts of the stack for "private use" in our
    
55     ; function. Again, this is just a style or convention.
    
56     push ebp       ; save previous base pointer
    
57     mov ebp, esp   ; set it to stack pointer
    
58     sub esp, 4     ; move pointer FORWARD to make room
    
59 
    60     mov ebx, [ebp + 8]  ; first arg - base number
    
61     mov ecx, [ebp + 12] ; second arg - exponent
    
62     mov [ebp - 4], ebx  ; store base number as start of total
    
63 
    64 power_loop_start:
    
65     cmp ecx, 1          ; once power is 1, we're done!
    
66     je end_power
    
67     mov eax, [ebp - 4]  ; put total in eax
    
68     imul eax, ebx       ; multiply total by base
    
69     mov [ebp - 4], eax  ; store total
    
70     dec ecx             ; reduce power by 1
    
71     jmp power_loop_start
    
72 
    73 end_power:
    
74     mov eax, [ebp - 4]  ; put total in eax to return
    
75     mov esp, ebp        ; restore stack pointer
    
76     pop ebp             ; restore base pointer (we pushed it)
    
77     ret