diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-04-03 00:19:31 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-05-18 00:44:46 -0700 |
commit | ca358b17a3fc36adcfbbb565675998de2d3e3576 (patch) | |
tree | 32c1d8726f4593521e1bc67b8e2d1ae4633c2d40 | |
parent | 546a92985f7da2491077d641a2c118b4af7f6913 (diff) | |
download | mu-ca358b17a3fc36adcfbbb565675998de2d3e3576.tar.gz |
table primitives working
$ ./translate_subx init.linux 0*.subx && ./a.elf test
-rw-r--r-- | 069allocate.subx | 521 | ||||
-rw-r--r-- | 070new-stream.subx | 8 | ||||
-rw-r--r-- | 081table.subx | 660 | ||||
-rwxr-xr-x | apps/handle | bin | 40201 -> 0 bytes | |||
-rw-r--r-- | apps/handle.subx | 428 | ||||
-rw-r--r-- | apps/mu.subx | 1 | ||||
-rw-r--r-- | html/apps/handle.subx.html | 495 | ||||
-rw-r--r-- | stats.txt | 3 | ||||
-rwxr-xr-x | test_apps | 16 |
9 files changed, 895 insertions, 1237 deletions
diff --git a/069allocate.subx b/069allocate.subx index 48d00a36..65a7f166 100644 --- a/069allocate.subx +++ b/069allocate.subx @@ -16,8 +16,8 @@ # very same 'allocate' helper. They just need a new allocation descriptor for # their book-keeping. # -# Allocations are returned in a handle, which consists of an allocid and a payload. -# The allocid helps detect use-after-free errors. +# Allocations are returned in a handle, which consists of an alloc-id and a payload. +# The alloc-id helps detect use-after-free errors. == data @@ -32,6 +32,9 @@ Heap: # allocation-descriptor Heap-size: # int 0x400000/imm32/4MB +Next-alloc-id: # int + 1/imm32 + == code # instruction effective address register displacement immediate # . op subop mod rm32 base index scale r32 @@ -74,9 +77,10 @@ allocate: # ad: (addr allocation-descriptor), n: int, out: (addr handle) e8/call allocate-raw/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # eax = out->payload + # eax = out->payload + 4 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax + 05/add-to-eax 4/imm32 # zero-out(eax, n) # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) @@ -104,26 +108,38 @@ allocate-raw: # ad: (addr allocation-descriptor), n: int, out: (addr handle) 51/push-ecx 52/push-edx 53/push-ebx + 56/push-esi + 57/push-edi # ecx = ad 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # edx = out 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx # ebx = n 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 3/r32/ebx 0xc/disp8 . # copy *(ebp+12) to ebx - # out->allocid = 0 - c7 0/subop/copy 0/mod/direct 2/rm32/edx . . . . . 0/imm32 # copy to *edx + # out->alloc-id = Next-alloc-id + 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Next-alloc-id/disp32 # copy *Next-alloc-id to eax + 89/copy 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # copy eax to *edx # out->payload = ad->curr 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax 89/copy 1/mod/*+disp8 2/rm32/edx . . . 0/r32/eax 4/disp8 . # copy eax to *(edx+4) + # *out->payload = Next-alloc-id + 8b/copy 1/mod/*+disp8 2/rm32/edx . . . 7/r32/edi 4/disp8 . # copy *(edx+4) to edi + 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 6/r32/esi Next-alloc-id/disp32 # copy *Next-alloc-id to esi + 89/copy 0/mod/indirect 7/rm32/edi . . . 6/r32/esi . . # copy esi to *edi + # increment *Next-alloc-id + ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # increment *Next-alloc-id # check if there's enough space + # TODO: move this check up before any state updates when we support error recovery 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 3/index/ebx . 0/r32/eax 4/disp8 . # copy eax+ebx+4 to eax 3b/compare 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # compare eax with *(ecx+4) 73/jump-if->=-signed $allocate-raw:abort/disp8 $allocate-raw:commit: - # update ad->curr + # ad->curr += n+4 89/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy eax to *ecx $allocate-raw:end: # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi 5b/pop-to-ebx 5a/pop-to-edx 59/pop-to-ecx @@ -152,14 +168,26 @@ test-allocate-raw-success: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ad/ecx: allocation-descriptor = {11, 32} - 68/push 0x20/imm32/limit - 68/push 0xb/imm32/curr + # var ad/ecx: allocation-descriptor + 68/push 0/imm32/limit + 68/push 0/imm32/curr 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # ad = new-segment(512) + # . . push args + 51/push-ecx + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # var expected-payload/ebx = ad->curr + 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx # var h/edx: handle = {0, 0} 68/push 0/imm32 68/push 0/imm32 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # *Next-alloc-id = 0x34 + c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id # allocate-raw(ad, 3, h) # . . push args 52/push-edx @@ -169,66 +197,228 @@ test-allocate-raw-success: e8/call allocate-raw/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # eax = h->payload - 8b/copy 1/mod/*+disp8 2/rm32/edx . . . 0/r32/eax 4/disp8 . # copy *(edx+4) to eax - # check-ints-equal(eax, 11, msg) + # check-ints-equal(h->alloc-id, 0x34, msg) # . . push args - 68/push "F - test-allocate-raw-success: returns current pointer of allocation descriptor"/imm32 - 68/push 0xb/imm32 - 50/push-eax + 68/push "F - test-allocate-raw-success: sets alloc-id in handle"/imm32 + 68/push 0x34/imm32 + ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h->payload, expected-payload, msg) + # . . push args + 68/push "F - test-allocate-raw-success: sets payload in handle"/imm32 + 53/push-ebx + ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(ad->curr, 18, msg) + # check-ints-equal(h->payload->alloc-id, 0x34, msg) + # . . push args + 68/push "F - test-allocate-raw-success: sets alloc-id in payload"/imm32 + 68/push 0x34/imm32 + ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(*Next-alloc-id, 0x35, msg) + # . . push args + 68/push "F - test-allocate-raw-success: increments Next-alloc-id"/imm32 + 68/push 0x35/imm32 + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(ad->curr - expected-payload, 3 + 4 for alloc-id, msg) # . . push args 68/push "F - test-allocate-raw-success: updates allocation descriptor"/imm32 - 68/push 0x12/imm32 - ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + 68/push 7/imm32 + 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax + 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax + 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 to esp + # clean up + c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +lookup: # h: (handle T) -> eax: (addr T) + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 51/push-ecx + # ecx = handle->alloc_id + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx + # eax = handle->address (payload) + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax + # if (ecx != *eax) abort + 39/compare 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # compare *eax and ecx + 75/jump-if-!= $lookup:abort/disp8 + # add 4 to eax + 05/add-to-eax 4/imm32 +$lookup:end: + # . restore registers + 59/pop-to-ecx # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return -_pending-test-allocate-raw-failure: +$lookup:abort: + # . _write(2/stderr, msg) + # . . push args + 68/push "lookup failed\n"/imm32 + 68/push 2/imm32/stderr + # . . call + e8/call _write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . syscall(exit, 1) + bb/copy-to-ebx 1/imm32/exit-status + b8/copy-to-eax 1/imm32/exit + cd/syscall 0x80/imm8 + +test-lookup-success: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ad/ecx: allocation-descriptor = {11, 15} - 68/push 0xf/imm32/limit - 68/push 0xb/imm32/curr + # . save registers + # var ad/ebx: allocation-descriptor + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx + # ad = new-segment(512) + # . . push args + 53/push-ebx + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # var handle/ecx: handle + 68/push 0/imm32/address + 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var eax: (handle byte) = allocate-raw(ad, 6) + # var old-top/edx = ad->curr + 8b/copy 0/mod/indirect 3/rm32/ebx . . . 2/r32/edx . . # copy *ebx to edx + # allocate-raw(ad, 2, handle) # . . push args - 68/push 6/imm32 51/push-ecx + 68/push 2/imm32/size + 53/push-ebx # . . call e8/call allocate-raw/disp32 # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # eax = lookup(handle) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) + ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # check-ints-equal(eax, 0, msg) + # eax contains old top of heap, except skipping the alloc-id in the payload + # . check-ints-equal(eax, old-top+4, msg) # . . push args - 68/push "F - test-allocate-raw-failure: returns null"/imm32 - 68/push 0/imm32 + 68/push "F - test-lookup-success"/imm32 + 81 0/subop/add 3/mod/direct 2/rm32/edx . . . . . 4/imm32 # add to edx + 52/push-edx 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 to esp - # no change to ad->curr - # . check-ints-equal(ad->curr, 11) + # clean up + # . *Next-alloc-id = 1 + c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id + # . restore registers + 5a/pop-to-edx + 59/pop-to-ecx + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +_pending-test-lookup-failure: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # var heap/esi: allocation-descriptor + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # heap = new-segment(512) # . . push args - 68/push "F - test-allocate-raw-failure: updates allocation descriptor"/imm32 - 68/push 0xb/imm32 - ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + 56/push-esi + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # var h1/ecx: handle + 68/push 0/imm32/address + 68/push 0/imm32/alloc-id + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # var old_top/ebx = heap->curr + 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx + # first allocation, to h1 + # . allocate(heap, 2, h1) + # . . push args + 51/push-ecx + 68/push 2/imm32/size + 56/push-esi + # . . call + e8/call allocate/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # reset heap->curr to mimic reclamation + 89/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy ebx to *esi + # second allocation that returns the same address as the first + # var h2/edx: handle + 68/push 0/imm32/address + 68/push 0/imm32/alloc-id + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # . allocate(heap, 2, h2) + # . . push args + 52/push-edx + 68/push 2/imm32/size + 56/push-esi + # . . call + e8/call allocate/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h1->address, h2->address, msg) + # . . push args + 68/push "F - test-lookup-failure"/imm32 + ff 6/subop/push 1/mod/*+disp8 2/rm32/ecx . . . . 4/disp8 . # push *(edx+4) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # lookup(h1) should crash + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) + ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # should never get past this point + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # clean up + # . *Next-alloc-id = 1 + c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp @@ -254,6 +444,8 @@ allocate-region: # ad: (addr allocation-descriptor), n: int, out: (addr handle # eax = out->payload 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax + # skip payload->allocid + 05/add-to-eax 4/imm32 # if (eax == 0) abort 3d/compare-eax-and 0/imm32 74/jump-if-= $allocate-region:abort/disp8 @@ -321,6 +513,9 @@ allocate-array: # ad: (addr allocation-descriptor), n: int, out: (addr handle) # *out->payload = n 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax + # . skip payload->allocid + 05/add-to-eax 4/imm32 + # . 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax $allocate-array:end: # . restore registers @@ -332,6 +527,268 @@ $allocate-array:end: 5d/pop-to-ebp c3/return +test-allocate-array: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # var ad/ecx: allocation-descriptor + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # ad = new-segment(512) + # . . push args + 51/push-ecx + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # var expected-payload/ebx = ad->curr + 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx + # var h/edx: handle = {0, 0} + 68/push 0/imm32 + 68/push 0/imm32 + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # *Next-alloc-id = 0x34 + c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id + # allocate-array(ad, 3, h) + # . . push args + 52/push-edx + 68/push 3/imm32 + 51/push-ecx + # . . call + e8/call allocate-array/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h->alloc-id, 0x34, msg) + # . . push args + 68/push "F - test-allocate-array: sets alloc-id in handle"/imm32 + 68/push 0x34/imm32 + ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h->payload, expected-payload, msg) + # . . push args + 68/push "F - test-allocate-array: sets payload in handle"/imm32 + 53/push-ebx + ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h->payload->alloc-id, 0x34, msg) + # . . push args + 68/push "F - test-allocate-array: sets alloc-id in payload"/imm32 + 68/push 0x34/imm32 + ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h->payload->size, 3, msg) + # . . push args + 68/push "F - test-allocate-array: sets array size in payload"/imm32 + 68/push 3/imm32 + ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(*Next-alloc-id, 0x35, msg) + # . . push args + 68/push "F - test-allocate-array: increments Next-alloc-id"/imm32 + 68/push 0x35/imm32 + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(ad->curr - expected-payload, 3 + 4 for alloc-id + 4 for array size, msg) + # . . push args + 68/push "F - test-allocate-array: updates allocation descriptor"/imm32 + 68/push 0xb/imm32 + 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax + 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax + 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 to esp + # clean up + c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +copy-array: # ad: (addr allocation-descriptor), src: (addr array), out: (addr handle) + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 56/push-esi + # esi = src + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi + # var size/ecx: int = src->size+4 + 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx + 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx + # allocate(ad, size, out) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) + 51/push-ecx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call allocate/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # var payload/eax: (addr byte) = out->payload + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax + 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax + # . skip payload->allocid + 05/add-to-eax 4/imm32 + # var max/ecx: (addr byte) = payload + size + 01/add 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # add eax to ecx + # _append-4(payload, max, src, &src->data[src->size]) + # . . push &src->data[src->size] + 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 2/index/edx . 2/r32/edx 4/disp8 . # copy esi+edx+4 to edx + 52/push-edx + # . . push src + 56/push-esi + # . . push max + 51/push-ecx + # . . push payload + 50/push-eax + # . . call + e8/call _append-4/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp +$copy-array:end: + # . restore registers + 5e/pop-to-esi + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-copy-array: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # var src/esi: (addr array int) = [3, 4, 5] + 68/push 5/imm32 + 68/push 4/imm32 + 68/push 3/imm32 + 68/push 0xc/imm32/size + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # var ad/ecx: allocation-descriptor + 68/push 0/imm32/limit + 68/push 0/imm32/curr + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # ad = new-segment(512) + # . . push args + 51/push-ecx + 68/push 0x200/imm32 + # . . call + e8/call new-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # var expected-payload/ebx = ad->curr + 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx + # var h/edx: handle = {0, 0} + 68/push 0/imm32 + 68/push 0/imm32 + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # *Next-alloc-id = 0x34 + c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id + # copy-array(ad, src, h) + # . . push args + 52/push-edx + 56/push-esi + 51/push-ecx + # . . call + e8/call copy-array/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h->alloc-id, 0x34, msg) + # . . push args + 68/push "F - test-copy-array: sets alloc-id in handle"/imm32 + 68/push 0x34/imm32 + ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h->payload, expected-payload, msg) + # . . push args + 68/push "F - test-copy-array: sets payload in handle"/imm32 + 53/push-ebx + ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(h->payload->alloc-id, 0x34, msg) + # . . push args + 68/push "F - test-copy-array: sets alloc-id in payload"/imm32 + 68/push 0x34/imm32 + ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # var payload/eax: (addr int) = lookup(h) + # . . push args + ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) + ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(payload->size, 0xc, msg) + # . . push args + 68/push "F - test-copy-array: sets array size in payload"/imm32 + 68/push 0xc/imm32 + ff 6/subop/push 0/mod/indirect 0/rm32/eax . . . . . . # push *eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(*Next-alloc-id, 0x35, msg) + # . . push args + 68/push "F - test-copy-array: increments Next-alloc-id"/imm32 + 68/push 0x35/imm32 + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # check-ints-equal(ad->curr - expected-payload, 12 + 4 for alloc-id + 4 for length, msg) + # . . push args + 68/push "F - test-copy-array: updates allocation descriptor"/imm32 + 68/push 0x14/imm32 + 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax + 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax + 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 to esp + # clean up + c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + # Fill a region of memory with zeroes. zero-out: # start: (addr byte), len: int # pseudocode: diff --git a/070new-stream.subx b/070new-stream.subx index b4326096..a219c347 100644 --- a/070new-stream.subx +++ b/070new-stream.subx @@ -5,14 +5,14 @@ # . 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 -new-stream: # ad: (addr allocation-descriptor), length: int, elemsize: int, out: (handle stream _) +new-stream: # ad: (addr allocation-descriptor), length: int, elemsize: int, out: (addr handle stream _) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 50/push-eax 52/push-edx - # var n/eax: int = elemsize * length + 12 (for read, write and size) + # var size/edx: int = elemsize*length (clobbering eax) # . eax = elemsize 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax # . eax *= length @@ -23,7 +23,7 @@ new-stream: # ad: (addr allocation-descriptor), length: int, elemsize: int, out 75/jump-if-!= $new-stream:abort/disp8 # . edx = elemsize*length 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx - # . eax += 12 + # var n/eax: int = size + 12 (for read, write and size) 05/add-to-eax 0xc/imm32 # allocate(ad, n, out) # . . push args @@ -39,7 +39,7 @@ new-stream: # ad: (addr allocation-descriptor), length: int, elemsize: int, out 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax # skip payload->allocid 05/add-to-eax 4/imm32 - # eax->size = elemsize*length + # eax->size = size 89/copy 1/mod/*+disp8 0/rm32/eax . . . 2/r32/edx 8/disp8 . # copy edx to *(eax+8) # clear-stream(eax) # . . push args diff --git a/081table.subx b/081table.subx index ed1e9a92..3916bad5 100644 --- a/081table.subx +++ b/081table.subx @@ -1,7 +1,6 @@ # A table is a stream of (key, value) rows. # -# Each row consists of a 4-byte key -- a 'string_key' which is (addr array -# byte) -- and a variable-size value. +# Each row consists of an 8-byte key -- a (handle array byte) -- and a variable-size value. # # Accessing the table performs a linear scan for a key string, and always # requires passing in the row size. @@ -13,6 +12,7 @@ # ------------------------+--------------------------------------------------- # abort | get get-slice # insert key | get-or-insert get-or-insert-slice +# | get-or-insert-handle # stop | get-or-stop get-slice-or-stop # return null | maybe-get maybe-get-slice # Some variants may take extra args. @@ -23,14 +23,14 @@ # . 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 # if no row is found, abort -# type string_key = (addr array byte) -get: # table: (addr stream {string_key, T}), key: string_key, row-size: int, abort-message-prefix: (addr array byte) -> eax: (addr T) +get: # table: (addr stream {(handle array byte), T}), key: (addr array byte), row-size: int, abort-message-prefix: (addr array byte) -> eax: (addr T) # pseudocode: # curr = table->data # max = &table->data[table->write] # while curr < max - # if string-equal?(key, *curr) - # return curr+4 + # var c: (addr array byte) = lookup(*curr) + # if string-equal?(key, c) + # return curr+8 # curr += row-size # abort # @@ -43,7 +43,7 @@ get: # table: (addr stream {string_key, T}), key: string_key, row-size: int, ab 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var curr/ecx: (addr string_key) = table->data + # var curr/ecx: (addr handle array byte) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx # var max/edx: (addr byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx @@ -52,19 +52,27 @@ $get:search-loop: # if (curr >= max) abort 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $get:abort/disp8 - # if (string-equal?(key, *curr)) return curr+4 - # . eax = string-equal?(key, *curr) + # var c/eax: (addr array byte) = lookup(*curr) # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (string-equal?(key, c)) return curr+8 + # . eax = string-equal?(key, c) + # . . push args + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return eax = curr+4 + # . if (eax != false) return eax = curr+8 3d/compare-eax-and 0/imm32/false 74/jump-if-= $get:mismatch/disp8 - 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax + 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy ecx+8 to eax eb/jump $get:end/disp8 $get:mismatch: # curr += row-size @@ -100,7 +108,7 @@ $get:abort: 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # . _write(2/stderr, key) # . . push args - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + 56/push-esi 68/push 2/imm32/stderr # . . call e8/call _write/disp32 @@ -125,45 +133,47 @@ test-get: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # - setup: create a table with a couple of keys - # var table/ecx: (stream {string, number} 16) # 2 rows * 8 bytes/row - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp - 68/push 0x10/imm32/size + # var table/ecx: (stream {(handle array byte), number} 24) # 2 rows * 12 bytes/row + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # subtract from esp + 68/push 0x18/imm32/size 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # insert(table, "code", 8 bytes per row) + # insert(table, "code", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # insert(table, "data", 8 bytes per row) + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # insert(table, "data", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "data"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp $test-get:check1: - # eax = get(table, "code", 8 bytes per row) + # eax = get(table, "code", 12 bytes/row) # . . push args - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(eax - table->data, 4, msg) - # . check-ints-equal(eax - table, 16, msg) + # check-ints-equal(eax - table->data, 8, msg) + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-get/0"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -171,20 +181,20 @@ $test-get:check1: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp $test-get:check2: - # eax = get(table, "data", 8 bytes per row) + # eax = get(table, "data", 12 bytes/row) # . . push args - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 68/push "data"/imm32 51/push-ecx # . . call e8/call get/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(eax - table->data, 12, msg) - # . check-ints-equal(eax - table, 24, msg) + # check-ints-equal(eax - table->data, 20, msg) + # . check-ints-equal(eax - table, 32, msg) # . . push args 68/push "F - test-get/1"/imm32 - 68/push 0x18/imm32 + 68/push 0x20/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -198,13 +208,14 @@ $test-get:end: c3/return # if no row is found, abort -get-slice: # table: (addr stream {string_key, T}), key: (addr slice), row-size: int, abort-message-prefix: (addr array byte) -> eax: (addr T) +get-slice: # table: (addr stream {(handle array byte), T}), key: (addr slice), row-size: int, abort-message-prefix: (addr array byte) -> eax: (addr T) # pseudocode: # curr = table->data # max = &table->data[table->write] # while curr < max - # if slice-equal?(key, *curr) - # return curr+4 + # var c: (addr array byte) = lookup(*curr) + # if slice-equal?(key, c) + # return curr+8 # curr += row-size # abort # @@ -217,7 +228,7 @@ get-slice: # table: (addr stream {string_key, T}), key: (addr slice), row-size: 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var curr/ecx: (addr string_key) = table->data + # var curr/ecx: (addr handle array byte) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx # var max/edx: (addr byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx @@ -226,19 +237,27 @@ $get-slice:search-loop: # if (curr >= max) abort 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $get-slice:abort/disp8 - # if (slice-equal?(key, *curr)) return curr+4 - # . eax = slice-equal?(key, *curr) + # var c/eax: (addr array byte) = lookup(*curr) # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (slice-equal?(key, c)) return curr+8 + # . eax = slice-equal?(key, c) + # . . push args + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return eax = curr+4 + # . if (eax != false) return eax = curr+8 3d/compare-eax-and 0/imm32/false 74/jump-if-= $get-slice:mismatch/disp8 - 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax + 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy ecx+8 to eax eb/jump $get-slice:end/disp8 $get-slice:mismatch: # curr += row-size @@ -306,30 +325,32 @@ test-get-slice: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # - setup: create a table with a couple of keys - # var table/ecx: (stream {string, number} 16) # 2 rows * 8 bytes/row - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp - 68/push 0x10/imm32/size + # var table/ecx: (stream {string, number} 24) # 2 rows * 12 bytes/row + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # subtract from esp + 68/push 0x18/imm32/size 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # insert(table, "code", 8 bytes per row) + # insert(table, "code", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # insert(table, "data", 8 bytes per row) + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # insert(table, "data", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "data"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp $test-get-slice:check1: # (eax..edx) = "code" b8/copy-to-eax "code"/imm32 @@ -340,20 +361,20 @@ $test-get-slice:check1: 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # eax = get-slice(table, "code", 8 bytes per row) + # eax = get-slice(table, "code", 12 bytes/row) # . . push args - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 52/push-edx 51/push-ecx # . . call e8/call get-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(eax - table->data, 4, msg) # first row's value slot returned - # . check-ints-equal(eax - table, 16, msg) + # check-ints-equal(eax - table->data, 8, msg) # first row's value slot returned + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-get-slice/0"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -370,20 +391,20 @@ $test-get-slice:check2: 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # eax = get-slice(table, "data" slice, 8 bytes per row) + # eax = get-slice(table, "data" slice, 12 bytes/row) # . . push args - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 52/push-edx 51/push-ecx # . . call e8/call get-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(eax - table->data, 12, msg) - # . check-ints-equal(eax - table, 24, msg) + # check-ints-equal(eax - table->data, 20, msg) + # . check-ints-equal(eax - table, 32, msg) # . . push args 68/push "F - test-get-slice/1"/imm32 - 68/push 0x18/imm32 + 68/push 0x20/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -399,22 +420,21 @@ $test-get-slice:end: # if no row is found, save 'key' to the next available row # if there are no rows free, abort # return the address of the value -# Beware: assume keys are immutable; they're inserted by reference -# TODO: pass in an allocation descriptor -get-or-insert: # table: (addr stream {string_key, T}), key: string_key, row-size: int -> eax: (addr T) +get-or-insert: # table: (addr stream {(handle array byte), T}), key: (addr array byte), row-size: int, ad: (addr allocation-descriptor) -> eax: (addr T) # pseudocode: # curr = table->data # max = &table->data[table->write] # while curr < max - # if string-equal?(key, *curr) - # return curr+4 + # var c: (addr array byte) = lookup(*curr) + # if string-equal?(key, c) + # return curr+8 # curr += row-size # if table->write >= table->size # abort # zero-out(max, row-size) - # *max = key + # copy-array(ad, key, max) # table->write += row-size - # return max+4 + # return max+8 # # . prologue 55/push-ebp @@ -425,28 +445,36 @@ get-or-insert: # table: (addr stream {string_key, T}), key: string_key, row-siz 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var curr/ecx: (addr string_key) = table->data + # var curr/ecx: (addr handle array byte) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # var max/edx: (addr string_key) = &table->data[table->write] + # var max/edx: (addr byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $get-or-insert:search-loop: # if (curr >= max) break 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $get-or-insert:not-found/disp8 - # if (string-equal?(key, *curr)) return curr+4 - # . eax = string-equal?(key, *curr) + # var c/eax: (addr array byte) = lookup(*curr) # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (string-equal?(key, c)) return curr+8 + # . eax = string-equal?(key, c) + # . . push args + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return eax = curr+4 + # . if (eax != false) return eax = curr+8 3d/compare-eax-and 0/imm32/false 74/jump-if-= $get-or-insert:mismatch/disp8 - 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax + 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy ecx+8 to eax eb/jump $get-or-insert:end/disp8 $get-or-insert:mismatch: # curr += row-size @@ -454,8 +482,6 @@ $get-or-insert:mismatch: # loop eb/jump $get-or-insert:search-loop/disp8 $get-or-insert:not-found: - # result/eax = 0 - 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax # if (table->write >= table->size) abort 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx 3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(esi+8) @@ -468,21 +494,25 @@ $get-or-insert:not-found: e8/call zero-out/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # *max = key - # . eax = key - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax - # . *max = eax - 89/copy 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # copy eax to *edx + # copy-array(ad, key, max) + # . . push args + 52/push-edx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20) + # . . call + e8/call copy-array/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # table->write += row-size # . eax = row-size 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax # . table->write += eax 01/add 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # add eax to *esi - # return max+4 + # return max+8 # . eax = max 89/copy 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # copy edx to eax - # . eax += 4 - 05/add-to-eax 4/imm32 + # . eax += 8 + 05/add-to-eax 8/imm32 $get-or-insert:end: # . restore registers 5e/pop-to-esi @@ -512,69 +542,78 @@ test-get-or-insert: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var table/ecx: (stream {string, number} 16) # 2 rows * 8 bytes/row - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp - 68/push 0x10/imm32/size + # var table/ecx: (stream {(handle array byte), number} 24) # 2 rows * 12 bytes/row + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # subtract from esp + 68/push 0x18/imm32/size 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx $test-get-or-insert:first-call: # - start with an empty table, insert one key, verify that it was inserted - # eax = get-or-insert(table, "code", 8 bytes per row) + # eax = get-or-insert(table, "code", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(eax - table->data, 4, msg) # first row's value slot returned - # . check-ints-equal(eax - table, 16, msg) + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # check-ints-equal(eax - table->data, 8, msg) # first row's value slot returned + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-get-or-insert/0"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 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 to esp -$test-get-or-insert:check2: - # check-ints-equal(table->write, row-size = 8, msg) + # check-ints-equal(table->write, row-size = 12, msg) # . . push args 68/push "F - test-get-or-insert/1"/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-strings-equal(*table->data, "code", msg) + # var curr-addr/eax: (addr array byte) = lookup(table->data) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x10/disp8 . # push *(ecx+16) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-strings-equal(curr-addr, "code", msg) # . . push args 68/push "F - test-get-or-insert/2"/imm32 68/push "code"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + 50/push-eax # . . call e8/call check-strings-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp $test-get-or-insert:second-call: # - insert the same key again, verify that it was reused - # eax = get-or-insert(table, "code", 8 bytes per row) + # eax = get-or-insert(table, "code", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(eax - table->data, 4, msg) - # . check-ints-equal(eax - table, 16, msg) + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # check-ints-equal(eax - table->data, 8, msg) + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-get-or-insert/3"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -582,62 +621,78 @@ $test-get-or-insert:second-call: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # no new row inserted - # . check-ints-equal(table->write, row-size = 8, msg) + # . check-ints-equal(table->write, row-size = 12, msg) # . . push args 68/push "F - test-get-or-insert/4"/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-strings-equal(*table->data, "code", msg) + # curr-addr = lookup(table->data) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x10/disp8 . # push *(ecx+16) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-strings-equal(curr-addr, "code", msg) # . . push args 68/push "F - test-get-or-insert/5"/imm32 68/push "code"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + 50/push-eax # . . call e8/call check-strings-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp $test-get-or-insert:third-call: # - insert a new key, verify that it was inserted - # eax = get-or-insert(table, "data", 8 bytes per row) + # eax = get-or-insert(table, "data", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "data"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp # table gets a new row - # check-ints-equal(eax - table->data, 12, msg) # second row's value slot returned - # . check-ints-equal(eax - table, 24, msg) + # check-ints-equal(eax - table->data, 20, msg) # second row's value slot returned + # . check-ints-equal(eax - table, 32, msg) # . . push args 68/push "F - test-get-or-insert/6"/imm32 - 68/push 0x18/imm32 + 68/push 0x20/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 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 to esp - # check-ints-equal(table->write, 2 rows = 16, msg) + # check-ints-equal(table->write, 2 rows = 24, msg) # . . push args 68/push "F - test-get-or-insert/7"/imm32 - 68/push 0x10/imm32/two-rows + 68/push 0x18/imm32/two-rows ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-strings-equal(*table->data+8, "data", msg) - # check-strings-equal(*(table+20), "data", msg) + # curr-addr = lookup(table->data+12) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x1c/disp8 . # push *(ecx+28) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x18/disp8 . # push *(ecx+24) + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-strings-equal(curr-addr, "data", msg) # . . push args 68/push "F - test-get-or-insert/8"/imm32 68/push "data"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x14/disp8 . # push *(ecx+20) + 50/push-eax # . . call e8/call check-strings-equal/disp32 # . . discard args @@ -650,20 +705,21 @@ $test-get-or-insert:end: # if no row is found, save 'key' in the next available row # if there are no rows free, abort -get-or-insert-slice: # table: (addr stream {string_key, T}), key: (addr slice), row-size: int, ad: (address allocation-descriptor) -> eax: (addr T) +get-or-insert-slice: # table: (addr stream {(handle array byte), T}), key: (addr slice), row-size: int, ad: (addr allocation-descriptor) -> eax: (addr T) # pseudocode: # curr = table->data # max = &table->data[table->write] # while curr < max + # var c: (addr array byte) = lookup(*curr) # if slice-equal?(key, *curr) - # return curr+4 + # return curr+8 # curr += row-size # if table->write >= table->size # abort # zero-out(max, row-size) - # *max = slice-to-string(ad, key) + # slice-to-string(ad, key, max) # table->write += row-size - # return max+4 + # return max+8 # # . prologue 55/push-ebp @@ -674,28 +730,36 @@ get-or-insert-slice: # table: (addr stream {string_key, T}), key: (addr slice), 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var curr/ecx: (addr string_key) = table->data + # var curr/ecx: (addr handle array byte) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # var max/edx: (addr string_key) = &table->data[table->write] + # var max/edx: (addr byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $get-or-insert-slice:search-loop: # if (curr >= max) break 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $get-or-insert-slice:not-found/disp8 - # if (slice-equal?(key, *curr)) return curr+4 - # . eax = slice-equal?(key, *curr) + # var c/eax: (addr array byte) = lookup(*curr) # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (slice-equal?(key, c)) return curr+4 + # . eax = slice-equal?(key, c) + # . . push args + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return eax = curr+4 + # . if (eax != false) return eax = curr+8 3d/compare-eax-and 0/imm32/false 74/jump-if-= $get-or-insert-slice:mismatch/disp8 - 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax + 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy ecx+8 to eax eb/jump $get-or-insert-slice:end/disp8 $get-or-insert-slice:mismatch: # curr += row-size @@ -717,27 +781,25 @@ $get-or-insert-slice:not-found: e8/call zero-out/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # *max = slice-to-string(ad, key) - # . eax = slice-to-string(ad, key) + # slice-to-string(ad, key, max) # . . push args + 52/push-edx ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20) # . . call e8/call slice-to-string/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . *max = eax - 89/copy 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # copy eax to *edx + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # table->write += row-size # . eax = row-size 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax # . table->write += eax 01/add 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # add eax to *esi - # return max+4 + # return max+8 # . eax = max 89/copy 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # copy edx to eax - # . eax += 4 - 05/add-to-eax 4/imm32 + # . eax += 8 + 05/add-to-eax 8/imm32 $get-or-insert-slice:end: # . restore registers 5e/pop-to-esi @@ -767,9 +829,9 @@ test-get-or-insert-slice: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var table/ecx: (stream {string, number} 16) # 2 rows * 8 bytes/row - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp - 68/push 0x10/imm32/size + # var table/ecx: (stream {string, number} 24) # 2 rows * 12 bytes/row + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # subtract from esp + 68/push 0x18/imm32/size 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -784,63 +846,70 @@ test-get-or-insert-slice: 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx $test-get-or-insert-slice:first-call: # - start with an empty table, insert one key, verify that it was inserted - # eax = get-or-insert-slice(table, "code" slice, 8 bytes per row) + # eax = get-or-insert-slice(table, "code" slice, 12 bytes/row, Heap) # . . push args 68/push Heap/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 52/push-edx 51/push-ecx # . . call e8/call get-or-insert-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # check-ints-equal(eax - table->data, 4, msg) # first row's value slot returned - # . check-ints-equal(eax - table, 16, msg) + # check-ints-equal(eax - table->data, 8, msg) # first row's value slot returned + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-get-or-insert-slice/0"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 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 to esp -$test-get-or-insert-slice:check2: - # check-ints-equal(table->write, row-size = 8, msg) + # check-ints-equal(table->write, row-size = 12, msg) # . . push args 68/push "F - test-get-or-insert-slice/1"/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-strings-equal(*table->data, "code", msg) + # var curr-addr/eax: (addr array byte) = lookup(table->data) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x10/disp8 . # push *(ecx+16) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-strings-equal(curr-addr, "code", msg) # . . push args 68/push "F - test-get-or-insert-slice/2"/imm32 68/push "code"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + 50/push-eax # . . call e8/call check-strings-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp $test-get-or-insert-slice:second-call: # - insert the same key again, verify that it was reused - # eax = get-or-insert-slice(table, "code" slice, 8 bytes per row) + # eax = get-or-insert-slice(table, "code" slice, 12 bytes/row) # . . push args 68/push Heap/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 52/push-edx 51/push-ecx # . . call e8/call get-or-insert-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # check-ints-equal(eax - table->data, 4, msg) - # . check-ints-equal(eax - table, 16, msg) + # check-ints-equal(eax - table->data, 8, msg) + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-get-or-insert-slice/3"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -848,20 +917,28 @@ $test-get-or-insert-slice:second-call: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # no new row inserted - # . check-ints-equal(table->write, row-size = 8, msg) + # . check-ints-equal(table->write, row-size = 12, msg) # . . push args 68/push "F - test-get-or-insert-slice/4"/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-strings-equal(*table->data, "code", msg) + # curr-addr = lookup(table->data) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x10/disp8 . # push *(ecx+16) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-strings-equal(curr-addr, "code", msg) # . . push args 68/push "F - test-get-or-insert-slice/5"/imm32 68/push "code"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + 50/push-eax # . . call e8/call check-strings-equal/disp32 # . . discard args @@ -877,10 +954,10 @@ $test-get-or-insert-slice:third-call: 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # eax = get-or-insert-slice(table, "data" slice, 8 bytes per row) + # eax = get-or-insert-slice(table, "data" slice, 12 bytes/row) # . . push args 68/push Heap/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 52/push-edx 51/push-ecx # . . call @@ -888,32 +965,39 @@ $test-get-or-insert-slice:third-call: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp # table gets a new row - # check-ints-equal(eax - table->data, 12, msg) # second row's value slot returned - # . check-ints-equal(eax - table, 24, msg) + # check-ints-equal(eax - table->data, 20, msg) # second row's value slot returned + # . check-ints-equal(eax - table, 32, msg) # . . push args 68/push "F - test-get-or-insert-slice/6"/imm32 - 68/push 0x18/imm32 + 68/push 0x20/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 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 to esp - # check-ints-equal(table->write, 2 rows = 16, msg) + # check-ints-equal(table->write, 2 rows = 24, msg) # . . push args 68/push "F - test-get-or-insert-slice/7"/imm32 - 68/push 0x10/imm32/two-rows + 68/push 0x18/imm32/two-rows ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-strings-equal(*table->data+8, "data", msg) - # check-strings-equal(*(table+20), "data", msg) + # curr-addr = lookup(table->data+12) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x1c/disp8 . # push *(ecx+28) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x18/disp8 . # push *(ecx+24) + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-strings-equal(curr-addr, "data", msg) # . . push args 68/push "F - test-get-or-insert-slice/8"/imm32 68/push "data"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x14/disp8 . # push *(ecx+20) + 50/push-eax # . . call e8/call check-strings-equal/disp32 # . . discard args @@ -925,15 +1009,16 @@ $test-get-or-insert-slice:end: c3/return # if no row is found, stop(ed) -get-or-stop: # table: (addr stream {string_key, T}), key: string_key, row-size: int, +get-or-stop: # table: (addr stream {(handle array byte), T}), key: (addr array byte), row-size: int, # abort-message-prefix: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor) # -> eax: (addr T) # pseudocode: # curr = table->data # max = &table->data[table->write] # while curr < max - # if string-equal?(key, *curr) - # return curr+4 + # var c: (addr array byte) = lookup(*curr) + # if string-equal?(key, c) + # return curr+8 # curr += row-size # write-buffered(err, msg) # stop(ed) @@ -947,7 +1032,7 @@ get-or-stop: # table: (addr stream {string_key, T}), key: string_key, row-size: 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var curr/ecx: (addr string_key) = table->data + # var curr/ecx: (addr handle array byte) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx # var max/edx: (addr byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx @@ -956,19 +1041,27 @@ $get-or-stop:search-loop: # if (curr >= max) stop(ed) 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $get-or-stop:stop/disp8 - # if (string-equal?(key, *curr)) return curr+4 - # . eax = string-equal?(key, *curr) + # var c/eax: (addr array byte) = lookup(*curr) # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (string-equal?(key, c)) return curr+8 + # . eax = string-equal?(key, c) + # . . push args + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return eax = curr+4 + # . if (eax != false) return eax = curr+8 3d/compare-eax-and 0/imm32/false 74/jump-if-= $get-or-stop:mismatch/disp8 - 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax + 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy ecx+8 to eax eb/jump $get-or-stop:end/disp8 $get-or-stop:mismatch: # curr += row-size @@ -1052,9 +1145,9 @@ test-get-or-stop: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var table/ecx: (stream {string, number} 16) # 2 rows * 8 bytes/row - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp - 68/push 0x10/imm32/size + # var table/ecx: (stream {string, number} 24) # 2 rows * 12 bytes/row + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # subtract from esp + 68/push 0x18/imm32/size 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -1071,22 +1164,23 @@ test-get-or-stop: e8/call tailor-exit-descriptor/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # insert(table, "code", 8 bytes per row) + # insert(table, "code", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp $test-get-or-stop:success: - # eax = get-or-stop(table, "code", row-size=8, msg, _test-error-buffered-file, ed) + # eax = get-or-stop(table, "code", row-size=12, msg, _test-error-buffered-file, ed) # . . push args 52/push-edx/ed 68/push _test-error-buffered-file/imm32 68/push "foo"/imm32/abort-prefix - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call @@ -1094,11 +1188,11 @@ $test-get-or-stop:success: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # add to esp $test-get-or-stop:success-assertion: - # check-ints-equal(eax - table->data, 4, msg) - # . check-ints-equal(eax - table, 16, msg) + # check-ints-equal(eax - table->data, 8, msg) + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-get-or-stop/0"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -1106,12 +1200,12 @@ $test-get-or-stop:success-assertion: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp $test-get-or-stop:failure: - # eax = get-or-stop(table, "data", row-size=8, msg, _test-error-buffered-file, ed) + # eax = get-or-stop(table, "data", row-size=12, msg, _test-error-buffered-file, ed) # . . push args 52/push-edx/ed 68/push _test-error-buffered-file/imm32 68/push "foo"/imm32/abort-prefix - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 68/push "data"/imm32 51/push-ecx # . . call @@ -1136,20 +1230,21 @@ $test-get-or-stop:failure-assertion: $test-get-or-stop:end: # . epilogue # don't restore esp from ebp; manually reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x24/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x2c/imm32 # add to esp 5d/pop-to-ebp c3/return # if no row is found, stop(ed) -get-slice-or-stop: # table: (addr stream {string_key, _}), key: (addr slice), row-size: int, +get-slice-or-stop: # table: (addr stream {(handle array byte), _}), key: (addr slice), row-size: int, # abort-message-prefix: (addr string), err: (addr buffered-file), ed: (addr exit-descriptor) # -> eax: (addr _) # pseudocode: # curr = table->data # max = &table->data[table->write] # while curr < max - # if slice-equal?(key, *curr) - # return curr+4 + # var c: (addr array byte) = lookup(*curr) + # if slice-equal?(key, c) + # return curr+8 # curr += row-size # write-buffered(err, msg) # stop(ed) @@ -1163,7 +1258,7 @@ get-slice-or-stop: # table: (addr stream {string_key, _}), key: (addr slice), r 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var curr/ecx: (addr string_key) = table->data + # var curr/ecx: (addr handle array byte) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx # var max/edx: (addr byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx @@ -1172,19 +1267,27 @@ $get-slice-or-stop:search-loop: # if (curr >= max) stop(ed) 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $get-slice-or-stop:stop/disp8 - # if (slice-equal?(key, *curr)) return curr+4 - # . eax = slice-equal?(key, *curr) + # var c/eax: (addr array byte) = lookup(*curr) # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (slice-equal?(key, c)) return curr+4 + # . eax = slice-equal?(key, c) + # . . push args + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return eax = curr+4 + # . if (eax != false) return eax = curr+8 3d/compare-eax-and 0/imm32/false 74/jump-if-= $get-slice-or-stop:mismatch/disp8 - 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax + 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy ecx+8 to eax eb/jump $get-slice-or-stop:end/disp8 $get-slice-or-stop:mismatch: # curr += row-size @@ -1268,9 +1371,9 @@ test-get-slice-or-stop: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var table/ecx: (stream {string, number} 16) # 2 rows * 8 bytes/row - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp - 68/push 0x10/imm32/size + # var table/ecx: (stream {string, number} 24) # 2 rows * 12 bytes/row + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # subtract from esp + 68/push 0x18/imm32/size 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -1297,22 +1400,23 @@ test-get-slice-or-stop: e8/call tailor-exit-descriptor/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # insert(table, "code", 8 bytes per row) + # insert(table, "code", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp $test-get-slice-or-stop:success: - # eax = get-slice-or-stop(table, slice, row-size=8, msg, _test-error-buffered-file, ed) + # eax = get-slice-or-stop(table, slice, row-size=12, msg, _test-error-buffered-file, ed) # . . push args 52/push-edx/ed 68/push _test-error-buffered-file/imm32 68/push "foo"/imm32/abort-prefix - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 53/push-ebx/slice 51/push-ecx # . . call @@ -1324,11 +1428,11 @@ $test-get-slice-or-stop:success: 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5a/pop-to-edx $test-get-slice-or-stop:success-assertion: - # check-ints-equal(eax - table->data, 4, msg) # first row's value slot returned - # . check-ints-equal(eax - table, 16, msg) + # check-ints-equal(eax - table->data, 8, msg) # first row's value slot returned + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-get-slice-or-stop/0"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -1344,12 +1448,12 @@ $test-get-slice-or-stop:failure: # . *(ebx+4) = "segment2"->data + len("segment2") 05/add-to-eax 8/imm32/strlen 89/copy 1/mod/*+disp8 3/rm32/ebx . . . 0/r32/eax 4/disp8 . # copy eax to *(ebx+4) - # eax = get-slice-or-stop(table, slice, row-size=8, msg, _test-error-buffered-file, ed) + # eax = get-slice-or-stop(table, slice, row-size=12, msg, _test-error-buffered-file, ed) # . . push args 52/push-edx/ed 68/push _test-error-buffered-file/imm32 68/push "foo"/imm32/abort-prefix - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 53/push-ebx/slice 51/push-ecx # . . call @@ -1375,18 +1479,19 @@ $test-get-slice-or-stop:failure-assertion: $test-get-slice-or-stop:end: # . epilogue # don't restore esp from ebp; manually reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x2c/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x34/imm32 # add to esp 5d/pop-to-ebp c3/return # if no row is found, return null (0) -maybe-get: # table: (addr stream {string_key, T}), key: string_key, row-size: int -> eax: (addr T) +maybe-get: # table: (addr stream {(handle array byte), T}), key: (addr array byte), row-size: int -> eax: (addr T) # pseudocode: # curr = table->data # max = &table->data[table->write] # while curr < max - # if string-equal?(key, *curr) - # return curr+4 + # var c: (addr array byte) = lookup(*curr) + # if string-equal?(key, c) + # return curr+8 # curr += row-size # return 0 # @@ -1399,7 +1504,7 @@ maybe-get: # table: (addr stream {string_key, T}), key: string_key, row-size: i 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var curr/ecx: (addr string_key) = table->data + # var curr/ecx: (addr handle array byte) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx # var max/edx: (addr byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx @@ -1408,19 +1513,27 @@ $maybe-get:search-loop: # if (curr >= max) return null 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $maybe-get:null/disp8 - # if (string-equal?(key, *curr)) return curr+4 - # . eax = string-equal?(key, *curr) + # var c/eax: (addr array byte) = lookup(*curr) # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (string-equal?(key, c)) return curr+4 + # . eax = string-equal?(key, c) + # . . push args + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return eax = curr+4 + # . if (eax != false) return eax = curr+8 3d/compare-eax-and 0/imm32/false 74/jump-if-= $maybe-get:mismatch/disp8 - 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax + 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy ecx+8 to eax eb/jump $maybe-get:end/disp8 $maybe-get:mismatch: # curr += row-size @@ -1444,37 +1557,38 @@ test-maybe-get: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # - setup: create a table with one row - # var table/ecx: (stream {string, number} 16) # 2 rows * 8 bytes/row - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp - 68/push 0x10/imm32/size + # var table/ecx: (stream {string, number} 24) # 2 rows * 12 bytes/row + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # subtract from esp + 68/push 0x18/imm32/size 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # eax = get-or-insert(table, "code", 8 bytes per row) + # eax = get-or-insert(table, "code", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp $test-maybe-get:success: # - check for the same key, verify that it was reused - # eax = maybe-get(table, "code", 8 bytes per row) + # eax = maybe-get(table, "code", 12 bytes/row) # . . push args - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call maybe-get/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(eax - table->data, 4, msg) - # . check-ints-equal(eax - table, 16, msg) + # check-ints-equal(eax - table->data, 8, msg) + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-maybe-get/0"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -1482,29 +1596,37 @@ $test-maybe-get:success: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # no new row inserted - # . check-ints-equal(table->write, row-size = 8, msg) + # . check-ints-equal(table->write, row-size = 12, msg) # . . push args 68/push "F - test-maybe-get/1"/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-strings-equal(*table->data, "code", msg) + # var curr-addr/eax: (addr array byte) = lookup(table->data) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x10/disp8 . # push *(ecx+16) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-strings-equal(curr-addr, "code", msg) # . . push args 68/push "F - test-maybe-get/2"/imm32 68/push "code"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + 50/push-eax # . . call e8/call check-strings-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp $test-maybe-get:failure: # - search for a new key - # eax = maybe-get(table, "data", 8 bytes per row) + # eax = maybe-get(table, "data", 12 bytes/row) # . . push args - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 68/push "data"/imm32 51/push-ecx # . . call @@ -1527,13 +1649,14 @@ $test-maybe-get:end: c3/return # if no row is found, return null (0) -maybe-get-slice: # table: (addr stream {string_key, T}), key: (addr slice), row-size: int -> eax: (addr T) +maybe-get-slice: # table: (addr stream {(handle array byte), T}), key: (addr slice), row-size: int -> eax: (addr T) # pseudocode: # curr = table->data # max = &table->data[table->write] # while curr < max - # if slice-equal?(key, *curr) - # return curr+4 + # var c: (addr array byte) = lookup(*curr) + # if slice-equal?(key, c) + # return curr+8 # curr += row-size # return 0 # @@ -1546,7 +1669,7 @@ maybe-get-slice: # table: (addr stream {string_key, T}), key: (addr slice), row 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var curr/ecx: (addr string_key) = table->data + # var curr/ecx: (addr handle array byte) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx # var max/edx: (addr byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx @@ -1555,19 +1678,27 @@ $maybe-get-slice:search-loop: # if (curr >= max) return null 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-addr>= $maybe-get-slice:null/disp8 - # if (slice-equal?(key, *curr)) return curr+4 - # . eax = slice-equal?(key, *curr) + # var c/eax: (addr array byte) = lookup(*curr) # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (slice-equal?(key, c)) return curr+4 + # . eax = slice-equal?(key, c) + # . . push args + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return eax = curr+4 + # . if (eax != false) return eax = curr+8 3d/compare-eax-and 0/imm32/false 74/jump-if-= $maybe-get-slice:mismatch/disp8 - 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax + 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy ecx+8 to eax eb/jump $maybe-get-slice:end/disp8 $maybe-get-slice:mismatch: # curr += row-size @@ -1591,21 +1722,22 @@ test-maybe-get-slice: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # - setup: create a table with one row - # var table/ecx: (stream {string, number} 16) # 2 rows * 8 bytes/row - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp - 68/push 0x10/imm32/size + # var table/ecx: (stream {string, number} 24) # 2 rows * 12 bytes/row + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # subtract from esp + 68/push 0x18/imm32/size 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # insert(table, "code", 8 bytes per row) + # insert(table, "code", 12 bytes/row, Heap) # . . push args - 68/push 8/imm32/row-size + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size 68/push "code"/imm32 51/push-ecx # . . call e8/call get-or-insert/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp $test-maybe-get-slice:success: # - check for the same key, verify that it was reused # (eax..edx) = "code" @@ -1617,20 +1749,20 @@ $test-maybe-get-slice:success: 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # eax = maybe-get-slice(table, "code" slice, 8 bytes per row) + # eax = maybe-get-slice(table, "code" slice, 12 bytes/row) # . . push args - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 52/push-edx 51/push-ecx # . . call e8/call maybe-get-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(eax - table->data, 4, msg) - # . check-ints-equal(eax - table, 16, msg) + # check-ints-equal(eax - table->data, 8, msg) + # . check-ints-equal(eax - table, 20, msg) # . . push args 68/push "F - test-maybe-get-slice/0"/imm32 - 68/push 0x10/imm32 + 68/push 0x14/imm32 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 50/push-eax # . . call @@ -1638,20 +1770,28 @@ $test-maybe-get-slice:success: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # no new row inserted - # . check-ints-equal(table->write, row-size = 8, msg) + # . check-ints-equal(table->write, row-size = 12, msg) # . . push args 68/push "F - test-maybe-get-slice/1"/imm32 - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-strings-equal(*table->data, "code", msg) + # var curr-addr/eax: (addr array byte) = lookup(table->data) + # . . push args + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0x10/disp8 . # push *(ecx+16) + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + # . . call + e8/call lookup/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-strings-equal(curr-addr, "code", msg) # . . push args 68/push "F - test-maybe-get-slice/2"/imm32 68/push "code"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 0xc/disp8 . # push *(ecx+12) + 50/push-eax # . . call e8/call check-strings-equal/disp32 # . . discard args @@ -1667,9 +1807,9 @@ $test-maybe-get-slice:failure: 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # eax = maybe-get-slice(table, "data" slice, 8 bytes per row) + # eax = maybe-get-slice(table, "data" slice, 12 bytes/row) # . . push args - 68/push 8/imm32/row-size + 68/push 0xc/imm32/row-size 52/push-edx 51/push-ecx # . . call diff --git a/apps/handle b/apps/handle deleted file mode 100755 index 33486991..00000000 --- a/apps/handle +++ /dev/null Binary files differdiff --git a/apps/handle.subx b/apps/handle.subx deleted file mode 100644 index 8e0a7ec3..00000000 --- a/apps/handle.subx +++ /dev/null @@ -1,428 +0,0 @@ -# A sketch of Mu-style handles or kinda-safe pointers, that add a modicum of -# checking to dynamically allocated memory. -# -# This approach avoids using 'allocate' directly in favor of two primitives: -# - 'new', which allocates some space (the 'payload'), stores the address -# along with an opaque 'alloc id' in a 'handle', and prepends the same -# alloc id to the payload. -# - 'lookup', which checks that the alloc id at the start of a handle matches -# the alloc id at the start of the payload before returning the address. -# -# Layout of a handle: -# offset 0: alloc id -# offset 4: address -# -# To run: -# $ ./bootstrap translate init.linux 0*.subx apps/handle.subx -o apps/handle -# $ ./bootstrap run apps/handle -# Expected result is a successful lookup followed by a hard abort: -# lookup succeeded -# lookup failed -# (This file is a prototype. The 'tests' in it aren't real; failures are -# expected.) - -== code -# instruction effective address register 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 - -Entry: - # initialize heap - # . Heap = new-segment(Heap-size) - # . . push args - 68/push Heap/imm32 - ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size - # . . call - e8/call new-segment/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - - e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. -$handle-main:end: - # syscall(exit, Num-test-failures) - 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx - b8/copy-to-eax 1/imm32/exit - cd/syscall 0x80/imm8 - -new: # ad: (addr allocation-descriptor), n: int, out: (handle _) - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # . save registers - 50/push-eax - 51/push-ecx - 52/push-edx - # ecx = n+4 - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx - 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx - # var eax: (handle _) = allocate(ad, ecx) - # . . push args - 51/push-ecx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call allocate/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # edx = out - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx - # out->address = eax - 89/copy 1/mod/*+disp8 2/rm32/edx . . . 0/r32/eax 4/disp8 . # copy eax to *(edx+4) - # if (eax == 0) out->alloc_id = 0, return - 3d/compare-eax-and 0/imm32 - 75/jump-if-!= $new:continue/disp8 - c7 0/subop/copy 0/mod/indirect 2/rm32/edx . . . . . 0/imm32 # copy to *edx - eb/jump $new:end/disp8 -$new:continue: - # otherwise: - # ecx = *Next-alloc-id - 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 1/r32/ecx Next-alloc-id/disp32 # copy *Next-alloc-id to ecx - # *eax = *Next-alloc-id/ecx - 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax - # out->alloc_id = *Next-alloc-id - 89/copy 0/mod/indirect 2/rm32/edx . . . 1/r32/ecx . . # copy ecx to *edx - # increment *Next-alloc-id - ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # increment *Next-alloc-id -$new:end: - # . restore registers - 5a/pop-to-edx - 59/pop-to-ecx - 58/pop-to-eax - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-new: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var heap/edx: allocation-descriptor - 68/push 0/imm32/limit - 68/push 0/imm32/curr - 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # heap = new-segment(512) - # . . push args - 52/push-edx - 68/push 0x200/imm32 - # . . call - e8/call new-segment/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # *Next-alloc-id = 0x34 - c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id - # var handle/ecx: handle - 68/push 0/imm32/address - 68/push 0/imm32/alloc-id - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # new(heap, 2, handle/ecx) - # . . push args - 51/push-ecx - 68/push 2/imm32/size - 52/push-edx - # . . call - e8/call new/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(handle->alloc_id, 0x34, msg) - # . . push args - 68/push "F - test-new: alloc id of handle"/imm32 - 68/push 0x34/imm32 - ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(*handle->address, 0x34, msg) - # . . push args - 68/push "F - test-new: alloc id of payload"/imm32 - 68/push 0x34/imm32 - 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx - ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(*Next-alloc-id, 0x35) - # . . push args - 68/push "F - test-new: next alloc id"/imm32 - 68/push 0x35/imm32 - ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # copy to *Next-alloc-id - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # clean up - # . *Next-alloc-id = 1 - c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -_pending-test-new-failure: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # . *Next-alloc-id = 0x34 - c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id - # define an allocation-descriptor with no space left - # . var ad/eax: allocation-descriptor = {0x10, 0x10} - 68/push 0x10/imm32/limit - 68/push 0x10/imm32/curr - 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax - # . var handle/ecx = {random, random} - 68/push 1234/imm32/address - 68/push 5678/imm32/alloc-id - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # try to allocate - # . new(ad, 2, handle/ecx) - # . . push args - 51/push-ecx - 68/push 2/imm32/size - 50/push-eax - # . . call - e8/call new/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # handle should be cleared - # . check-ints-equal(handle->alloc_id, 0, msg) - # . . push args - 68/push "F - test-new-failure: alloc id of handle"/imm32 - 68/push 0/imm32 - ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-ints-equal(handle->address, 0, msg) - # . . push args - 68/push "F - test-new-failure: address of handle"/imm32 - 68/push 0/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # Next-alloc-id should be unmodified - # . check-ints-equal(*Next-alloc-id, 0x34) - # . . push args - 68/push "F - test-new-failure: next alloc id"/imm32 - 68/push 0x34/imm32 - ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # copy to *Next-alloc-id - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # clean up - # . *Next-alloc-id = 1 - c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -lookup: # h: (handle T) -> eax: (addr T) - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # - as a proof of concept for future inlining, uses no general-purpose registers besides the output (eax) - # eax = handle - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax - # - inline { - # push handle->alloc_id - ff 6/subop/push 0/mod/indirect 0/rm32/eax . . . . . . # push *eax - # eax = handle->address (payload) - 8b/copy 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # copy *(eax+4) to eax - # push handle->address - 50/push-eax - # eax = payload->alloc_id - 8b/copy 0/mod/indirect 0/rm32/eax . . . . . . # copy *eax to eax - # if (eax != handle->alloc_id) abort - 39/compare 1/mod/*+disp8 4/rm32/sib 4/base/esp 4/index/none . 0/r32/eax 4/disp8 . # compare *(esp+4) and eax - 75/jump-if-!= $lookup:abort/disp8 - # eax = pop handle->address - 58/pop-to-eax - # discard handle->alloc_id - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # add 4 - 05/add-to-eax 4/imm32 - # - } - # - alternative consuming a second register { -#? # ecx = handle->alloc_id -#? 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -#? # eax = handle->address (payload) -#? 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax -#? # if (ecx != *eax) abort -#? 39/compare 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # compare *eax and ecx -#? 75/jump-if-!= $lookup:abort/disp8 -#? # add 4 to eax -#? 05/add-to-eax 4/imm32 - # - } - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -$lookup:abort: - # . _write(2/stderr, msg) - # . . push args - 68/push "lookup failed\n"/imm32 - 68/push 2/imm32/stderr - # . . call - e8/call _write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . syscall(exit, 1) - bb/copy-to-ebx 1/imm32/exit-status - b8/copy-to-eax 1/imm32/exit - cd/syscall 0x80/imm8 - -test-lookup-success: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # . save registers - # var heap/ebx: allocation-descriptor - 68/push 0/imm32/limit - 68/push 0/imm32/curr - 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx - # heap = new-segment(512) - # . . push args - 53/push-ebx - 68/push 0x200/imm32 - # . . call - e8/call new-segment/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # var handle/ecx: handle - 68/push 0/imm32/address - 68/push 0/imm32/alloc-id - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var old_top/edx = heap->curr - 8b/copy 0/mod/indirect 3/rm32/ebx . . . 2/r32/edx . . # copy *ebx to edx - # new(heap, 2, handle) - # . . push args - 51/push-ecx - 68/push 2/imm32/size - 53/push-ebx - # . . call - e8/call new/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # eax = lookup(handle) - # . . push args - 51/push-ecx - # . . call - e8/call lookup/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # eax contains old top of heap, except skipping the alloc id in the payload - # . check-ints-equal(eax, old_top+4, msg) - # . . push args - 68/push "F - test-lookup-success"/imm32 - 81 0/subop/add 3/mod/direct 2/rm32/edx . . . . . 4/imm32 # add to edx - 52/push-edx - 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 to esp - # clean up - # . *Next-alloc-id = 1 - c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id - # write(2/stderr, "lookup succeeded\n") - # . . push args - 68/push "lookup succeeded\n"/imm32 - 68/push 2/imm32/stderr - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . restore registers - 5a/pop-to-edx - 59/pop-to-ecx - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-lookup-failure: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var heap/esi: allocation-descriptor - 68/push 0/imm32/limit - 68/push 0/imm32/curr - 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi - # heap = new-segment(512) - # . . push args - 56/push-esi - 68/push 0x200/imm32 - # . . call - e8/call new-segment/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # var h1/ecx: handle - 68/push 0/imm32/address - 68/push 0/imm32/alloc-id - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var old_top/ebx = heap->curr - 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx - # first allocation, to h1 - # . new(heap, 2, h1) - # . . push args - 51/push-ecx - 68/push 2/imm32/size - 56/push-esi - # . . call - e8/call new/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # reset heap->curr to mimic reclamation - 89/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy ebx to *esi - # second allocation that returns the same address as the first - # var h2/edx: handle - 68/push 0/imm32/address - 68/push 0/imm32/alloc-id - 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # . new(heap, 2, h2) - # . . push args - 52/push-edx - 68/push 2/imm32/size - 56/push-esi - # . . call - e8/call new/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # check-ints-equal(h1->address, h2->address, msg) - # . . push args - 68/push "F - test-lookup-failure"/imm32 - ff 6/subop/push 1/mod/*+disp8 2/rm32/ecx . . . . 4/disp8 . # push *(edx+4) - ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # lookup(h1) should crash - # . . push args - 51/push-ecx - # . . call - e8/call lookup/disp32 - # should never get past this point - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # clean up - # . *Next-alloc-id = 1 - c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -== data - -# Monotonically increasing counter for calls to 'new' -Next-alloc-id: # int - 1/imm32 - -# . . vim:nowrap:textwidth=0 diff --git a/apps/mu.subx b/apps/mu.subx index 112d3c29..307c65e2 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -7778,6 +7778,7 @@ $emit-subx-stmt:end: 5d/pop-to-ebp c3/return +# TODO: actually return the length in array elements, rather than the size in bytes translate-mu-length-stmt: # out: (address buffered-file), stmt: (handle stmt) # . prologue 55/push-ebp diff --git a/html/apps/handle.subx.html b/html/apps/handle.subx.html deleted file mode 100644 index 9cf47d93..00000000 --- a/html/apps/handle.subx.html +++ /dev/null @@ -1,495 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - apps/handle.subx</title> -<meta name="Generator" content="Vim/8.1"> -<meta name="plugin-version" content="vim8.1_v1"> -<meta name="syntax" content="none"> -<meta name="settings" content="number_lines,use_css,no_foldcolumn,expand_tabs,line_ids,prevent_copy="> -<meta name="colorscheme" content="minimal-light"> -<style type="text/css"> -<!-- -pre { font-family: monospace; color: #000000; background-color: #c6c6c6; } -body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; } -a { color:inherit; } -* { font-size:12pt; font-size: 1em; } -.subxComment { color: #005faf; } -.subxS2Comment { color: #8a8a8a; } -.subxFunction { color: #af5f00; text-decoration: underline; } -.subxH1Comment { color: #005faf; text-decoration: underline; } -.LineNr { } -.subxS1Comment { color: #0000af; } -.CommentedCode { color: #8a8a8a; } -.SpecialChar { color: #d70000; } -.Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } -.subxMinorFunction { color: #875f5f; } -.Constant { color: #008787; } -.subxTest { color: #5f8700; } ---> -</style> - -<script type='text/javascript'> -<!-- - -/* function to open any folds containing a jumped-to line before jumping to it */ -function JumpToLine() -{ - var lineNum; - lineNum = window.location.hash; - lineNum = lineNum.substr(1); /* strip off '#' */ - - if (lineNum.indexOf('L') == -1) { - lineNum = 'L'+lineNum; - } - var lineElem = document.getElementById(lineNum); - /* Always jump to new location even if the line was hidden inside a fold, or - * we corrected the raw number to a line ID. - */ - if (lineElem) { - lineElem.scrollIntoView(true); - } - return true; -} -if ('onhashchange' in window) { - window.onhashchange = JumpToLine; -} - ---> -</script> -</head> -<body onload='JumpToLine();'> -<a href='https://github.com/akkartik/mu/blob/master/apps/handle.subx'>https://github.com/akkartik/mu/blob/master/apps/handle.subx</a> -<pre id='vimCodeElement'> -<span id="L1" class="LineNr"> 1 </span><span class="subxComment"># A sketch of Mu-style handles or kinda-safe pointers, that add a modicum of</span> -<span id="L2" class="LineNr"> 2 </span><span class="subxComment"># checking to dynamically allocated memory.</span> -<span id="L3" class="LineNr"> 3 </span><span class="subxComment">#</span> -<span id="L4" class="LineNr"> 4 </span><span class="subxComment"># This approach avoids using 'allocate' directly in favor of two primitives:</span> -<span id="L5" class="LineNr"> 5 </span><span class="subxComment"># - 'new', which allocates some space (the 'payload'), stores the address</span> -<span id="L6" class="LineNr"> 6 </span><span class="subxComment"># along with an opaque 'alloc id' in a 'handle', and prepends the same</span> -<span id="L7" class="LineNr"> 7 </span><span class="subxComment"># alloc id to the payload.</span> -<span id="L8" class="LineNr"> 8 </span><span class="subxComment"># - 'lookup', which checks that the alloc id at the start of a handle matches</span> -<span id="L9" class="LineNr"> 9 </span><span class="subxComment"># the alloc id at the start of the payload before returning the address.</span> -<span id="L10" class="LineNr"> 10 </span><span class="subxComment">#</span> -<span id="L11" class="LineNr"> 11 </span><span class="subxComment"># Layout of a handle:</span> -<span id="L12" class="LineNr"> 12 </span><span class="subxComment"># offset 0: alloc id</span> -<span id="L13" class="LineNr"> 13 </span><span class="subxComment"># offset 4: address</span> -<span id="L14" class="LineNr"> 14 </span><span class="subxComment">#</span> -<span id="L15" class="LineNr"> 15 </span><span class="subxComment"># To run:</span> -<span id="L16" class="LineNr"> 16 </span><span class="subxComment"># $ ./bootstrap translate init.linux 0*.subx apps/handle.subx -o apps/handle</span> -<span id="L17" class="LineNr"> 17 </span><span class="subxComment"># $ ./bootstrap run apps/handle</span> -<span id="L18" class="LineNr"> 18 </span><span class="subxComment"># Expected result is a successful lookup followed by a hard abort:</span> -<span id="L19" class="LineNr"> 19 </span><span class="subxComment"># lookup succeeded</span> -<span id="L20" class="LineNr"> 20 </span><span class="subxComment"># lookup failed</span> -<span id="L21" class="LineNr"> 21 </span><span class="subxComment"># (This file is a prototype. The 'tests' in it aren't real; failures are</span> -<span id="L22" class="LineNr"> 22 </span><span class="subxComment"># expected.)</span> -<span id="L23" class="LineNr"> 23 </span> -<span id="L24" class="LineNr"> 24 </span>== code -<span id="L25" class="LineNr"> 25 </span><span class="subxComment"># instruction effective address register displacement immediate</span> -<span id="L26" class="LineNr"> 26 </span><span class="subxS1Comment"># . op subop mod rm32 base index scale r32</span> -<span id="L27" class="LineNr"> 27 </span><span class="subxS1Comment"># . 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</span> -<span id="L28" class="LineNr"> 28 </span> -<span id="L29" class="LineNr"> 29 </span><span class="SpecialChar">Entry</span>: -<span id="L30" class="LineNr"> 30 </span> <span class="subxComment"># initialize heap</span> -<span id="L31" class="LineNr"> 31 </span> <span class="subxS1Comment"># . Heap = new-segment(Heap-size)</span> -<span id="L32" class="LineNr"> 32 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L33" class="LineNr"> 33 </span> 68/push <span class="SpecialChar"><a href='../069allocate.subx.html#L22'>Heap</a></span>/imm32 -<span id="L34" class="LineNr"> 34 </span> ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='../069allocate.subx.html#L29'>Heap-size</a></span>/disp32 <span class="subxComment"># push *Heap-size</span> -<span id="L35" class="LineNr"> 35 </span> <span class="subxS2Comment"># . . call</span> -<span id="L36" class="LineNr"> 36 </span> e8/call <a href='../053new-segment.subx.html#L41'>new-segment</a>/disp32 -<span id="L37" class="LineNr"> 37 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L38" class="LineNr"> 38 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> -<span id="L39" class="LineNr"> 39 </span> -<span id="L40" class="LineNr"> 40 </span> e8/call run-tests/disp32 <span class="subxComment"># 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.</span> -<span id="L41" class="LineNr"> 41 </span><span class="Constant">$handle-main:end</span>: -<span id="L42" class="LineNr"> 42 </span> <span class="subxComment"># syscall(exit, Num-test-failures)</span> -<span id="L43" class="LineNr"> 43 </span> 8b/copy 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> 3/r32/ebx <span class="SpecialChar"><a href='../051test.subx.html#L90'>Num-test-failures</a></span>/disp32 <span class="subxComment"># copy *Num-test-failures to ebx</span> -<span id="L44" class="LineNr"> 44 </span> b8/copy-to-eax 1/imm32/exit -<span id="L45" class="LineNr"> 45 </span> cd/syscall 0x80/imm8 -<span id="L46" class="LineNr"> 46 </span> -<span id="L47" class="LineNr"> 47 </span><span class="subxFunction">new</span>: <span class="subxComment"># ad: (addr allocation-descriptor), n: int, out: (handle _)</span> -<span id="L48" class="LineNr"> 48 </span> <span class="subxS1Comment"># . prologue</span> -<span id="L49" class="LineNr"> 49 </span> 55/push-ebp -<span id="L50" class="LineNr"> 50 </span> 89/copy 3/mod/direct 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ebp</span> -<span id="L51" class="LineNr"> 51 </span> <span class="subxS1Comment"># . save registers</span> -<span id="L52" class="LineNr"> 52 </span> 50/push-eax -<span id="L53" class="LineNr"> 53 </span> 51/push-ecx -<span id="L54" class="LineNr"> 54 </span> 52/push-edx -<span id="L55" class="LineNr"> 55 </span> <span class="subxComment"># ecx = n+4</span> -<span id="L56" class="LineNr"> 56 </span> 8b/copy 1/mod/*+disp8 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 1/r32/ecx 0xc/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy *(ebp+12) to ecx</span> -<span id="L57" class="LineNr"> 57 </span> 81 0/subop/add 3/mod/direct 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to ecx</span> -<span id="L58" class="LineNr"> 58 </span> <span class="subxComment"># var eax: (handle _) = allocate(ad, ecx)</span> -<span id="L59" class="LineNr"> 59 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L60" class="LineNr"> 60 </span> 51/push-ecx -<span id="L61" class="LineNr"> 61 </span> ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/disp8 <span class="Normal"> . </span> <span class="subxComment"># push *(ebp+8)</span> -<span id="L62" class="LineNr"> 62 </span> <span class="subxS2Comment"># . . call</span> -<span id="L63" class="LineNr"> 63 </span> e8/call <a href='../069allocate.subx.html#L59'>allocate</a>/disp32 -<span id="L64" class="LineNr"> 64 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L65" class="LineNr"> 65 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> -<span id="L66" class="LineNr"> 66 </span> <span class="subxComment"># edx = out</span> -<span id="L67" class="LineNr"> 67 </span> 8b/copy 1/mod/*+disp8 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 2/r32/edx 0x10/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy *(ebp+16) to edx</span> -<span id="L68" class="LineNr"> 68 </span> <span class="subxComment"># out->address = eax</span> -<span id="L69" class="LineNr"> 69 </span> 89/copy 1/mod/*+disp8 2/rm32/edx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0/r32/eax 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy eax to *(edx+4)</span> -<span id="L70" class="LineNr"> 70 </span> <span class="subxComment"># if (eax == 0) out->alloc_id = 0, return</span> -<span id="L71" class="LineNr"> 71 </span> 3d/compare-eax-and 0/imm32 -<span id="L72" class="LineNr"> 72 </span> 75/jump-if-!= $new:continue/disp8 -<span id="L73" class="LineNr"> 73 </span> c7 0/subop/copy 0/mod/indirect 2/rm32/edx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0/imm32 <span class="subxComment"># copy to *edx</span> -<span id="L74" class="LineNr"> 74 </span> eb/jump $new:end/disp8 -<span id="L75" class="LineNr"> 75 </span><span class="Constant">$new:continue</span>: -<span id="L76" class="LineNr"> 76 </span> <span class="subxComment"># otherwise:</span> -<span id="L77" class="LineNr"> 77 </span> <span class="subxComment"># ecx = *Next-alloc-id</span> -<span id="L78" class="LineNr"> 78 </span> 8b/copy 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> 1/r32/ecx <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 <span class="subxComment"># copy *Next-alloc-id to ecx</span> -<span id="L79" class="LineNr"> 79 </span> <span class="subxComment"># *eax = *Next-alloc-id/ecx</span> -<span id="L80" class="LineNr"> 80 </span> 89/copy 0/mod/indirect 0/rm32/eax <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 1/r32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ecx to *eax</span> -<span id="L81" class="LineNr"> 81 </span> <span class="subxComment"># out->alloc_id = *Next-alloc-id</span> -<span id="L82" class="LineNr"> 82 </span> 89/copy 0/mod/indirect 2/rm32/edx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 1/r32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ecx to *edx</span> -<span id="L83" class="LineNr"> 83 </span> <span class="subxComment"># increment *Next-alloc-id</span> -<span id="L84" class="LineNr"> 84 </span> ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 <span class="subxComment"># increment *Next-alloc-id</span> -<span id="L85" class="LineNr"> 85 </span><span class="Constant">$new:end</span>: -<span id="L86" class="LineNr"> 86 </span> <span class="subxS1Comment"># . restore registers</span> -<span id="L87" class="LineNr"> 87 </span> 5a/pop-to-edx -<span id="L88" class="LineNr"> 88 </span> 59/pop-to-ecx -<span id="L89" class="LineNr"> 89 </span> 58/pop-to-eax -<span id="L90" class="LineNr"> 90 </span> <span class="subxS1Comment"># . epilogue</span> -<span id="L91" class="LineNr"> 91 </span> 89/copy 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 5/r32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ebp to esp</span> -<span id="L92" class="LineNr"> 92 </span> 5d/pop-to-ebp -<span id="L93" class="LineNr"> 93 </span> c3/return -<span id="L94" class="LineNr"> 94 </span> -<span id="L95" class="LineNr"> 95 </span><span class="subxTest">test-new</span>: -<span id="L96" class="LineNr"> 96 </span> <span class="subxS1Comment"># . prologue</span> -<span id="L97" class="LineNr"> 97 </span> 55/push-ebp -<span id="L98" class="LineNr"> 98 </span> 89/copy 3/mod/direct 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ebp</span> -<span id="L99" class="LineNr"> 99 </span> <span class="subxComment"># var heap/edx: allocation-descriptor</span> -<span id="L100" class="LineNr">100 </span> 68/push 0/imm32/limit -<span id="L101" class="LineNr">101 </span> 68/push 0/imm32/curr -<span id="L102" class="LineNr">102 </span> 89/copy 3/mod/direct 2/rm32/edx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to edx</span> -<span id="L103" class="LineNr">103 </span> <span class="subxComment"># heap = new-segment(512)</span> -<span id="L104" class="LineNr">104 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L105" class="LineNr">105 </span> 52/push-edx -<span id="L106" class="LineNr">106 </span> 68/push 0x200/imm32 -<span id="L107" class="LineNr">107 </span> <span class="subxS2Comment"># . . call</span> -<span id="L108" class="LineNr">108 </span> e8/call <a href='../053new-segment.subx.html#L41'>new-segment</a>/disp32 -<span id="L109" class="LineNr">109 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L110" class="LineNr">110 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> -<span id="L111" class="LineNr">111 </span> <span class="subxComment"># *Next-alloc-id = 0x34</span> -<span id="L112" class="LineNr">112 </span> c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 0x34/imm32 <span class="subxComment"># copy to *Next-alloc-id</span> -<span id="L113" class="LineNr">113 </span> <span class="subxComment"># var handle/ecx: handle</span> -<span id="L114" class="LineNr">114 </span> 68/push 0/imm32/address -<span id="L115" class="LineNr">115 </span> 68/push 0/imm32/alloc-id -<span id="L116" class="LineNr">116 </span> 89/copy 3/mod/direct 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ecx</span> -<span id="L117" class="LineNr">117 </span> <span class="subxComment"># new(heap, 2, handle/ecx)</span> -<span id="L118" class="LineNr">118 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L119" class="LineNr">119 </span> 51/push-ecx -<span id="L120" class="LineNr">120 </span> 68/push 2/imm32/size -<span id="L121" class="LineNr">121 </span> 52/push-edx -<span id="L122" class="LineNr">122 </span> <span class="subxS2Comment"># . . call</span> -<span id="L123" class="LineNr">123 </span> e8/call <a href='handle.subx.html#L47'>new</a>/disp32 -<span id="L124" class="LineNr">124 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L125" class="LineNr">125 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L126" class="LineNr">126 </span> <span class="subxComment"># check-ints-equal(handle->alloc_id, 0x34, msg)</span> -<span id="L127" class="LineNr">127 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L128" class="LineNr">128 </span> 68/push <span class="Constant">"F - <a href='handle.subx.html#L95'>test-new</a>: alloc id of handle"</span>/imm32 -<span id="L129" class="LineNr">129 </span> 68/push 0x34/imm32 -<span id="L130" class="LineNr">130 </span> ff 6/subop/push 0/mod/indirect 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># push *ecx</span> -<span id="L131" class="LineNr">131 </span> <span class="subxS2Comment"># . . call</span> -<span id="L132" class="LineNr">132 </span> e8/call <a href='../051test.subx.html#L24'>check-ints-equal</a>/disp32 -<span id="L133" class="LineNr">133 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L134" class="LineNr">134 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L135" class="LineNr">135 </span> <span class="subxComment"># check-ints-equal(*handle->address, 0x34, msg)</span> -<span id="L136" class="LineNr">136 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L137" class="LineNr">137 </span> 68/push <span class="Constant">"F - <a href='handle.subx.html#L95'>test-new</a>: alloc id of payload"</span>/imm32 -<span id="L138" class="LineNr">138 </span> 68/push 0x34/imm32 -<span id="L139" class="LineNr">139 </span> 8b/copy 1/mod/*+disp8 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 2/r32/edx 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy *(ecx+4) to edx</span> -<span id="L140" class="LineNr">140 </span> ff 6/subop/push 0/mod/indirect 2/rm32/edx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># push *edx</span> -<span id="L141" class="LineNr">141 </span> <span class="subxS2Comment"># . . call</span> -<span id="L142" class="LineNr">142 </span> e8/call <a href='../051test.subx.html#L24'>check-ints-equal</a>/disp32 -<span id="L143" class="LineNr">143 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L144" class="LineNr">144 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L145" class="LineNr">145 </span> <span class="subxComment"># check-ints-equal(*Next-alloc-id, 0x35)</span> -<span id="L146" class="LineNr">146 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L147" class="LineNr">147 </span> 68/push <span class="Constant">"F - <a href='handle.subx.html#L95'>test-new</a>: next alloc id"</span>/imm32 -<span id="L148" class="LineNr">148 </span> 68/push 0x35/imm32 -<span id="L149" class="LineNr">149 </span> ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 <span class="subxComment"># copy to *Next-alloc-id</span> -<span id="L150" class="LineNr">150 </span> <span class="subxS2Comment"># . . call</span> -<span id="L151" class="LineNr">151 </span> e8/call <a href='../051test.subx.html#L24'>check-ints-equal</a>/disp32 -<span id="L152" class="LineNr">152 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L153" class="LineNr">153 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L154" class="LineNr">154 </span> <span class="subxComment"># clean up</span> -<span id="L155" class="LineNr">155 </span> <span class="subxS1Comment"># . *Next-alloc-id = 1</span> -<span id="L156" class="LineNr">156 </span> c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 1/imm32 <span class="subxComment"># copy to *Next-alloc-id</span> -<span id="L157" class="LineNr">157 </span> <span class="subxS1Comment"># . epilogue</span> -<span id="L158" class="LineNr">158 </span> 89/copy 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 5/r32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ebp to esp</span> -<span id="L159" class="LineNr">159 </span> 5d/pop-to-ebp -<span id="L160" class="LineNr">160 </span> c3/return -<span id="L161" class="LineNr">161 </span> -<span id="L162" class="LineNr">162 </span><span class="subxMinorFunction">_pending-test-new-failure</span>: -<span id="L163" class="LineNr">163 </span> <span class="subxS1Comment"># . prologue</span> -<span id="L164" class="LineNr">164 </span> 55/push-ebp -<span id="L165" class="LineNr">165 </span> 89/copy 3/mod/direct 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ebp</span> -<span id="L166" class="LineNr">166 </span> <span class="subxS1Comment"># . *Next-alloc-id = 0x34</span> -<span id="L167" class="LineNr">167 </span> c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 0x34/imm32 <span class="subxComment"># copy to *Next-alloc-id</span> -<span id="L168" class="LineNr">168 </span> <span class="subxComment"># define an allocation-descriptor with no space left</span> -<span id="L169" class="LineNr">169 </span> <span class="subxS1Comment"># . var ad/eax: allocation-descriptor = {0x10, 0x10}</span> -<span id="L170" class="LineNr">170 </span> 68/push 0x10/imm32/limit -<span id="L171" class="LineNr">171 </span> 68/push 0x10/imm32/curr -<span id="L172" class="LineNr">172 </span> 89/copy 3/mod/direct 0/rm32/eax <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to eax</span> -<span id="L173" class="LineNr">173 </span> <span class="subxS1Comment"># . var handle/ecx = {random, random}</span> -<span id="L174" class="LineNr">174 </span> 68/push 1234/imm32/address -<span id="L175" class="LineNr">175 </span> 68/push 5678/imm32/alloc-id -<span id="L176" class="LineNr">176 </span> 89/copy 3/mod/direct 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ecx</span> -<span id="L177" class="LineNr">177 </span> <span class="subxComment"># try to allocate</span> -<span id="L178" class="LineNr">178 </span> <span class="subxS1Comment"># . new(ad, 2, handle/ecx)</span> -<span id="L179" class="LineNr">179 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L180" class="LineNr">180 </span> 51/push-ecx -<span id="L181" class="LineNr">181 </span> 68/push 2/imm32/size -<span id="L182" class="LineNr">182 </span> 50/push-eax -<span id="L183" class="LineNr">183 </span> <span class="subxS2Comment"># . . call</span> -<span id="L184" class="LineNr">184 </span> e8/call <a href='handle.subx.html#L47'>new</a>/disp32 -<span id="L185" class="LineNr">185 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L186" class="LineNr">186 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L187" class="LineNr">187 </span> <span class="subxComment"># handle should be cleared</span> -<span id="L188" class="LineNr">188 </span> <span class="subxS1Comment"># . check-ints-equal(handle->alloc_id, 0, msg)</span> -<span id="L189" class="LineNr">189 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L190" class="LineNr">190 </span> 68/push <span class="Constant">"F - test-new-failure: alloc id of handle"</span>/imm32 -<span id="L191" class="LineNr">191 </span> 68/push 0/imm32 -<span id="L192" class="LineNr">192 </span> ff 6/subop/push 0/mod/indirect 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># push *ecx</span> -<span id="L193" class="LineNr">193 </span> <span class="subxS2Comment"># . . call</span> -<span id="L194" class="LineNr">194 </span> e8/call <a href='../051test.subx.html#L24'>check-ints-equal</a>/disp32 -<span id="L195" class="LineNr">195 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L196" class="LineNr">196 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L197" class="LineNr">197 </span> <span class="subxS1Comment"># . check-ints-equal(handle->address, 0, msg)</span> -<span id="L198" class="LineNr">198 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L199" class="LineNr">199 </span> 68/push <span class="Constant">"F - test-new-failure: address of handle"</span>/imm32 -<span id="L200" class="LineNr">200 </span> 68/push 0/imm32 -<span id="L201" class="LineNr">201 </span> ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># push *(ecx+4)</span> -<span id="L202" class="LineNr">202 </span> <span class="subxS2Comment"># . . call</span> -<span id="L203" class="LineNr">203 </span> e8/call <a href='../051test.subx.html#L24'>check-ints-equal</a>/disp32 -<span id="L204" class="LineNr">204 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L205" class="LineNr">205 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L206" class="LineNr">206 </span> <span class="subxComment"># Next-alloc-id should be unmodified</span> -<span id="L207" class="LineNr">207 </span> <span class="subxS1Comment"># . check-ints-equal(*Next-alloc-id, 0x34)</span> -<span id="L208" class="LineNr">208 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L209" class="LineNr">209 </span> 68/push <span class="Constant">"F - test-new-failure: next alloc id"</span>/imm32 -<span id="L210" class="LineNr">210 </span> 68/push 0x34/imm32 -<span id="L211" class="LineNr">211 </span> ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 <span class="subxComment"># copy to *Next-alloc-id</span> -<span id="L212" class="LineNr">212 </span> <span class="subxS2Comment"># . . call</span> -<span id="L213" class="LineNr">213 </span> e8/call <a href='../051test.subx.html#L24'>check-ints-equal</a>/disp32 -<span id="L214" class="LineNr">214 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L215" class="LineNr">215 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L216" class="LineNr">216 </span> <span class="subxComment"># clean up</span> -<span id="L217" class="LineNr">217 </span> <span class="subxS1Comment"># . *Next-alloc-id = 1</span> -<span id="L218" class="LineNr">218 </span> c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 1/imm32 <span class="subxComment"># copy to *Next-alloc-id</span> -<span id="L219" class="LineNr">219 </span> <span class="subxS1Comment"># . epilogue</span> -<span id="L220" class="LineNr">220 </span> 89/copy 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 5/r32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ebp to esp</span> -<span id="L221" class="LineNr">221 </span> 5d/pop-to-ebp -<span id="L222" class="LineNr">222 </span> c3/return -<span id="L223" class="LineNr">223 </span> -<span id="L224" class="LineNr">224 </span><span class="subxFunction">lookup</span>: <span class="subxComment"># h: (handle T) -> eax: (addr T)</span> -<span id="L225" class="LineNr">225 </span> <span class="subxS1Comment"># . prologue</span> -<span id="L226" class="LineNr">226 </span> 55/push-ebp -<span id="L227" class="LineNr">227 </span> 89/copy 3/mod/direct 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ebp</span> -<span id="L228" class="LineNr">228 </span> <span class="subxH1Comment"># - as a proof of concept for future inlining, uses no general-purpose registers besides the output (eax)</span> -<span id="L229" class="LineNr">229 </span> <span class="subxComment"># eax = handle</span> -<span id="L230" class="LineNr">230 </span> 8b/copy 1/mod/*+disp8 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0/r32/eax 8/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy *(ebp+8) to eax</span> -<span id="L231" class="LineNr">231 </span> <span class="subxH1Comment"># - inline {</span> -<span id="L232" class="LineNr">232 </span> <span class="subxComment"># push handle->alloc_id</span> -<span id="L233" class="LineNr">233 </span> ff 6/subop/push 0/mod/indirect 0/rm32/eax <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># push *eax</span> -<span id="L234" class="LineNr">234 </span> <span class="subxComment"># eax = handle->address (payload)</span> -<span id="L235" class="LineNr">235 </span> 8b/copy 1/mod/*+disp8 0/rm32/eax <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># copy *(eax+4) to eax</span> -<span id="L236" class="LineNr">236 </span> <span class="subxComment"># push handle->address</span> -<span id="L237" class="LineNr">237 </span> 50/push-eax -<span id="L238" class="LineNr">238 </span> <span class="subxComment"># eax = payload->alloc_id</span> -<span id="L239" class="LineNr">239 </span> 8b/copy 0/mod/indirect 0/rm32/eax <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy *eax to eax</span> -<span id="L240" class="LineNr">240 </span> <span class="subxComment"># if (eax != handle->alloc_id) abort</span> -<span id="L241" class="LineNr">241 </span> 39/compare 1/mod/*+disp8 4/rm32/sib 4/base/esp 4/index/none <span class="Normal"> . </span> 0/r32/eax 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># compare *(esp+4) and eax</span> -<span id="L242" class="LineNr">242 </span> 75/jump-if-!= $lookup:abort/disp8 -<span id="L243" class="LineNr">243 </span> <span class="subxComment"># eax = pop handle->address</span> -<span id="L244" class="LineNr">244 </span> 58/pop-to-eax -<span id="L245" class="LineNr">245 </span> <span class="subxComment"># discard handle->alloc_id</span> -<span id="L246" class="LineNr">246 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> -<span id="L247" class="LineNr">247 </span> <span class="subxComment"># add 4</span> -<span id="L248" class="LineNr">248 </span> 05/add-to-eax 4/imm32 -<span id="L249" class="LineNr">249 </span> <span class="subxH1Comment"># - }</span> -<span id="L250" class="LineNr">250 </span> <span class="subxH1Comment"># - alternative consuming a second register {</span> -<span id="L251" class="LineNr">251 </span><span class="CommentedCode">#? # ecx = handle->alloc_id</span> -<span id="L252" class="LineNr">252 </span><span class="CommentedCode">#? 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx</span> -<span id="L253" class="LineNr">253 </span><span class="CommentedCode">#? # eax = handle->address (payload)</span> -<span id="L254" class="LineNr">254 </span><span class="CommentedCode">#? 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax</span> -<span id="L255" class="LineNr">255 </span><span class="CommentedCode">#? # if (ecx != *eax) abort</span> -<span id="L256" class="LineNr">256 </span><span class="CommentedCode">#? 39/compare 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # compare *eax and ecx</span> -<span id="L257" class="LineNr">257 </span><span class="CommentedCode">#? 75/jump-if-!= $lookup:abort/disp8</span> -<span id="L258" class="LineNr">258 </span><span class="CommentedCode">#? # add 4 to eax</span> -<span id="L259" class="LineNr">259 </span><span class="CommentedCode">#? 05/add-to-eax 4/imm32</span> -<span id="L260" class="LineNr">260 </span> <span class="subxH1Comment"># - }</span> -<span id="L261" class="LineNr">261 </span> <span class="subxS1Comment"># . epilogue</span> -<span id="L262" class="LineNr">262 </span> 89/copy 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 5/r32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ebp to esp</span> -<span id="L263" class="LineNr">263 </span> 5d/pop-to-ebp -<span id="L264" class="LineNr">264 </span> c3/return -<span id="L265" class="LineNr">265 </span> -<span id="L266" class="LineNr">266 </span><span class="Constant">$lookup:abort</span>: -<span id="L267" class="LineNr">267 </span> <span class="subxS1Comment"># . _write(2/stderr, msg)</span> -<span id="L268" class="LineNr">268 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L269" class="LineNr">269 </span> 68/push <span class="Constant">"lookup failed\n"</span>/imm32 -<span id="L270" class="LineNr">270 </span> 68/push 2/imm32/stderr -<span id="L271" class="LineNr">271 </span> <span class="subxS2Comment"># . . call</span> -<span id="L272" class="LineNr">272 </span> e8/call <a href='../050_write.subx.html#L14'>_write</a>/disp32 -<span id="L273" class="LineNr">273 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L274" class="LineNr">274 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> -<span id="L275" class="LineNr">275 </span> <span class="subxS1Comment"># . syscall(exit, 1)</span> -<span id="L276" class="LineNr">276 </span> bb/copy-to-ebx 1/imm32/exit-status -<span id="L277" class="LineNr">277 </span> b8/copy-to-eax 1/imm32/exit -<span id="L278" class="LineNr">278 </span> cd/syscall 0x80/imm8 -<span id="L279" class="LineNr">279 </span> -<span id="L280" class="LineNr">280 </span><span class="subxTest">test-lookup-success</span>: -<span id="L281" class="LineNr">281 </span> <span class="subxS1Comment"># . prologue</span> -<span id="L282" class="LineNr">282 </span> 55/push-ebp -<span id="L283" class="LineNr">283 </span> 89/copy 3/mod/direct 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ebp</span> -<span id="L284" class="LineNr">284 </span> <span class="subxS1Comment"># . save registers</span> -<span id="L285" class="LineNr">285 </span> <span class="subxComment"># var heap/ebx: allocation-descriptor</span> -<span id="L286" class="LineNr">286 </span> 68/push 0/imm32/limit -<span id="L287" class="LineNr">287 </span> 68/push 0/imm32/curr -<span id="L288" class="LineNr">288 </span> 89/copy 3/mod/direct 3/rm32/ebx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ebx</span> -<span id="L289" class="LineNr">289 </span> <span class="subxComment"># heap = new-segment(512)</span> -<span id="L290" class="LineNr">290 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L291" class="LineNr">291 </span> 53/push-ebx -<span id="L292" class="LineNr">292 </span> 68/push 0x200/imm32 -<span id="L293" class="LineNr">293 </span> <span class="subxS2Comment"># . . call</span> -<span id="L294" class="LineNr">294 </span> e8/call <a href='../053new-segment.subx.html#L41'>new-segment</a>/disp32 -<span id="L295" class="LineNr">295 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L296" class="LineNr">296 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> -<span id="L297" class="LineNr">297 </span> <span class="subxComment"># var handle/ecx: handle</span> -<span id="L298" class="LineNr">298 </span> 68/push 0/imm32/address -<span id="L299" class="LineNr">299 </span> 68/push 0/imm32/alloc-id -<span id="L300" class="LineNr">300 </span> 89/copy 3/mod/direct 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ecx</span> -<span id="L301" class="LineNr">301 </span> <span class="subxComment"># var old_top/edx = heap->curr</span> -<span id="L302" class="LineNr">302 </span> 8b/copy 0/mod/indirect 3/rm32/ebx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 2/r32/edx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy *ebx to edx</span> -<span id="L303" class="LineNr">303 </span> <span class="subxComment"># new(heap, 2, handle)</span> -<span id="L304" class="LineNr">304 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L305" class="LineNr">305 </span> 51/push-ecx -<span id="L306" class="LineNr">306 </span> 68/push 2/imm32/size -<span id="L307" class="LineNr">307 </span> 53/push-ebx -<span id="L308" class="LineNr">308 </span> <span class="subxS2Comment"># . . call</span> -<span id="L309" class="LineNr">309 </span> e8/call <a href='handle.subx.html#L47'>new</a>/disp32 -<span id="L310" class="LineNr">310 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L311" class="LineNr">311 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L312" class="LineNr">312 </span> <span class="subxComment"># eax = lookup(handle)</span> -<span id="L313" class="LineNr">313 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L314" class="LineNr">314 </span> 51/push-ecx -<span id="L315" class="LineNr">315 </span> <span class="subxS2Comment"># . . call</span> -<span id="L316" class="LineNr">316 </span> e8/call <a href='handle.subx.html#L224'>lookup</a>/disp32 -<span id="L317" class="LineNr">317 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L318" class="LineNr">318 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> -<span id="L319" class="LineNr">319 </span> <span class="subxComment"># eax contains old top of heap, except skipping the alloc id in the payload</span> -<span id="L320" class="LineNr">320 </span> <span class="subxS1Comment"># . check-ints-equal(eax, old_top+4, msg)</span> -<span id="L321" class="LineNr">321 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L322" class="LineNr">322 </span> 68/push <span class="Constant">"F - test-lookup-success"</span>/imm32 -<span id="L323" class="LineNr">323 </span> 81 0/subop/add 3/mod/direct 2/rm32/edx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to edx</span> -<span id="L324" class="LineNr">324 </span> 52/push-edx -<span id="L325" class="LineNr">325 </span> 50/push-eax -<span id="L326" class="LineNr">326 </span> <span class="subxS2Comment"># . . call</span> -<span id="L327" class="LineNr">327 </span> e8/call <a href='../051test.subx.html#L24'>check-ints-equal</a>/disp32 -<span id="L328" class="LineNr">328 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L329" class="LineNr">329 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L330" class="LineNr">330 </span> <span class="subxComment"># clean up</span> -<span id="L331" class="LineNr">331 </span> <span class="subxS1Comment"># . *Next-alloc-id = 1</span> -<span id="L332" class="LineNr">332 </span> c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 1/imm32 <span class="subxComment"># copy to *Next-alloc-id</span> -<span id="L333" class="LineNr">333 </span> <span class="subxComment"># write(2/stderr, "lookup succeeded\n")</span> -<span id="L334" class="LineNr">334 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L335" class="LineNr">335 </span> 68/push <span class="Constant">"lookup succeeded\n"</span>/imm32 -<span id="L336" class="LineNr">336 </span> 68/push 2/imm32/stderr -<span id="L337" class="LineNr">337 </span> <span class="subxS2Comment"># . . call</span> -<span id="L338" class="LineNr">338 </span> e8/call <a href='../057write.subx.html#L24'>write</a>/disp32 -<span id="L339" class="LineNr">339 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L340" class="LineNr">340 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> -<span id="L341" class="LineNr">341 </span> <span class="subxS1Comment"># . restore registers</span> -<span id="L342" class="LineNr">342 </span> 5a/pop-to-edx -<span id="L343" class="LineNr">343 </span> 59/pop-to-ecx -<span id="L344" class="LineNr">344 </span> <span class="subxS1Comment"># . epilogue</span> -<span id="L345" class="LineNr">345 </span> 89/copy 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 5/r32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ebp to esp</span> -<span id="L346" class="LineNr">346 </span> 5d/pop-to-ebp -<span id="L347" class="LineNr">347 </span> c3/return -<span id="L348" class="LineNr">348 </span> -<span id="L349" class="LineNr">349 </span><span class="subxTest">test-lookup-failure</span>: -<span id="L350" class="LineNr">350 </span> <span class="subxS1Comment"># . prologue</span> -<span id="L351" class="LineNr">351 </span> 55/push-ebp -<span id="L352" class="LineNr">352 </span> 89/copy 3/mod/direct 5/rm32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ebp</span> -<span id="L353" class="LineNr">353 </span> <span class="subxComment"># var heap/esi: allocation-descriptor</span> -<span id="L354" class="LineNr">354 </span> 68/push 0/imm32/limit -<span id="L355" class="LineNr">355 </span> 68/push 0/imm32/curr -<span id="L356" class="LineNr">356 </span> 89/copy 3/mod/direct 6/rm32/esi <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to esi</span> -<span id="L357" class="LineNr">357 </span> <span class="subxComment"># heap = new-segment(512)</span> -<span id="L358" class="LineNr">358 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L359" class="LineNr">359 </span> 56/push-esi -<span id="L360" class="LineNr">360 </span> 68/push 0x200/imm32 -<span id="L361" class="LineNr">361 </span> <span class="subxS2Comment"># . . call</span> -<span id="L362" class="LineNr">362 </span> e8/call <a href='../053new-segment.subx.html#L41'>new-segment</a>/disp32 -<span id="L363" class="LineNr">363 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L364" class="LineNr">364 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 8/imm32 <span class="subxComment"># add to esp</span> -<span id="L365" class="LineNr">365 </span> <span class="subxComment"># var h1/ecx: handle</span> -<span id="L366" class="LineNr">366 </span> 68/push 0/imm32/address -<span id="L367" class="LineNr">367 </span> 68/push 0/imm32/alloc-id -<span id="L368" class="LineNr">368 </span> 89/copy 3/mod/direct 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to ecx</span> -<span id="L369" class="LineNr">369 </span> <span class="subxComment"># var old_top/ebx = heap->curr</span> -<span id="L370" class="LineNr">370 </span> 8b/copy 0/mod/indirect 6/rm32/esi <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 3/r32/ebx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy *esi to ebx</span> -<span id="L371" class="LineNr">371 </span> <span class="subxComment"># first allocation, to h1</span> -<span id="L372" class="LineNr">372 </span> <span class="subxS1Comment"># . new(heap, 2, h1)</span> -<span id="L373" class="LineNr">373 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L374" class="LineNr">374 </span> 51/push-ecx -<span id="L375" class="LineNr">375 </span> 68/push 2/imm32/size -<span id="L376" class="LineNr">376 </span> 56/push-esi -<span id="L377" class="LineNr">377 </span> <span class="subxS2Comment"># . . call</span> -<span id="L378" class="LineNr">378 </span> e8/call <a href='handle.subx.html#L47'>new</a>/disp32 -<span id="L379" class="LineNr">379 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L380" class="LineNr">380 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L381" class="LineNr">381 </span> <span class="subxComment"># reset heap->curr to mimic reclamation</span> -<span id="L382" class="LineNr">382 </span> 89/copy 0/mod/indirect 6/rm32/esi <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 3/r32/ebx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ebx to *esi</span> -<span id="L383" class="LineNr">383 </span> <span class="subxComment"># second allocation that returns the same address as the first</span> -<span id="L384" class="LineNr">384 </span> <span class="subxComment"># var h2/edx: handle</span> -<span id="L385" class="LineNr">385 </span> 68/push 0/imm32/address -<span id="L386" class="LineNr">386 </span> 68/push 0/imm32/alloc-id -<span id="L387" class="LineNr">387 </span> 89/copy 3/mod/direct 2/rm32/edx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/r32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy esp to edx</span> -<span id="L388" class="LineNr">388 </span> <span class="subxS1Comment"># . new(heap, 2, h2)</span> -<span id="L389" class="LineNr">389 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L390" class="LineNr">390 </span> 52/push-edx -<span id="L391" class="LineNr">391 </span> 68/push 2/imm32/size -<span id="L392" class="LineNr">392 </span> 56/push-esi -<span id="L393" class="LineNr">393 </span> <span class="subxS2Comment"># . . call</span> -<span id="L394" class="LineNr">394 </span> e8/call <a href='handle.subx.html#L47'>new</a>/disp32 -<span id="L395" class="LineNr">395 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L396" class="LineNr">396 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L397" class="LineNr">397 </span> <span class="subxComment"># check-ints-equal(h1->address, h2->address, msg)</span> -<span id="L398" class="LineNr">398 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L399" class="LineNr">399 </span> 68/push <span class="Constant">"F - test-lookup-failure"</span>/imm32 -<span id="L400" class="LineNr">400 </span> ff 6/subop/push 1/mod/*+disp8 2/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># push *(edx+4)</span> -<span id="L401" class="LineNr">401 </span> ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/disp8 <span class="Normal"> . </span> <span class="subxComment"># push *(ecx+4)</span> -<span id="L402" class="LineNr">402 </span> <span class="subxS2Comment"># . . call</span> -<span id="L403" class="LineNr">403 </span> e8/call <a href='../051test.subx.html#L24'>check-ints-equal</a>/disp32 -<span id="L404" class="LineNr">404 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L405" class="LineNr">405 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 0xc/imm32 <span class="subxComment"># add to esp</span> -<span id="L406" class="LineNr">406 </span> <span class="subxComment"># lookup(h1) should crash</span> -<span id="L407" class="LineNr">407 </span> <span class="subxS2Comment"># . . push args</span> -<span id="L408" class="LineNr">408 </span> 51/push-ecx -<span id="L409" class="LineNr">409 </span> <span class="subxS2Comment"># . . call</span> -<span id="L410" class="LineNr">410 </span> e8/call <a href='handle.subx.html#L224'>lookup</a>/disp32 -<span id="L411" class="LineNr">411 </span> <span class="subxComment"># should never get past this point</span> -<span id="L412" class="LineNr">412 </span> <span class="subxS2Comment"># . . discard args</span> -<span id="L413" class="LineNr">413 </span> 81 0/subop/add 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 4/imm32 <span class="subxComment"># add to esp</span> -<span id="L414" class="LineNr">414 </span> <span class="subxComment"># clean up</span> -<span id="L415" class="LineNr">415 </span> <span class="subxS1Comment"># . *Next-alloc-id = 1</span> -<span id="L416" class="LineNr">416 </span> c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="SpecialChar"><a href='handle.subx.html#L425'>Next-alloc-id</a></span>/disp32 1/imm32 <span class="subxComment"># copy to *Next-alloc-id</span> -<span id="L417" class="LineNr">417 </span> <span class="subxS1Comment"># . epilogue</span> -<span id="L418" class="LineNr">418 </span> 89/copy 3/mod/direct 4/rm32/esp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="Normal"> . </span> 5/r32/ebp <span class="Normal"> . </span> <span class="Normal"> . </span> <span class="subxComment"># copy ebp to esp</span> -<span id="L419" class="LineNr">419 </span> 5d/pop-to-ebp -<span id="L420" class="LineNr">420 </span> c3/return -<span id="L421" class="LineNr">421 </span> -<span id="L422" class="LineNr">422 </span>== data -<span id="L423" class="LineNr">423 </span> -<span id="L424" class="LineNr">424 </span><span class="subxComment"># Monotonically increasing counter for calls to 'new'</span> -<span id="L425" class="LineNr">425 </span><span class="SpecialChar">Next-alloc-id</span>: <span class="subxComment"># int</span> -<span id="L426" class="LineNr">426 </span> 1/imm32 -<span id="L427" class="LineNr">427 </span> -<span id="L428" class="LineNr">428 </span><span class="subxS2Comment"># . . vim:nowrap:textwidth=0</span> -</pre> -</body> -</html> -<!-- vim: set foldmethod=manual : --> diff --git a/stats.txt b/stats.txt index 9a53dea9..6abac27d 100644 --- a/stats.txt +++ b/stats.txt @@ -3,7 +3,6 @@ apps/factorial.subx 120 44 apps/crenshaw2-1.subx 561 180 apps/crenshaw2-1b.subx 757 186 -apps/handle.subx 428 44 apps/hex.subx 1442 149 apps/survey.subx 4733 905 apps/pack.subx 5881 840 @@ -20,7 +19,6 @@ apps/mu.subx (incomplete) 11592 4165 apps/factorial.subx 8436 1700 apps/crenshaw2-1.subx 8644 1925 apps/crenshaw2-1b.subx 8736 1931 -apps/handle.subx 8601 1638 apps/hex.subx 9065 1908 apps/survey.subx 10217 3248 apps/pack.subx 10589 2727 @@ -37,7 +35,6 @@ apps/mu.subx (incomplete) 16250 6524 apps/crenshaw2-1 41 4.3 apps/crenshaw2-1b 42 5.2 apps/factorial 42 5.2 -apps/handle 42 4.2 apps/hex 45 5.0 apps/survey 51 9.6 apps/pack 54 7.6 diff --git a/test_apps b/test_apps index 83073191..06b658b3 100755 --- a/test_apps +++ b/test_apps @@ -221,20 +221,6 @@ test $NATIVE && { echo } -echo handle -./bootstrap translate init.$OS 0[0-8]*.subx apps/handle.subx -o apps/handle -test "$1" = 'record' || git diff --exit-code apps/handle -test $EMULATED && { - ./bootstrap run apps/handle > handle.out 2>&1 || true - grep -q 'lookup succeeded' handle.out || { echo "missing success test"; exit 1; } - grep -q 'lookup failed' handle.out || { echo "missing failure test"; exit 1; } -} -test $NATIVE && { - apps/handle > handle.out 2>&1 || true - grep -q 'lookup succeeded' handle.out || { echo "missing success test"; exit 1; } - grep -q 'lookup failed' handle.out || { echo "missing failure test"; exit 1; } -} - # Phases of the self-hosted SubX translator. for phase in hex survey pack assort dquotes tests @@ -324,7 +310,7 @@ done # Larger apps that use the standard library. -for app in factorial crenshaw2-1 crenshaw2-1b handle +for app in factorial crenshaw2-1 crenshaw2-1b do echo $app ./translate_subx init.$OS 0[0-8]*.subx apps/$app.subx |