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