From 5a2cb154eb016aa8b84ad939f63eb56dd7a0a90f Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 2 Oct 2018 01:21:01 -0700 Subject: 4649 --- html/subx/examples/ex11.subx.html | 627 ++++++++++++++++++++------------------ 1 file changed, 336 insertions(+), 291 deletions(-) (limited to 'html/subx/examples/ex11.subx.html') diff --git a/html/subx/examples/ex11.subx.html b/html/subx/examples/ex11.subx.html index f0fd07c2..3273b21a 100644 --- a/html/subx/examples/ex11.subx.html +++ b/html/subx/examples/ex11.subx.html @@ -57,13 +57,13 @@ if ('onhashchange' in window) { 1 ## Null-terminated vs length-prefixed ascii strings. 2 # 3 # By default we create strings with a 4-byte length prefix rather than a null suffix. - 4 # However, commandline arguments come null-prefixed from the Linux kernel. - 5 # This example shows a helper that can compare a commandline argument with the - 6 # (length-prefixed) literal string "target". + 4 # However we still need null-prefixed strings when interacting with the Linux + 5 # kernel in a few places. This layer implements a function for comparing + 6 # a null-terminated 'kernel string' with a length-prefixed 'SubX string'. 7 # - 8 # To run: - 9 # $ subx translate ex11.subx ex11 - 10 # $ subx run ex11 # runs a series of tests + 8 # To run (from the subx directory): + 9 # $ subx translate examples/ex11.subx -o examples/ex11 + 10 # $ subx run examples/ex11 # runs a series of tests 11 # ...... # all tests pass 12 # 13 # (We can't yet run the tests when given a "test" commandline argument, @@ -71,293 +71,338 @@ if ('onhashchange' in window) { 15 # would cause tests to not run, rather than to fail as we'd like.) 16 17 == code - 18 # instruction effective address operand displacement immediate - 19 # op subop mod rm32 base index scale r32 - 20 # 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 - 21 - 22 # main: - 23 e8/call run_tests/disp32 # 'run_tests' is a function created automatically by SubX. It calls all functions that start with 'test_'. - 24 # exit(EAX) - 25 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX - 26 b8/copy . . . . . . . 1/imm32 # copy 1 to EAX - 27 cd/syscall 0x80/imm8 - 28 - 29 # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array - 30 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args - 31 argv_equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean - 32 # pseudocode: - 33 # initialize n = b.length - 34 # initialize s1 = s - 35 # initialize s2 = b.data - 36 # i = 0 - 37 # for (i = 0; i < n; ++n) - 38 # c1 = *s1 - 39 # c2 = *s2 - 40 # if c1 == 0 - 41 # return false - 42 # if c1 != c2 - 43 # return false - 44 # return *s1 == 0 - 45 - 46 # initialize s into EDI - 47 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 7/r32/EDI 8/disp8 . # copy *(ESP+8) to EDI - 48 # initialize benchmark length n into EDX - 49 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 2/r32/EDX 4/disp8 . # copy *(ESP+4) to EDX - 50 8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX - 51 # initialize benchmark data into ESI - 52 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 6/r32/ESI 4/disp8 . # copy *(ESP+4) to ESI - 53 81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 4/imm32 # add 4 to ESI - 54 # initialize loop counter i into ECX - 55 b9/copy . . . . . . . 0/imm32/exit # copy 1 to ECX - 56 # while (i/ECX < n/EDX) - 57 $argv_loop: - 58 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX - 59 74/jump-if-equal $argv_break/disp8 - 60 # c1/EAX, c2/EBX = *s, *benchmark - 61 b8/copy 0/imm32 # clear EAX - 62 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX - 63 bb/copy 0/imm32 # clear EBX - 64 8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX - 65 # if (c1 == 0) return false - 66 3d/compare . . . . . . . 0/imm32 # compare EAX with 0 - 67 74/jump-if-equal $argv_fail/disp8 - 68 # if (c1 != c2) return false - 69 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX - 70 75/jump-if-not-equal $argv_fail/disp8 - 71 # ++s1, ++s2, ++i - 72 41/inc-ECX - 73 46/inc-ESI - 74 47/inc-EDI - 75 # end while - 76 eb/jump $argv_loop/disp8 - 77 $argv_break: - 78 # if (*s/EDI == 0) return true - 79 b8/copy 0/imm32 # clear EAX - 80 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX - 81 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX with 0 - 82 75/jump-if-not-equal $argv_fail/disp8 - 83 b8/copy . . . . . . . 1/imm32 # copy 1 to EAX - 84 c3/return - 85 # return false - 86 $argv_fail: - 87 b8/copy . . . . . . . 0/imm32 # copy 0 to EAX - 88 c3/return - 89 - 90 ## tests - 91 - 92 test_compare_null_argv_with_empty_array: - 93 # EAX = argv_equal(Null_argv, "") - 94 # push args - 95 68/push Null_argv/imm32 - 96 68/push ""/imm32 - 97 # call - 98 e8/call argv_equal/disp32 - 99 # discard args -100 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add 8 to ESP -101 # call check_ints_equal(EAX, 1) -102 50/push-EAX -103 68/push 1/imm32/true -104 68/push "F - test_compare_null_argv_with_empty_array"/imm32 -105 # call -106 e8/call check_ints_equal/disp32 -107 # discard args -108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add 12 to ESP + 18 + 19 # instruction effective address operand displacement immediate + 20 # op subop mod rm32 base index scale r32 + 21 # 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 + 22 + 23 # main: + 24 e8/call run_tests/disp32 # 'run_tests' is a function created automatically by SubX. It calls all functions that start with 'test_'. + 25 # exit(EAX) + 26 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX + 27 b8/copy . . . . . . . 1/imm32 # copy to EAX + 28 cd/syscall 0x80/imm8 + 29 + 30 # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array + 31 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args + 32 kernel_string_equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean + 33 # prolog + 34 55/push-EBP + 35 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 36 # save registers + 37 51/push-ECX + 38 52/push-EDX + 39 53/push-EBX + 40 56/push-ESI + 41 57/push-EDI + 42 + 43 # pseudocode: + 44 # initialize n = b.length + 45 # initialize s1 = s + 46 # initialize s2 = b.data + 47 # i = 0 + 48 # for (i = 0; i < n; ++n) + 49 # c1 = *s1 + 50 # c2 = *s2 + 51 # if c1 == 0 + 52 # return false + 53 # if c1 != c2 + 54 # return false + 55 # return *s1 == 0 + 56 # initialize s into EDI + 57 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI + 58 # initialize benchmark length n into EDX + 59 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX + 60 8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX + 61 # initialize benchmark data into ESI + 62 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI + 63 81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 4/imm32 # add to ESI + 64 # initialize loop counter i into ECX + 65 b9/copy . . . . . . . 0/imm32/exit # copy to ECX + 66 # while (i/ECX < n/EDX) + 67 $kernel_string_loop: + 68 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX + 69 74/jump-if-equal $kernel_string_break/disp8 + 70 # c1/EAX, c2/EBX = *s, *benchmark + 71 b8/copy 0/imm32 # clear EAX + 72 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX + 73 bb/copy 0/imm32 # clear EBX + 74 8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX + 75 # if (c1 == 0) return false + 76 3d/compare-EAX 0/imm32 + 77 74/jump-if-equal $kernel_string_fail/disp8 + 78 # if (c1 != c2) return false + 79 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX + 80 75/jump-if-not-equal $kernel_string_fail/disp8 + 81 # ++s1, ++s2, ++i + 82 41/inc-ECX + 83 46/inc-ESI + 84 47/inc-EDI + 85 # end while + 86 eb/jump $kernel_string_loop/disp8 + 87 $kernel_string_break: + 88 # if (*s/EDI == 0) return true + 89 b8/copy 0/imm32 # clear EAX + 90 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX + 91 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX + 92 75/jump-if-not-equal $kernel_string_fail/disp8 + 93 b8/copy . . . . . . . 1/imm32 # copy to EAX + 94 eb/jump $kernel_string_end/disp8 + 95 # return false + 96 $kernel_string_fail: + 97 b8/copy . . . . . . . 0/imm32 # copy to EAX + 98 + 99 $kernel_string_end: +100 # restore registers +101 5f/pop-to-EDI +102 5e/pop-to-ESI +103 5b/pop-to-EBX +104 5a/pop-to-EDX +105 59/pop-to-ECX +106 # end +107 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +108 5d/pop-to-EBP 109 c3/return 110 -111 test_compare_null_argv_with_non_empty_array: -112 # EAX = argv_equal(Null_argv, "Abc") -113 # push args -114 68/push Null_argv/imm32 -115 68/push "Abc"/imm32 -116 # call -117 e8/call argv_equal/disp32 -118 # discard args -119 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add 8 to ESP -120 # call check_ints_equal(EAX, 0) -121 50/push-EAX -122 68/push 0/imm32/false -123 68/push "F - test_compare_null_argv_with_non_empty_array"/imm32 -124 # call -125 e8/call check_ints_equal/disp32 -126 # discard args -127 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add 12 to ESP -128 c3/return -129 -130 test_compare_argv_with_equal_array: -131 # EAX = argv_equal(Abc_argv, "Abc") -132 # push args -133 68/push Abc_argv/imm32 -134 68/push "Abc"/imm32 -135 # call -136 e8/call argv_equal/disp32 -137 # discard args -138 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add 8 to ESP -139 # call check_ints_equal(EAX, 1) -140 50/push-EAX -141 68/push 1/imm32/true -142 68/push "F - test_compare_argv_with_equal_array"/imm32 -143 # call -144 e8/call check_ints_equal/disp32 -145 # discard args -146 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add 12 to ESP -147 c3/return -148 -149 test_compare_argv_with_inequal_array: -150 # EAX = argv_equal(Abc_argv, "Adc") -151 # push args -152 68/push Abc_argv/imm32 -153 68/push "Adc"/imm32 -154 # call -155 e8/call argv_equal/disp32 -156 # discard args -157 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add 8 to ESP -158 # call check_ints_equal(EAX, 0) -159 50/push-EAX -160 68/push 0/imm32/false -161 68/push "F - test_compare_argv_with_equal_array"/imm32 -162 # call -163 e8/call check_ints_equal/disp32 -164 # discard args -165 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add 12 to ESP -166 c3/return -167 -168 test_compare_argv_with_empty_array: -169 # EAX = argv_equal(Abc_argv, "") -170 # push args -171 68/push Abc_argv/imm32 -172 68/push ""/imm32 -173 # call -174 e8/call argv_equal/disp32 -175 # discard args -176 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add 8 to ESP -177 # call check_ints_equal(EAX, 0) -178 50/push-EAX -179 68/push 0/imm32/false -180 68/push "F - test_compare_argv_with_equal_array"/imm32 -181 # call -182 e8/call check_ints_equal/disp32 -183 # discard args -184 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add 12 to ESP -185 c3/return -186 -187 test_compare_argv_with_shorter_array: -188 # EAX = argv_equal(Abc_argv, "Ab") -189 # push args -190 68/push Abc_argv/imm32 -191 68/push "Ab"/imm32 -192 # call -193 e8/call argv_equal/disp32 -194 # discard args -195 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add 8 to ESP -196 # call check_ints_equal(EAX, 0) -197 50/push-EAX -198 68/push 0/imm32/false -199 68/push "F - test_compare_argv_with_shorter_array"/imm32 -200 # call -201 e8/call check_ints_equal/disp32 -202 # discard args -203 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add 12 to ESP -204 c3/return -205 -206 test_compare_argv_with_longer_array: -207 # EAX = argv_equal(Abc_argv, "Abcd") -208 # push args -209 68/push Abc_argv/imm32 -210 68/push "Abcd"/imm32 -211 # call -212 e8/call argv_equal/disp32 -213 # discard args -214 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add 8 to ESP -215 # call check_ints_equal(EAX, 0) -216 50/push-EAX -217 68/push 0/imm32/false -218 68/push "F - test_compare_argv_with_longer_array"/imm32 -219 # call -220 e8/call check_ints_equal/disp32 -221 # discard args -222 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add 12 to ESP -223 c3/return -224 -225 ## helpers -226 -227 # print msg to stderr if a != b, otherwise print "." -228 check_ints_equal: # (a : int, b : int, msg : (address array byte)) -> boolean -229 # load args into EAX, EBX and ECX -230 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX 0xc/disp8 . # copy *(ESP+12) to EAX -231 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 3/r32/EBX 0x8/disp8 . # copy *(ESP+8) to EBX -232 # if EAX == b/EBX -233 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX -234 75/jump-if-unequal $check_ints_equal:else/disp8 -235 # print('.') -236 # push args -237 68/push "."/imm32 -238 # call -239 e8/call write_stderr/disp32 -240 # discard arg -241 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add 4 to ESP -242 # return -243 c3/return -244 # else: -245 $check_ints_equal:else: -246 # copy msg into ECX -247 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX 4/disp8 . # copy *(ESP+4) to ECX -248 # print(ECX) -249 # push args -250 51/push-ECX -251 # call -252 e8/call write_stderr/disp32 -253 # discard arg -254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add 4 to ESP -255 # print newline -256 # push args -257 68/push Newline/imm32 -258 # call -259 e8/call write_stderr/disp32 -260 # discard arg -261 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add 4 to ESP -262 # end -263 c3/return -264 -265 write_stderr: # s : (address array byte) -> <void> -266 # save registers -267 50/push-EAX -268 51/push-ECX -269 52/push-EDX -270 53/push-EBX -271 # write(2/stderr, (data) s+4, (size) *s) -272 # fd = 2 (stderr) -273 bb/copy . . . . . . . 2/imm32 # copy 2 to EBX -274 # x = s+4 -275 8b/copy 1/mod/*+disp8 4/rm32/SIB 4/base/ESP 4/index/none . 1/r32/ECX 0x14/disp8 . # copy *(ESP+20) to ECX -276 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add 4 to ECX -277 # size = *s -278 8b/copy 1/mod/*+disp8 4/rm32/SIB 4/base/ESP 4/index/none . 2/r32/EDX 0x14/disp8 . # copy *(ESP+20) to EDX -279 8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX -280 # call write() -281 b8/copy . . . . . . . 4/imm32/write # copy 1 to EAX -282 cd/syscall 0x80/imm8 -283 # restore registers -284 5b/pop-EBX -285 5a/pop-EDX -286 59/pop-ECX -287 58/pop-EAX -288 # end -289 c3/return -290 -291 == data -292 Newline: -293 # size -294 01 00 00 00 -295 # data -296 0a/newline -297 -298 # for argv_equal tests -299 Null_argv: -300 00/null -301 Abc_argv: -302 41/A 62/b 63/c 00/null -303 -304 # vim:ft=subx:nowrap:so=0 +111 ## tests +112 +113 test_compare_null_kernel_string_with_empty_array: +114 # EAX = kernel_string_equal(Null_kernel_string, "") +115 # push args +116 68/push ""/imm32 +117 68/push Null_kernel_string/imm32 +118 # call +119 e8/call kernel_string_equal/disp32 +120 # discard args +121 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +122 # call check_ints_equal(EAX, 1, msg) +123 # push args +124 68/push "F - test_compare_null_kernel_string_with_empty_array"/imm32 +125 68/push 1/imm32/true +126 50/push-EAX +127 # call +128 e8/call check_ints_equal/disp32 +129 # discard args +130 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +131 c3/return +132 +133 test_compare_null_kernel_string_with_non_empty_array: +134 # EAX = kernel_string_equal(Null_kernel_string, "Abc") +135 # push args +136 68/push "Abc"/imm32 +137 68/push Null_kernel_string/imm32 +138 # call +139 e8/call kernel_string_equal/disp32 +140 # discard args +141 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +142 # call check_ints_equal(EAX, 0, msg) +143 # push args +144 68/push "F - test_compare_null_kernel_string_with_non_empty_array"/imm32 +145 68/push 0/imm32/false +146 50/push-EAX +147 # call +148 e8/call check_ints_equal/disp32 +149 # discard args +150 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +151 c3/return +152 +153 test_compare_kernel_string_with_equal_array: +154 # EAX = kernel_string_equal(Abc_kernel_string, "Abc") +155 # push args +156 68/push "Abc"/imm32 +157 68/push Abc_kernel_string/imm32 +158 # call +159 e8/call kernel_string_equal/disp32 +160 # discard args +161 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +162 # call check_ints_equal(EAX, 1, msg) +163 # push args +164 68/push "F - test_compare_kernel_string_with_equal_array"/imm32 +165 68/push 1/imm32/true +166 50/push-EAX +167 # call +168 e8/call check_ints_equal/disp32 +169 # discard args +170 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +171 c3/return +172 +173 test_compare_kernel_string_with_inequal_array: +174 # EAX = kernel_string_equal(Abc_kernel_string, "Adc") +175 # push args +176 68/push "Adc"/imm32 +177 68/push Abc_kernel_string/imm32 +178 # call +179 e8/call kernel_string_equal/disp32 +180 # discard args +181 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +182 # call check_ints_equal(EAX, 0, msg) +183 # push args +184 68/push "F - test_compare_kernel_string_with_equal_array"/imm32 +185 68/push 0/imm32/false +186 50/push-EAX +187 # call +188 e8/call check_ints_equal/disp32 +189 # discard args +190 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +191 c3/return +192 +193 test_compare_kernel_string_with_empty_array: +194 # EAX = kernel_string_equal(Abc_kernel_string, "") +195 # push args +196 68/push ""/imm32 +197 68/push Abc_kernel_string/imm32 +198 # call +199 e8/call kernel_string_equal/disp32 +200 # discard args +201 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +202 # call check_ints_equal(EAX, 0) +203 # push args +204 68/push "F - test_compare_kernel_string_with_equal_array"/imm32 +205 68/push 0/imm32/false +206 50/push-EAX +207 # call +208 e8/call check_ints_equal/disp32 +209 # discard args +210 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +211 c3/return +212 +213 test_compare_kernel_string_with_shorter_array: +214 # EAX = kernel_string_equal(Abc_kernel_string, "Ab") +215 # push args +216 68/push "Ab"/imm32 +217 68/push Abc_kernel_string/imm32 +218 # call +219 e8/call kernel_string_equal/disp32 +220 # discard args +221 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +222 # call check_ints_equal(EAX, 0) +223 # push args +224 68/push "F - test_compare_kernel_string_with_shorter_array"/imm32 +225 68/push 0/imm32/false +226 50/push-EAX +227 # call +228 e8/call check_ints_equal/disp32 +229 # discard args +230 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +231 c3/return +232 +233 test_compare_kernel_string_with_longer_array: +234 # EAX = kernel_string_equal(Abc_kernel_string, "Abcd") +235 # push args +236 68/push "Abcd"/imm32 +237 68/push Abc_kernel_string/imm32 +238 # call +239 e8/call kernel_string_equal/disp32 +240 # discard args +241 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +242 # call check_ints_equal(EAX, 0) +243 # push args +244 68/push "F - test_compare_kernel_string_with_longer_array"/imm32 +245 68/push 0/imm32/false +246 50/push-EAX +247 # call +248 e8/call check_ints_equal/disp32 +249 # discard args +250 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +251 c3/return +252 +253 ## helpers +254 +255 # print msg to stderr if a != b, otherwise print "." +256 check_ints_equal: # (a : int, b : int, msg : (address array byte)) -> boolean +257 # prolog +258 55/push-EBP +259 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +260 # save registers +261 51/push-ECX +262 53/push-EBX +263 # load args into EAX, EBX and ECX +264 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 0/r32/EAX 0x8/disp8 . # copy *(EBP+8) to EAX +265 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX +266 # if EAX == b/EBX +267 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX +268 75/jump-if-unequal $check_ints_equal:else/disp8 +269 # print('.') +270 # push args +271 68/push "."/imm32 +272 # call +273 e8/call write_stderr/disp32 +274 # discard arg +275 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +276 # return +277 eb/jump $check_ints_equal:end/disp8 +278 # else: +279 $check_ints_equal:else: +280 # copy msg into ECX +281 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX +282 # print(ECX) +283 # push args +284 51/push-ECX +285 # call +286 e8/call write_stderr/disp32 +287 # discard arg +288 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +289 # print newline +290 # push args +291 68/push Newline/imm32 +292 # call +293 e8/call write_stderr/disp32 +294 # discard arg +295 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +296 $check_ints_equal:end: +297 # restore registers +298 5b/pop-to-EBX +299 59/pop-to-ECX +300 # end +301 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +302 5d/pop-to-EBP +303 c3/return +304 +305 write_stderr: # s : (address array byte) -> <void> +306 # prolog +307 55/push-EBP +308 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +309 # save registers +310 50/push-EAX +311 51/push-ECX +312 52/push-EDX +313 53/push-EBX +314 # write(2/stderr, (data) s+4, (size) *s) +315 # fd = 2 (stderr) +316 bb/copy . . . . . . . 2/imm32 # copy to EBX +317 # x = s+4 +318 8b/copy 1/mod/*+disp8 4/rm32/SIB 5/base/EBP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX +319 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add to ECX +320 # size = *s +321 8b/copy 1/mod/*+disp8 4/rm32/SIB 5/base/EBP 4/index/none . 2/r32/EDX 8/disp8 . # copy *(EBP+8) to EDX +322 8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX +323 # call write() +324 b8/copy . . . . . . . 4/imm32/write # copy to EAX +325 cd/syscall 0x80/imm8 +326 # restore registers +327 5b/pop-to-EBX +328 5a/pop-to-EDX +329 59/pop-to-ECX +330 58/pop-to-EAX +331 # end +332 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +333 5d/pop-to-EBP +334 c3/return +335 +336 == data +337 Newline: +338 # size +339 01 00 00 00 +340 # data +341 0a/newline +342 +343 # for kernel_string_equal tests +344 Null_kernel_string: +345 00/null +346 Abc_kernel_string: +347 41/A 62/b 63/c 00/null +348 +349 # vim:ft=subx:nowrap:so=0 -- cgit 1.4.1-2-gfad0