about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-09-21 15:10:34 -0700
committerKartik Agaram <vc@akkartik.com>2018-09-21 15:22:08 -0700
commitd9818a5333805148586b7ac14c22f5dd413f593e (patch)
treeefa70a8848997489be2c5d76da5597b91470c937 /subx
parent0d8d7618f1484e35706df4db1a61a5fefc2d63e0 (diff)
downloadmu-d9818a5333805148586b7ac14c22f5dd413f593e.tar.gz
4575
New example, just to fix in my head how arguments go on the stack.

It's possible I'm still confused about the order callers push args in to
the stack. But even if this violates the calling convention, it should
still run.
Diffstat (limited to 'subx')
-rwxr-xr-xsubx/examples/ex9bin0 -> 129 bytes
-rw-r--r--subx/examples/ex9.subx49
2 files changed, 49 insertions, 0 deletions
diff --git a/subx/examples/ex9 b/subx/examples/ex9
new file mode 100755
index 00000000..874efe52
--- /dev/null
+++ b/subx/examples/ex9
Binary files differdiff --git a/subx/examples/ex9.subx b/subx/examples/ex9.subx
new file mode 100644
index 00000000..aa519dc1
--- /dev/null
+++ b/subx/examples/ex9.subx
@@ -0,0 +1,49 @@
+## Example showing arg order on the stack.
+# Show difference between ascii codes of first letter of first arg and first
+# letter of second arg.
+#
+# To run:
+#   $ subx translate ex9.subx ex9
+#   $ subx run ex9 z x
+# Expected result:
+#   $ echo $?
+#   2
+#
+# At the start of a SubX program:
+#   argc: *ESP
+#   argv[0]: *(ESP+4)
+#   argv[1]: *(ESP+8)
+#   ...
+# Locals start from ESP-4 downwards.
+
+== code
+# 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
+  # s1 = argv[1] (EAX)
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              0/r32/EAX   8/disp8         .                 # copy *(ESP+8) to EAX
+  # s2 = argv[2] (EBX)
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              3/r32/EBX   0xc/disp8       .                 # copy *(ESP+12) to EBX
+  # call string_equal(s1, s2)
+    # push args
+  50/push                         .               .             .           .             .           .           .               .                 # push EAX
+  53/push                         .               .             .           .             .           .           .               .                 # push EBX
+    # call
+  e8/call  ascii_difference/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
+  # exit(EAX)
+  89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to EBX
+  b8/copy                         .               .             .           .             .           .           .               1/imm32/exit      # copy 1 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8         # int 80h
+
+ascii_difference:  # (s1, s2) : null-terminated ascii strings
+  # a = first letter of s1 (ECX)
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              0/r32/EAX   8/disp8                           # copy *(ESP+8) to EAX
+  8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # copy *EAX to EAX
+  # b = first letter of s2 (EDX)
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              1/r32/ECX   4/disp8                           # copy *(ESP+4) to ECX
+  8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # copy *ECX to ECX
+  # a-b
+  29/subtract                     3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # subtract ECX from EAX
+  c3/return