diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-10-01 12:22:59 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-10-01 12:27:39 -0700 |
commit | 57628c0e4461b8bb6e6024135bf1e7f46f650030 (patch) | |
tree | 52a9f28ac189dee50b63ceeb723d7a872701dab3 /subx/052argv_equal.subx | |
parent | 5ece295328f872fa368e7852f62f363eb701c0f9 (diff) | |
download | mu-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.subx | 231 |
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 |