about summary refs log tree commit diff stats
path: root/subx/ex7.subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx/ex7.subx')
-rw-r--r--subx/ex7.subx90
1 files changed, 90 insertions, 0 deletions
diff --git a/subx/ex7.subx b/subx/ex7.subx
new file mode 100644
index 00000000..c95ed361
--- /dev/null
+++ b/subx/ex7.subx
@@ -0,0 +1,90 @@
+## compute the factorial of 5, and return the result in the exit code
+#
+# To run:
+#   $ subx translate ex7.subx ex7
+#   $ subx run ex7
+# Expected result:
+#   $ echo $?
+#   120
+
+== 0x08048054  # code segment, after leaving room for ELF header
+# instruction                     effective address                                           operand     displacement    immediate
+# op          subop               mod             rm32          base      index     scale     r32
+# 1-3 bytes   3 bits              2 bits          3 bits        3 bits    3 bits    2 bits    2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+
+# main:
+  # prepare to make a call
+# 54
+  55/push                                                                                                                                   # push EBP
+# 55
+  89/copy                         3/mod/direct    5/rm32/EBP                                  4/r32/ESP                                     # copy ESP to EBP
+# 57
+  # factorial(5)
+  68/push                                                                                                                 5/imm32           # push 5
+# 5c
+  e8/call                                                                                                 factorial/disp32
+# 61
+  # discard arg
+  5a/pop                                                                                                                                    # pop into EDX
+# 62
+  # clean up after call
+  89/copy                         3/mod/direct    4/rm32/ESP                                  5/r32/EBP                                     # copy EBP to ESP
+# 64
+  5d/pop                                                                                                                                    # pop to EBP
+
+  # exit(EAX)
+# 65
+  89/copy                         3/mod/direct    3/rm32/EBX                                  0/r32/EAX                                     # copy EAX to EBX
+# 67
+  b8/copy                                                                                                                 1/imm32           # copy 1 to EAX
+# 6c
+  cd/syscall                                                                                                              0x80/imm8         # int 80h
+
+# factorial(n)
+# 6e
+factorial:
+  # initialize n
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/esp   4/index/none     2/r32/edx   4/disp8                           # copy *(ESP+4) to EDX
+# 72
+  # initialize EAX to 1 (base case)
+  b8/copy                                                                                                                 1/imm32           # copy 1 to EAX
+# 77
+  # if (n <= 1) jump exit
+  81          7/subop/compare     3/mod/direct    2/rm32/EDX                                                              1/imm32           # compare EDX with 1
+# 7d
+  7e/jump-if                                                                                              factorial:exit/disp8              # jump if <= to exit
+# 7f
+  # EBX: n-1
+  89/copy                         3/mod/direct    3/rm32/EBX                                  2/r32/EDX                                     # copy EDX to EBX
+# 81
+  81          5/subop/subtract    3/mod/direct    3/rm32/EBX                                                              1/imm32           # subtract 1 from EBX
+# 87
+  # prepare call
+  55/push                                                                                                                                   # push EBP
+# 88
+  89/copy                         3/mod/direct    5/rm32/EBP                                  4/r32/ESP                                     # copy ESP to EBP
+  # EAX: factorial(n-1)
+# 8a
+  53/push                                                                                                                                   # push EBX
+# 8b
+  e8/call                                                                                                 factorial/disp32
+# 90
+  # discard arg
+  5e/pop                                                                                                                                    # pop into ESI
+# 91
+  # clean up after call
+  89/copy                         3/mod/direct    4/rm32/ESP                                  5/r32/EBP                                     # copy EBP to ESP
+# 93
+  5d/pop                                                                                                                                    # pop to EBP
+# 94
+  # refresh n
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/esp   4/index/none     2/r32/edx   4/disp8                           # copy *(ESP+4) to EDX
+# 98
+  # return n * factorial(n-1)
+  0f af/multiply                  3/mod/direct    2/rm32/EDX                                  0/r32/EAX                                     # multiply EDX (n) into EAX (factorial(n-1))
+  # TODO: check for overflow
+# 9b
+factorial:exit:
+  c3/return
+
+# vim:ft=subx:nowrap:so=0