From 40077d0d2b39ca5bed1f316e186b8f23b7148dc8 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 22 May 2019 21:59:39 -0700 Subject: [PATCH] 5220 --- html/subx/056trace.subx.html | 2 +- html/subx/062write-stream.subx.html | 2 +- html/subx/064write-byte.subx.html | 2 +- html/subx/069allocate.subx.html | 2 +- html/subx/070new-stream.subx.html | 2 +- html/subx/072slice.subx.html | 4 +- html/subx/074print-int-decimal.subx.html | 2 +- html/subx/apps/assort.subx.html | 2 +- html/subx/apps/dquotes.subx.html | 2 +- html/subx/apps/factorial.subx.html | 4 +- html/subx/apps/handle.subx.html | 732 ++++++++++++----------- 11 files changed, 386 insertions(+), 370 deletions(-) diff --git a/html/subx/056trace.subx.html b/html/subx/056trace.subx.html index 9e734e19..8502bbd3 100644 --- a/html/subx/056trace.subx.html +++ b/html/subx/056trace.subx.html @@ -412,7 +412,7 @@ if ('onhashchange' in window) { 350 $_append-4:abort: 351 # . _write(2/stderr, error) 352 # . . push args -353 68/push "stream overflow"/imm32 +353 68/push "stream overflow\n"/imm32 354 68/push 2/imm32/stderr 355 # . . call 356 e8/call _write/disp32 diff --git a/html/subx/062write-stream.subx.html b/html/subx/062write-stream.subx.html index 6e4e6faa..1e97f935 100644 --- a/html/subx/062write-stream.subx.html +++ b/html/subx/062write-stream.subx.html @@ -183,7 +183,7 @@ if ('onhashchange' in window) { 122 $_write-stream:abort: 123 # . _write(2/stderr, error) 124 # . . push args -125 68/push "_write-stream: failed to write to file"/imm32 +125 68/push "_write-stream: failed to write to file\n"/imm32 126 68/push 2/imm32/stderr 127 # . . call 128 e8/call _write/disp32 diff --git a/html/subx/064write-byte.subx.html b/html/subx/064write-byte.subx.html index 9345b4ef..7ba45da6 100644 --- a/html/subx/064write-byte.subx.html +++ b/html/subx/064write-byte.subx.html @@ -304,7 +304,7 @@ if ('onhashchange' in window) { 243 $append-byte:abort: 244 # . _write(2/stderr, error) 245 # . . push args -246 68/push "append-byte: out of space"/imm32 +246 68/push "append-byte: out of space\n"/imm32 247 68/push 2/imm32/stderr 248 # . . call 249 e8/call _write/disp32 diff --git a/html/subx/069allocate.subx.html b/html/subx/069allocate.subx.html index 689fb989..30bb3040 100644 --- a/html/subx/069allocate.subx.html +++ b/html/subx/069allocate.subx.html @@ -236,7 +236,7 @@ if ('onhashchange' in window) { 177 $allocate-region:abort: 178 # . _write(2/stderr, error) 179 # . . push args -180 68/push "allocate-region: failed to allocate"/imm32 +180 68/push "allocate-region: failed to allocate\n"/imm32 181 68/push 2/imm32/stderr 182 # . . call 183 e8/call _write/disp32 diff --git a/html/subx/070new-stream.subx.html b/html/subx/070new-stream.subx.html index 0779e2d7..c99b6ab7 100644 --- a/html/subx/070new-stream.subx.html +++ b/html/subx/070new-stream.subx.html @@ -111,7 +111,7 @@ if ('onhashchange' in window) { 52 $new-stream:abort: 53 # . _write(2/stderr, error) 54 # . . push args - 55 68/push "new-stream: size too large"/imm32 + 55 68/push "new-stream: size too large\n"/imm32 56 68/push 2/imm32/stderr 57 # . . call 58 e8/call _write/disp32 diff --git a/html/subx/072slice.subx.html b/html/subx/072slice.subx.html index a22b0f1b..0d40c1ce 100644 --- a/html/subx/072slice.subx.html +++ b/html/subx/072slice.subx.html @@ -964,7 +964,7 @@ if ('onhashchange' in window) { 901 $slice-to-string:abort: 902 # . _write(2/stderr, error) 903 # . . push args - 904 68/push "slice-to-string: out of space"/imm32 + 904 68/push "slice-to-string: out of space\n"/imm32 905 68/push 2/imm32/stderr 906 # . . call 907 e8/call _write/disp32 @@ -1039,7 +1039,7 @@ if ('onhashchange' in window) { 1001 64/d 1002 _test-slice-data-4: 1003 -1004 # . _. vim:nowrap:textwidth=0 +1004 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/074print-int-decimal.subx.html b/html/subx/074print-int-decimal.subx.html index 9eb8c9f8..cbfcbb8d 100644 --- a/html/subx/074print-int-decimal.subx.html +++ b/html/subx/074print-int-decimal.subx.html @@ -186,7 +186,7 @@ if ('onhashchange' in window) { 124 $print-int32-decimal:abort: 125 # . _write(2/stderr, error) 126 # . . push args -127 68/push "print-int32-decimal: out of space"/imm32 +127 68/push "print-int32-decimal: out of space\n"/imm32 128 68/push 2/imm32/stderr 129 # . . call 130 e8/call _write/disp32 diff --git a/html/subx/apps/assort.subx.html b/html/subx/apps/assort.subx.html index 62fd3896..e05b7de6 100644 --- a/html/subx/apps/assort.subx.html +++ b/html/subx/apps/assort.subx.html @@ -810,7 +810,7 @@ if ('onhashchange' in window) { 885 $get-or-insert-segment:abort: 886 # . _write(2/stderr, error) 887 # . . push args - 888 68/push "get-or-insert-segment: too many segments"/imm32 + 888 68/push "get-or-insert-segment: too many segments\n"/imm32 889 68/push 2/imm32/stderr 890 # . . call 891 e8/call _write/disp32 diff --git a/html/subx/apps/dquotes.subx.html b/html/subx/apps/dquotes.subx.html index 0645f2f4..690d3b10 100644 --- a/html/subx/apps/dquotes.subx.html +++ b/html/subx/apps/dquotes.subx.html @@ -803,7 +803,7 @@ if ('onhashchange' in window) { 796 e8/call check-next-stream-line-equal/disp32 797 # . . discard args 798 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 799 # . check-next-stream-line-equal(_test-output-stream, "== data ", msg) + 799 # . check-next-stream-line-equal(_test-output-stream, "== data", msg) 800 # . . push args 801 68/push "F - test-convert-processes-string-literals/3"/imm32 802 68/push "== data"/imm32 diff --git a/html/subx/apps/factorial.subx.html b/html/subx/apps/factorial.subx.html index 86eb6b65..27859afe 100644 --- a/html/subx/apps/factorial.subx.html +++ b/html/subx/apps/factorial.subx.html @@ -107,8 +107,8 @@ if ('onhashchange' in window) { 45 e8/call run-tests/disp32 46 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Num-test-failures/disp32 # copy *Num-test-failures to EAX 47 eb/jump $main:end/disp8 # where EAX will get copied to EBX - 48 # - otherwise return factorial(5) - 49 $run-main: + 48 $run-main: + 49 # - otherwise return factorial(5) 50 # . . push args 51 68/push 5/imm32 52 # . . call diff --git a/html/subx/apps/handle.subx.html b/html/subx/apps/handle.subx.html index 59cafb27..7e80e7e0 100644 --- a/html/subx/apps/handle.subx.html +++ b/html/subx/apps/handle.subx.html @@ -76,374 +76,390 @@ if ('onhashchange' in window) { 15 # To run (from the subx directory): 16 # $ ./subx translate *.subx apps/handle.subx -o apps/handle 17 # $ ./subx run apps/handle - 18 # Expected result is a hard abort: - 19 # ........lookup failed - 20 # (This file is a prototype, so the tests in this file aren't real tests. Don't - 21 # expect to run anything in the same process after they've completed.) - 22 - 23 == code - 24 # instruction effective address register displacement immediate - 25 # . op subop mod rm32 base index scale r32 - 26 # . 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 - 27 - 28 # no Entry; the standard library runs all tests by default - 29 - 30 new: # ad : (address allocation-descriptor), n : int, out : (address handle) - 31 # . prolog - 32 55/push-EBP - 33 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 34 # . save registers - 35 50/push-EAX - 36 51/push-ECX - 37 52/push-EDX - 38 # ECX = n+4 - 39 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 0xc/disp8 . # copy *(EBP+12) to ECX - 40 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add to ECX - 41 # EAX = allocate(ad, ECX) - 42 # . . push args - 43 51/push-ECX - 44 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 45 # . . call - 46 e8/call allocate/disp32 - 47 # . . discard args - 48 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 49 # EDX = out - 50 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0x10/disp8 . # copy *(EBP+16) to EDX - 51 # out->address = EAX - 52 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) - 53 # if (EAX == 0) out->alloc_id = 0, return - 54 3d/compare-EAX-and 0/imm32 - 55 75/jump-if-not-equal $new:continue/disp8 - 56 c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . 0/imm32 # copy to *EDX - 57 eb/jump $new:end/disp8 - 58 $new:continue: - 59 # otherwise: - 60 # ECX = *Next-alloc-id - 61 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 1/r32/ECX Next-alloc-id/disp32 # copy *Next-alloc-id to ECX - 62 # *EAX = *Next-alloc-id/ECX - 63 89/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy ECX to *EAX - 64 # out->alloc_id = *Next-alloc-id - 65 89/copy 0/mod/indirect 2/rm32/EDX . . . 1/r32/ECX . . # copy ECX to *EDX - 66 # increment *Next-alloc-id - 67 ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # increment *Next-alloc-id - 68 $new:end: - 69 # . restore registers - 70 5a/pop-to-EDX - 71 59/pop-to-ECX - 72 58/pop-to-EAX - 73 # . epilog - 74 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 75 5d/pop-to-EBP - 76 c3/return - 77 - 78 test-new: - 79 # . prolog - 80 55/push-EBP - 81 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 82 # var heap/EDX : (address allocation-descriptor) = {0, 0} - 83 68/push 0/imm32/limit - 84 68/push 0/imm32/curr - 85 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX - 86 # heap = new-segment(512) - 87 # . . push args - 88 52/push-EDX - 89 68/push 0x200/imm32 - 90 # . . call - 91 e8/call new-segment/disp32 - 92 # . . discard args - 93 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 94 # *Next-alloc-id = 0x34 - 95 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id - 96 # var handle/ECX = {0, 0} - 97 68/push 0/imm32/address - 98 68/push 0/imm32/alloc-id - 99 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -100 # new(heap, 2, handle/ECX) -101 # . . push args -102 51/push-ECX -103 68/push 2/imm32/size -104 52/push-EDX -105 # . . call -106 e8/call new/disp32 -107 # . . discard args -108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -109 # check-ints-equal(handle->alloc_id, 0x34, msg) -110 # . . push args -111 68/push "F - test-new: alloc id of handle"/imm32 -112 68/push 0x34/imm32 -113 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX -114 # . . call -115 e8/call check-ints-equal/disp32 -116 # . . discard args -117 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -118 # check-ints-equal(*handle->address, 0x34, msg) -119 # . . push args -120 68/push "F - test-new: alloc id of payload"/imm32 -121 68/push 0x34/imm32 -122 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX -123 ff 6/subop/push 0/mod/indirect 2/rm32/EDX . . . . . . # push *EDX -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 to ESP -128 # check-ints-equal(*Next-alloc-id, 0x35) -129 # . . push args -130 68/push "F - test-new: next alloc id"/imm32 -131 68/push 0x35/imm32 -132 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # copy to *Next-alloc-id -133 # . . call -134 e8/call check-ints-equal/disp32 -135 # . . discard args -136 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -137 # clean up -138 # . *Next-alloc-id = 1 -139 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id -140 # . epilog -141 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -142 5d/pop-to-EBP -143 c3/return -144 -145 test-new-failure: -146 # . prolog -147 55/push-EBP -148 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -149 # . *Next-alloc-id = 0x34 -150 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id -151 # define an allocation-descriptor with no space left -152 # . var ad/EAX : (address allocation-descriptor) = {0x10, 0x10} -153 68/push 0x10/imm32/limit -154 68/push 0x10/imm32/curr -155 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX -156 # . var handle/ECX = {random, random} -157 68/push 1234/imm32/address -158 68/push 5678/imm32/alloc-id -159 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -160 # try to allocate -161 # . new(ad, 2, handle/ECX) -162 # . . push args -163 51/push-ECX -164 68/push 2/imm32/size -165 50/push-EAX -166 # . . call -167 e8/call new/disp32 -168 # . . discard args -169 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -170 # handle should be cleared -171 # . check-ints-equal(handle->alloc_id, 0, msg) -172 # . . push args -173 68/push "F - test-new-failure: alloc id of handle"/imm32 -174 68/push 0/imm32 -175 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX -176 # . . call -177 e8/call check-ints-equal/disp32 -178 # . . discard args -179 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -180 # . check-ints-equal(handle->address, 0, msg) -181 # . . push args -182 68/push "F - test-new-failure: address of handle"/imm32 -183 68/push 0/imm32 -184 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -185 # . . call -186 e8/call check-ints-equal/disp32 -187 # . . discard args -188 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -189 # Next-alloc-id should be unmodified -190 # . check-ints-equal(*Next-alloc-id, 0x34) -191 # . . push args -192 68/push "F - test-new-failure: next alloc id"/imm32 -193 68/push 0x34/imm32 -194 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # copy to *Next-alloc-id -195 # . . call -196 e8/call check-ints-equal/disp32 -197 # . . discard args -198 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -199 # clean up -200 # . *Next-alloc-id = 1 -201 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id -202 # . epilog -203 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -204 5d/pop-to-EBP -205 c3/return -206 -207 lookup: # h : (handle T) -> EAX : (address T) -208 # . prolog -209 55/push-EBP -210 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -211 # - as a proof of concept for future inlining, uses no general-purpose registers besides the output (EAX) -212 # EAX = handle -213 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX -214 # - inline { -215 # push handle->address -216 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(EAX+4) -217 # EAX = handle->alloc_id -218 8b/copy 0/mod/indirect 0/rm32/EAX . . . . . . # copy *EAX to EAX -219 # if (EAX != *ESP) abort -220 39/compare 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # compare *ESP and EAX -221 75/jump-if-not-equal $lookup:abort/disp8 -222 # return ESP+4 -223 58/pop-to-EAX -224 05/add-to-EAX 4/imm32 -225 # - } -226 # . epilog -227 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -228 5d/pop-to-EBP -229 c3/return -230 -231 $lookup:abort: -232 # . _write(2/stderr, msg) -233 # . . push args -234 68/push "lookup failed"/imm32 -235 68/push 2/imm32/stderr -236 # . . call -237 e8/call _write/disp32 -238 # . . discard args -239 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -240 # . syscall(exit, 1) -241 bb/copy-to-EBX 1/imm32/exit-status -242 b8/copy-to-EAX 1/imm32/exit -243 cd/syscall 0x80/imm8 -244 -245 test-lookup-success: -246 # . prolog -247 55/push-EBP -248 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -249 # . save registers -250 # var heap/EBX : (address allocation-descriptor) = {0, 0} -251 68/push 0/imm32/limit -252 68/push 0/imm32/curr -253 89/copy 3/mod/direct 3/rm32/EBX . . . 4/r32/ESP . . # copy ESP to EBX -254 # heap = new-segment(512) -255 # . . push args -256 53/push-EBX -257 68/push 0x200/imm32 -258 # . . call -259 e8/call new-segment/disp32 -260 # . . discard args -261 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -262 # var handle/ECX = {0, 0} -263 68/push 0/imm32/address -264 68/push 0/imm32/alloc-id -265 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -266 # var old_top/EDX = heap->curr -267 8b/copy 0/mod/indirect 3/rm32/EBX . . . 2/r32/EDX . . # copy *EBX to EDX -268 # new(heap, 2, handle) -269 # . . push args -270 51/push-ECX -271 68/push 2/imm32/size -272 53/push-EBX -273 # . . call -274 e8/call new/disp32 -275 # . . discard args -276 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -277 # EAX = lookup(handle) -278 # . . push args -279 51/push-ECX -280 # . . call -281 e8/call lookup/disp32 -282 # . . discard args -283 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -284 # EAX contains old top of heap, except skipping the alloc id in the payload -285 # . check-ints-equal(EAX, old_top+4, msg) + 18 # Expected result is a successful lookup followed by a hard abort: + 19 # lookup succeeded + 20 # lookup failed + 21 # (This file is a prototype. The 'tests' in it aren't real; failures are + 22 # expected.) + 23 + 24 == code + 25 # instruction effective address register displacement immediate + 26 # . op subop mod rm32 base index scale r32 + 27 # . 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 + 28 + 29 # no Entry; the standard library runs all tests by default + 30 + 31 new: # ad : (address allocation-descriptor), n : int, out : (address handle) + 32 # . prolog + 33 55/push-EBP + 34 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 35 # . save registers + 36 50/push-EAX + 37 51/push-ECX + 38 52/push-EDX + 39 # ECX = n+4 + 40 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 0xc/disp8 . # copy *(EBP+12) to ECX + 41 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add to ECX + 42 # EAX = allocate(ad, ECX) + 43 # . . push args + 44 51/push-ECX + 45 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 46 # . . call + 47 e8/call allocate/disp32 + 48 # . . discard args + 49 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 50 # EDX = out + 51 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0x10/disp8 . # copy *(EBP+16) to EDX + 52 # out->address = EAX + 53 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) + 54 # if (EAX == 0) out->alloc_id = 0, return + 55 3d/compare-EAX-and 0/imm32 + 56 75/jump-if-not-equal $new:continue/disp8 + 57 c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . 0/imm32 # copy to *EDX + 58 eb/jump $new:end/disp8 + 59 $new:continue: + 60 # otherwise: + 61 # ECX = *Next-alloc-id + 62 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 1/r32/ECX Next-alloc-id/disp32 # copy *Next-alloc-id to ECX + 63 # *EAX = *Next-alloc-id/ECX + 64 89/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy ECX to *EAX + 65 # out->alloc_id = *Next-alloc-id + 66 89/copy 0/mod/indirect 2/rm32/EDX . . . 1/r32/ECX . . # copy ECX to *EDX + 67 # increment *Next-alloc-id + 68 ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # increment *Next-alloc-id + 69 $new:end: + 70 # . restore registers + 71 5a/pop-to-EDX + 72 59/pop-to-ECX + 73 58/pop-to-EAX + 74 # . epilog + 75 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 76 5d/pop-to-EBP + 77 c3/return + 78 + 79 test-new: + 80 # . prolog + 81 55/push-EBP + 82 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 83 # var heap/EDX : (address allocation-descriptor) = {0, 0} + 84 68/push 0/imm32/limit + 85 68/push 0/imm32/curr + 86 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX + 87 # heap = new-segment(512) + 88 # . . push args + 89 52/push-EDX + 90 68/push 0x200/imm32 + 91 # . . call + 92 e8/call new-segment/disp32 + 93 # . . discard args + 94 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 95 # *Next-alloc-id = 0x34 + 96 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id + 97 # var handle/ECX = {0, 0} + 98 68/push 0/imm32/address + 99 68/push 0/imm32/alloc-id +100 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +101 # new(heap, 2, handle/ECX) +102 # . . push args +103 51/push-ECX +104 68/push 2/imm32/size +105 52/push-EDX +106 # . . call +107 e8/call new/disp32 +108 # . . discard args +109 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +110 # check-ints-equal(handle->alloc_id, 0x34, msg) +111 # . . push args +112 68/push "F - test-new: alloc id of handle"/imm32 +113 68/push 0x34/imm32 +114 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX +115 # . . call +116 e8/call check-ints-equal/disp32 +117 # . . discard args +118 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +119 # check-ints-equal(*handle->address, 0x34, msg) +120 # . . push args +121 68/push "F - test-new: alloc id of payload"/imm32 +122 68/push 0x34/imm32 +123 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX +124 ff 6/subop/push 0/mod/indirect 2/rm32/EDX . . . . . . # push *EDX +125 # . . call +126 e8/call check-ints-equal/disp32 +127 # . . discard args +128 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +129 # check-ints-equal(*Next-alloc-id, 0x35) +130 # . . push args +131 68/push "F - test-new: next alloc id"/imm32 +132 68/push 0x35/imm32 +133 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # copy to *Next-alloc-id +134 # . . call +135 e8/call check-ints-equal/disp32 +136 # . . discard args +137 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +138 # clean up +139 # . *Next-alloc-id = 1 +140 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id +141 # . epilog +142 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +143 5d/pop-to-EBP +144 c3/return +145 +146 test-new-failure: +147 # . prolog +148 55/push-EBP +149 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +150 # . *Next-alloc-id = 0x34 +151 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id +152 # define an allocation-descriptor with no space left +153 # . var ad/EAX : (address allocation-descriptor) = {0x10, 0x10} +154 68/push 0x10/imm32/limit +155 68/push 0x10/imm32/curr +156 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX +157 # . var handle/ECX = {random, random} +158 68/push 1234/imm32/address +159 68/push 5678/imm32/alloc-id +160 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +161 # try to allocate +162 # . new(ad, 2, handle/ECX) +163 # . . push args +164 51/push-ECX +165 68/push 2/imm32/size +166 50/push-EAX +167 # . . call +168 e8/call new/disp32 +169 # . . discard args +170 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +171 # handle should be cleared +172 # . check-ints-equal(handle->alloc_id, 0, msg) +173 # . . push args +174 68/push "F - test-new-failure: alloc id of handle"/imm32 +175 68/push 0/imm32 +176 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX +177 # . . call +178 e8/call check-ints-equal/disp32 +179 # . . discard args +180 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +181 # . check-ints-equal(handle->address, 0, msg) +182 # . . push args +183 68/push "F - test-new-failure: address of handle"/imm32 +184 68/push 0/imm32 +185 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +186 # . . call +187 e8/call check-ints-equal/disp32 +188 # . . discard args +189 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +190 # Next-alloc-id should be unmodified +191 # . check-ints-equal(*Next-alloc-id, 0x34) +192 # . . push args +193 68/push "F - test-new-failure: next alloc id"/imm32 +194 68/push 0x34/imm32 +195 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # copy to *Next-alloc-id +196 # . . call +197 e8/call check-ints-equal/disp32 +198 # . . discard args +199 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +200 # clean up +201 # . *Next-alloc-id = 1 +202 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id +203 # . epilog +204 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +205 5d/pop-to-EBP +206 c3/return +207 +208 lookup: # h : (handle T) -> EAX : (address T) +209 # . prolog +210 55/push-EBP +211 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +212 # - as a proof of concept for future inlining, uses no general-purpose registers besides the output (EAX) +213 # EAX = handle +214 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX +215 # - inline { +216 # push handle->alloc_id +217 ff 6/subop/push 0/mod/indirect 0/rm32/EAX . . . . . . # push *EAX +218 # EAX = handle->address (payload) +219 8b/copy 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # copy *(EAX+4) to EAX +220 # push handle->address +221 50/push-EAX +222 # EAX = payload->alloc_id +223 8b/copy 0/mod/indirect 0/rm32/EAX . . . . . . # copy *EAX to EAX +224 # if (EAX != handle->alloc_id) abort +225 39/compare 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX 4/disp8 . # compare *(ESP+4) and EAX +226 75/jump-if-not-equal $lookup:abort/disp8 +227 # EAX = pop handle->address +228 58/pop-to-EAX +229 # discard handle->alloc_id +230 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +231 # add 4 +232 05/add-to-EAX 4/imm32 +233 # - } +234 # . epilog +235 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +236 5d/pop-to-EBP +237 c3/return +238 +239 $lookup:abort: +240 # . _write(2/stderr, msg) +241 # . . push args +242 68/push "lookup failed\n"/imm32 +243 68/push 2/imm32/stderr +244 # . . call +245 e8/call _write/disp32 +246 # . . discard args +247 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +248 # . syscall(exit, 1) +249 bb/copy-to-EBX 1/imm32/exit-status +250 b8/copy-to-EAX 1/imm32/exit +251 cd/syscall 0x80/imm8 +252 +253 test-lookup-success: +254 # . prolog +255 55/push-EBP +256 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +257 # . save registers +258 # var heap/EBX : (address allocation-descriptor) = {0, 0} +259 68/push 0/imm32/limit +260 68/push 0/imm32/curr +261 89/copy 3/mod/direct 3/rm32/EBX . . . 4/r32/ESP . . # copy ESP to EBX +262 # heap = new-segment(512) +263 # . . push args +264 53/push-EBX +265 68/push 0x200/imm32 +266 # . . call +267 e8/call new-segment/disp32 +268 # . . discard args +269 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +270 # var handle/ECX = {0, 0} +271 68/push 0/imm32/address +272 68/push 0/imm32/alloc-id +273 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +274 # var old_top/EDX = heap->curr +275 8b/copy 0/mod/indirect 3/rm32/EBX . . . 2/r32/EDX . . # copy *EBX to EDX +276 # new(heap, 2, handle) +277 # . . push args +278 51/push-ECX +279 68/push 2/imm32/size +280 53/push-EBX +281 # . . call +282 e8/call new/disp32 +283 # . . discard args +284 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +285 # EAX = lookup(handle) 286 # . . push args -287 68/push "F - test-lookup-success"/imm32 -288 81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 4/imm32 # add to EDX -289 52/push-EDX -290 50/push-EAX -291 # . . call -292 e8/call check-ints-equal/disp32 -293 # . . discard args -294 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -295 # clean up -296 # . *Next-alloc-id = 1 -297 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id -298 # . restore registers -299 5a/pop-to-EDX -300 59/pop-to-ECX -301 # . epilog -302 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -303 5d/pop-to-EBP -304 c3/return -305 -306 test-lookup-failure: -307 # . prolog -308 55/push-EBP -309 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -310 # var heap/ESI : (address allocation-descriptor) = {0, 0} -311 68/push 0/imm32/limit -312 68/push 0/imm32/curr -313 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI -314 # heap = new-segment(512) -315 # . . push args -316 56/push-ESI -317 68/push 0x200/imm32 -318 # . . call -319 e8/call new-segment/disp32 -320 # . . discard args -321 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -322 # var h1/ECX = {0, 0} -323 68/push 0/imm32/address -324 68/push 0/imm32/alloc-id -325 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -326 # var old_top/EBX = heap->curr -327 8b/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy *ESI to EBX -328 # first allocation, to h1 -329 # . new(heap, 2, h1) -330 # . . push args -331 51/push-ECX -332 68/push 2/imm32/size -333 56/push-ESI +287 51/push-ECX +288 # . . call +289 e8/call lookup/disp32 +290 # . . discard args +291 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +292 # EAX contains old top of heap, except skipping the alloc id in the payload +293 # . check-ints-equal(EAX, old_top+4, msg) +294 # . . push args +295 68/push "F - test-lookup-success"/imm32 +296 81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 4/imm32 # add to EDX +297 52/push-EDX +298 50/push-EAX +299 # . . call +300 e8/call check-ints-equal/disp32 +301 # . . discard args +302 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +303 # clean up +304 # . *Next-alloc-id = 1 +305 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id +306 # write(2/stderr, "lookup succeeded\n") +307 # . . push args +308 68/push "lookup succeeded\n"/imm32 +309 68/push 2/imm32/stderr +310 # . . call +311 e8/call write/disp32 +312 # . . discard args +313 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +314 # . restore registers +315 5a/pop-to-EDX +316 59/pop-to-ECX +317 # . epilog +318 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +319 5d/pop-to-EBP +320 c3/return +321 +322 test-lookup-failure: +323 # . prolog +324 55/push-EBP +325 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +326 # var heap/ESI : (address allocation-descriptor) = {0, 0} +327 68/push 0/imm32/limit +328 68/push 0/imm32/curr +329 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +330 # heap = new-segment(512) +331 # . . push args +332 56/push-ESI +333 68/push 0x200/imm32 334 # . . call -335 e8/call new/disp32 +335 e8/call new-segment/disp32 336 # . . discard args -337 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -338 # reset heap->curr to mimic reclamation -339 89/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy EBX to *ESI -340 # second allocation that returns the same address as the first -341 # var h2/EDX = {0, 0} -342 68/push 0/imm32/address -343 68/push 0/imm32/alloc-id -344 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX -345 # . new(heap, 2, h2) +337 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +338 # var h1/ECX = {0, 0} +339 68/push 0/imm32/address +340 68/push 0/imm32/alloc-id +341 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +342 # var old_top/EBX = heap->curr +343 8b/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy *ESI to EBX +344 # first allocation, to h1 +345 # . new(heap, 2, h1) 346 # . . push args -347 52/push-EDX +347 51/push-ECX 348 68/push 2/imm32/size 349 56/push-ESI 350 # . . call -351 e8/call new/disp32 +351 e8/call new/disp32 352 # . . discard args 353 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -354 # check-ints-equal(h1->address, h2->address, msg) -355 # . . push args -356 68/push "F - test-lookup-failure"/imm32 -357 ff 6/subop/push 1/mod/*+disp8 2/rm32/ECX . . . . 4/disp8 . # push *(EDX+4) -358 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -359 # . . call -360 e8/call check-ints-equal/disp32 -361 # . . discard args -362 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -363 # lookup(h1) should crash -364 # . . push args -365 51/push-ECX +354 # reset heap->curr to mimic reclamation +355 89/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy EBX to *ESI +356 # second allocation that returns the same address as the first +357 # var h2/EDX = {0, 0} +358 68/push 0/imm32/address +359 68/push 0/imm32/alloc-id +360 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX +361 # . new(heap, 2, h2) +362 # . . push args +363 52/push-EDX +364 68/push 2/imm32/size +365 56/push-ESI 366 # . . call -367 e8/call lookup/disp32 -368 # should never get past this point -369 # . . discard args -370 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -371 # clean up -372 # . *Next-alloc-id = 1 -373 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id -374 # . epilog -375 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -376 5d/pop-to-EBP -377 c3/return -378 -379 == data -380 -381 # Monotonically increasing counter for calls to 'new' -382 Next-alloc-id: -383 1/imm32 -384 -385 # . . vim:nowrap:textwidth=0 +367 e8/call new/disp32 +368 # . . discard args +369 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +370 # check-ints-equal(h1->address, h2->address, msg) +371 # . . push args +372 68/push "F - test-lookup-failure"/imm32 +373 ff 6/subop/push 1/mod/*+disp8 2/rm32/ECX . . . . 4/disp8 . # push *(EDX+4) +374 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +375 # . . call +376 e8/call check-ints-equal/disp32 +377 # . . discard args +378 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +379 # lookup(h1) should crash +380 # . . push args +381 51/push-ECX +382 # . . call +383 e8/call lookup/disp32 +384 # should never get past this point +385 # . . discard args +386 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +387 # clean up +388 # . *Next-alloc-id = 1 +389 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id +390 # . epilog +391 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +392 5d/pop-to-EBP +393 c3/return +394 +395 == data +396 +397 # Monotonically increasing counter for calls to 'new' +398 Next-alloc-id: +399 1/imm32 +400 +401 # . . vim:nowrap:textwidth=0