about summary refs log tree commit diff stats
path: root/subx/052argv_equal.subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-10-01 12:22:59 -0700
committerKartik Agaram <vc@akkartik.com>2018-10-01 12:27:39 -0700
commit57628c0e4461b8bb6e6024135bf1e7f46f650030 (patch)
tree52a9f28ac189dee50b63ceeb723d7a872701dab3 /subx/052argv_equal.subx
parent5ece295328f872fa368e7852f62f363eb701c0f9 (diff)
downloadmu-57628c0e4461b8bb6e6024135bf1e7f46f650030.tar.gz
4638 - extract some common libraries from apps
I'm still trying to figure out what the defaults should be. At the moment
you have to explicitly pass in every file you want loaded into the output
binary. Maybe that control is a good thing. The examples need no libraries
so far.
Diffstat (limited to 'subx/052argv_equal.subx')
-rw-r--r--subx/052argv_equal.subx231
1 files changed, 231 insertions, 0 deletions
diff --git a/subx/052argv_equal.subx b/subx/052argv_equal.subx
new file mode 100644
index 00000000..60c24b01
--- /dev/null
+++ b/subx/052argv_equal.subx
@@ -0,0 +1,231 @@
+== code
+
+# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
+# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
+argv_equal:  # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
+  # prolog
+  55/push-EBP
+  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  # save registers
+  51/push-ECX
+  52/push-EDX
+  53/push-EBX
+  56/push-ESI
+  57/push-EDI
+
+  # pseudocode:
+  #   initialize n = b.length
+  #   initialize s1 = s
+  #   initialize s2 = b.data
+  #   i = 0
+  #   for (i = 0; i < n; ++n)
+  #     c1 = *s1
+  #     c2 = *s2
+  #     if c1 == 0
+  #       return false
+  #     if c1 != c2
+  #       return false
+  #   return *s1 == 0
+  # initialize s into EDI
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
+  # initialize benchmark length n into EDX
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
+  8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
+  # initialize benchmark data into ESI
+  8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
+  81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               4/imm32           # add 4 to ESI
+  # initialize loop counter i into ECX
+  b9/copy                         .               .             .           .             .           .           .               0/imm32/exit      # copy 1 to ECX
+  # while (i/ECX < n/EDX)
+$argv_loop:
+  39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # compare ECX with EDX
+  74/jump-if-equal  $argv_break/disp8
+    # c1/EAX, c2/EBX = *s, *benchmark
+  b8/copy  0/imm32  # clear EAX
+  8a/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy byte at *EDI to lower byte of EAX
+  bb/copy  0/imm32  # clear EBX
+  8a/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy byte at *ESI to lower byte of EBX
+    # if (c1 == 0) return false
+  3d/compare                      .               .             .           .             .           .           .               0/imm32           # compare EAX with 0
+  74/jump-if-equal  $argv_fail/disp8
+    # if (c1 != c2) return false
+  39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX with EBX
+  75/jump-if-not-equal  $argv_fail/disp8
+    # ++s1, ++s2, ++i
+  41/inc-ECX
+  46/inc-ESI
+  47/inc-EDI
+  # end while
+  eb/jump  $argv_loop/disp8
+$argv_break:
+  # if (*s/EDI == 0) return true
+  b8/copy  0/imm32  # clear EAX
+  8a/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy byte at *EDI to lower byte of EAX
+  81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # compare EAX with 0
+  75/jump-if-not-equal  $argv_fail/disp8
+  b8/copy                         .               .             .           .             .           .           .               1/imm32           # copy 1 to EAX
+  eb/jump  $argv_end/disp8
+  # return false
+$argv_fail:
+  b8/copy                         .               .             .           .             .           .           .               0/imm32           # copy 0 to EAX
+
+$argv_end:
+  # restore registers
+  5f/pop-to-EDI
+  5e/pop-to-ESI
+  5b/pop-to-EBX
+  5a/pop-to-EDX
+  59/pop-to-ECX
+  # end
+  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  5d/pop-to-EBP
+  c3/return
+
+## tests
+
+test_compare_null_argv_with_empty_array:
+  # EAX = argv_equal(Null_argv, "")
+    # push args
+  68/push  ""/imm32
+  68/push  Null_argv/imm32
+    # call
+  e8/call  argv_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
+  # call check_ints_equal(EAX, 1, msg)
+    # push args
+  68/push  "F - test_compare_null_argv_with_empty_array"/imm32
+  68/push  1/imm32/true
+  50/push-EAX
+    # call
+  e8/call  check_ints_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add 12 to ESP
+  c3/return
+
+test_compare_null_argv_with_non_empty_array:
+  # EAX = argv_equal(Null_argv, "Abc")
+    # push args
+  68/push  "Abc"/imm32
+  68/push  Null_argv/imm32
+    # call
+  e8/call  argv_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
+  # call check_ints_equal(EAX, 0, msg)
+    # push args
+  68/push  "F - test_compare_null_argv_with_non_empty_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
+    # call
+  e8/call  check_ints_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add 12 to ESP
+  c3/return
+
+test_compare_argv_with_equal_array:
+  # EAX = argv_equal(Abc_argv, "Abc")
+    # push args
+  68/push  "Abc"/imm32
+  68/push  Abc_argv/imm32
+    # call
+  e8/call  argv_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
+  # call check_ints_equal(EAX, 1, msg)
+    # push args
+  68/push  "F - test_compare_argv_with_equal_array"/imm32
+  68/push  1/imm32/true
+  50/push-EAX
+    # call
+  e8/call  check_ints_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add 12 to ESP
+  c3/return
+
+test_compare_argv_with_inequal_array:
+  # EAX = argv_equal(Abc_argv, "Adc")
+    # push args
+  68/push  "Adc"/imm32
+  68/push  Abc_argv/imm32
+    # call
+  e8/call  argv_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
+  # call check_ints_equal(EAX, 0, msg)
+    # push args
+  68/push  "F - test_compare_argv_with_equal_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
+    # call
+  e8/call  check_ints_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add 12 to ESP
+  c3/return
+
+test_compare_argv_with_empty_array:
+  # EAX = argv_equal(Abc_argv, "")
+    # push args
+  68/push  ""/imm32
+  68/push  Abc_argv/imm32
+    # call
+  e8/call  argv_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
+  # call check_ints_equal(EAX, 0)
+    # push args
+  68/push  "F - test_compare_argv_with_equal_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
+    # call
+  e8/call  check_ints_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add 12 to ESP
+  c3/return
+
+test_compare_argv_with_shorter_array:
+  # EAX = argv_equal(Abc_argv, "Ab")
+    # push args
+  68/push  "Ab"/imm32
+  68/push  Abc_argv/imm32
+    # call
+  e8/call  argv_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
+  # call check_ints_equal(EAX, 0)
+    # push args
+  68/push  "F - test_compare_argv_with_shorter_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
+    # call
+  e8/call  check_ints_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add 12 to ESP
+  c3/return
+
+test_compare_argv_with_longer_array:
+  # EAX = argv_equal(Abc_argv, "Abcd")
+    # push args
+  68/push  "Abcd"/imm32
+  68/push  Abc_argv/imm32
+    # call
+  e8/call  argv_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add 8 to ESP
+  # call check_ints_equal(EAX, 0)
+    # push args
+  68/push  "F - test_compare_argv_with_longer_array"/imm32
+  68/push  0/imm32/false
+  50/push-EAX
+    # call
+  e8/call  check_ints_equal/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add 12 to ESP
+  c3/return
+
+== data
+
+Null_argv:
+  00/null
+Abc_argv:
+  41/A 62/b 63/c 00/null