diff options
author | Kartik Agaram <vc@akkartik.com> | 2021-01-15 20:51:02 -0800 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2021-01-15 21:11:30 -0800 |
commit | 8ed27ce4319eb843ee021ca0b1cb46d275c2f89d (patch) | |
tree | 67439343bb4be931cd712120aafe69b8023892ed /baremetal | |
parent | 6e36ce06dd035408d43a6599b75b933a0709cc78 (diff) | |
download | mu-8ed27ce4319eb843ee021ca0b1cb46d275c2f89d.tar.gz |
7522 - bring back a few tests in .subx files
Even though baremetal has tests in SubX, they can only run in Mu programs since the test harness is currently in a Mu layer. Baremetal isn't really intended for running SubX programs at the moment. Is this a step down the slippery slope towards C compilers that I complained about in http://akkartik.name/akkartik-convivial-20200607.pdf?
Diffstat (limited to 'baremetal')
-rw-r--r-- | baremetal/108write.subx | 92 | ||||
-rw-r--r-- | baremetal/109stream-equal.subx | 595 | ||||
-rw-r--r-- | baremetal/112read-byte.subx | 2 | ||||
-rw-r--r-- | baremetal/115write-byte.subx | 30 | ||||
-rw-r--r-- | baremetal/120allocate.subx | 30 |
5 files changed, 744 insertions, 5 deletions
diff --git a/baremetal/108write.subx b/baremetal/108write.subx index 91a5e680..4f3b0b7f 100644 --- a/baremetal/108write.subx +++ b/baremetal/108write.subx @@ -1,3 +1,10 @@ +# write: write to in-memory streams +# +# A stream looks like this: +# read: int # index at which to read next +# write: int # index at which writes go +# data: (array byte) # prefixed by size as usual + == code # instruction effective address register displacement immediate # . op subop mod rm32 base index scale r32 @@ -10,8 +17,6 @@ write: # f: (addr stream byte), s: (addr array byte) # if (s == 0) return 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 0/imm32 # compare *(ebp+12) 74/jump-if-= $write:end/disp8 - # TODO: write to file - # otherwise, treat 'f' as a stream to append to # . save registers 50/push-eax 51/push-ecx @@ -49,7 +54,88 @@ $write:end: 5d/pop-to-ebp c3/return -# TODO: bring in tests once we have check-ints-equal +test-write-single: + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "Ab") + # . . push args + 68/push "Ab"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(*_test-stream->data, 41/A 62/b 00 00, msg) + # . . push args + 68/push "F - test-write-single"/imm32 + 68/push 0x006241/imm32/Ab + # . . push *_test-stream->data + b8/copy-to-eax _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 . # push *(eax+12) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # end + c3/return + +test-write-appends: + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "C") + # . . push args + 68/push "C"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # write(_test-stream, "D") + # . . push args + 68/push "D"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(*_test-stream->data, 43/C 44/D 00 00, msg) + # . . push args + 68/push "F - test-write-appends"/imm32 + 68/push 0x00004443/imm32/C-D + # . . push *_test-stream->data + b8/copy-to-eax _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 . # push *(eax+12) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # end + c3/return + +== data + +_test-stream: # (stream byte) + # current write index + 0/imm32 + # current read index + 0/imm32 + # size + 0x10/imm32 + # data (2 lines x 8 bytes/line) + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + +== code # 3-argument variant of _append _append-3: # out: (addr byte), outend: (addr byte), s: (addr array byte) -> num_bytes_appended/eax diff --git a/baremetal/109stream-equal.subx b/baremetal/109stream-equal.subx new file mode 100644 index 00000000..8f6cf1bf --- /dev/null +++ b/baremetal/109stream-equal.subx @@ -0,0 +1,595 @@ +# some primitives for checking stream contents + +== 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 + +# compare all the data in a stream (ignoring the read pointer) +stream-data-equal?: # f: (addr stream byte), s: (addr array byte) -> result/eax: boolean + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 51/push-ecx + 52/push-edx + 56/push-esi + 57/push-edi + # esi = f + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi + # eax = f->write + 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax + # var maxf/edx: (addr byte) = &f->data[f->write] + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 2/r32/edx 0xc/disp8 . # copy esi+eax+12 to edx + # var currf/esi: (addr byte) = f->data + 81 0/subop/add 3/mod/direct 6/rm32/esi . . . . . 0xc/imm32 # add to esi + # edi = s + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi +$stream-data-equal?:compare-sizes: + # if (f->write != s->size) return false + 39/compare 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # compare *edi and eax + 75/jump-if-!= $stream-data-equal?:false/disp8 + # var currs/edi: (addr byte) = s->data + 81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi + # var eax: byte = 0 + 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + # var ecx: byte = 0 + 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx +$stream-data-equal?:loop: + # if (currf >= maxf) return true + 39/compare 3/mod/direct 6/rm32/esi . . . 2/r32/edx . . # compare esi with edx + 73/jump-if-addr>= $stream-data-equal?:true/disp8 + # AL = *currs + 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL + # CL = *curr + 8a/copy-byte 0/mod/indirect 7/rm32/edi . . . 1/r32/CL . . # copy byte at *edi to CL + # if (eax != ecx) return false + 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax and ecx + 75/jump-if-!= $stream-data-equal?:false/disp8 + # ++f + 46/increment-esi + # ++curr + 47/increment-edi + eb/jump $stream-data-equal?:loop/disp8 +$stream-data-equal?:false: + b8/copy-to-eax 0/imm32 + eb/jump $stream-data-equal?:end/disp8 +$stream-data-equal?:true: + b8/copy-to-eax 1/imm32 +$stream-data-equal?:end: + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 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-stream-data-equal: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "Abc") + # . . push args + 68/push "Abc"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = stream-data-equal?(_test-stream, "Abc") + # . . push args + 68/push "Abc"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call stream-data-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-stream-data-equal"/imm32 + 68/push 1/imm32 + 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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-stream-data-equal-2: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "Abc") + # . . push args + 68/push "Abc"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = stream-data-equal?(_test-stream, "Abd") + # . . push args + 68/push "Abd"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call stream-data-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-stream-data-equal-2"/imm32 + 68/push 0/imm32 + 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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-stream-data-equal-size-check: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "Abc") + # . . push args + 68/push "Abc"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = stream-data-equal?(_test-stream, "Abcd") + # . . push args + 68/push "Abcd"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call stream-data-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-stream-data-equal-size-check"/imm32 + 68/push 0/imm32 + 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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +# helper for later tests +check-stream-equal: # f: (addr stream byte), s: (addr array byte), msg: (addr array byte) + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 50/push-eax + # eax = stream-data-equal?(f, s) + # . . push args + 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 . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call stream-data-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) + 68/push 1/imm32 + 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-stream-equal:end: + # . restore registers + 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 + +# scan the next line until newline starting from f->read and compare it with +# 's' (ignoring the trailing newline) +# on success, set f->read to after the next newline +# on failure, leave f->read unmodified +# this function is usually used only in tests, so we repeatedly write f->read +next-stream-line-equal?: # f: (addr stream byte), s: (addr array byte) -> result/eax: boolean + # pseudocode: + # currf = f->read # bound: f->write + # currs = 0 # bound: s->size + # while true + # if currf >= f->write + # return currs >= s->size + # if f[currf] == '\n' + # ++currf + # return currs >= s->size + # if (currs >= s->size) return false # the current line of f still has data to match + # if (f[currf] != s[currs]) return false + # ++currf + # ++currs + # + # collapsing the two branches that can return true: + # currf = f->read # bound: f->write + # currs = 0 # bound: s->size + # while true + # if (currf >= f->write) break + # if (f[currf] == '\n') break + # if (currs >= s->size) return false # the current line of f still has data to match + # if (f[currf] != s[currs]) return false + # ++currf + # ++currs + # ++currf # skip '\n' + # return currs >= s->size + # Here the final `++currf` is sometimes unnecessary (if we're already at the end of the stream) + # + # registers: + # f: esi + # s: edi + # currf: ecx + # currs: edx + # f[currf]: eax + # s[currs]: ebx + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 51/push-ecx + 52/push-edx + 56/push-esi + 57/push-edi + # esi = f + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi + # var currf/ecx: int = f->read + 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx + # edi = s + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi + # var currs/edx: int = 0 + 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx + # var c1/eax: byte = 0 + 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + # var c2/ebx: byte = 0 + 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx +$next-stream-line-equal?:loop: + # if (currf >= f->write) break + 3b/compare 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # compare ecx with *esi + 7d/jump-if->= $next-stream-line-equal?:break/disp8 + # c1 = f->data[f->read] + 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL + # if (c1 == '\n') break + 3d/compare-eax-and 0xa/imm32/newline + 74/jump-if-= $next-stream-line-equal?:break/disp8 + # if (currs >= s->size) return false + 3b/compare 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # compare edx with *edi + 7d/jump-if->= $next-stream-line-equal?:false/disp8 + # c2 = s->data[currs] + 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 2/index/edx . 3/r32/BL 4/disp8 . # copy byte at *(edi+edx+4) to BL + # if (c1 != c2) return false + 39/compare 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # compare eax and ebx + 75/jump-if-!= $next-stream-line-equal?:false/disp8 + # ++currf + 41/increment-ecx + # ++currs + 42/increment-edx + eb/jump $next-stream-line-equal?:loop/disp8 +$next-stream-line-equal?:break: + # ++currf + 41/increment-ecx + # if (currs >= s->size) return true + 3b/compare 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # compare edx with *edi + 7c/jump-if-< $next-stream-line-equal?:false/disp8 +$next-stream-line-equal?:true: + b8/copy-to-eax 1/imm32 + # persist f->read on success + 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4) + eb/jump $next-stream-line-equal?:end/disp8 +$next-stream-line-equal?:false: + b8/copy-to-eax 0/imm32 +$next-stream-line-equal?:end: + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 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-next-stream-line-equal-stops-at-newline: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "Abc\ndef") + # . . push args + 68/push "Abc\ndef"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = next-stream-line-equal?(_test-stream, "Abc") + # . . push args + 68/push "Abc"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-next-stream-line-equal-stops-at-newline"/imm32 + 68/push 1/imm32 + 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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-next-stream-line-equal-stops-at-newline-2: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "Abc\ndef") + # . . push args + 68/push "Abc\ndef"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = next-stream-line-equal?(_test-stream, "def") + # . . push args + 68/push "def"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-next-stream-line-equal-stops-at-newline-2"/imm32 + 68/push 0/imm32 + 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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-next-stream-line-equal-skips-newline: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "Abc\ndef\n") + # . . push args + 68/push "Abc\ndef\n"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # next-stream-line-equal?(_test-stream, "Abc") + # . . push args + 68/push "Abc"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = next-stream-line-equal?(_test-stream, "def") + # . . push args + 68/push "def"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-next-stream-line-equal-skips-newline"/imm32 + 68/push 1/imm32 + 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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-next-stream-line-equal-handles-final-line: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write(_test-stream, "Abc\ndef") + # . . push args + 68/push "Abc\ndef"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # next-stream-line-equal?(_test-stream, "Abc") + # . . push args + 68/push "Abc"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = next-stream-line-equal?(_test-stream, "def") + # . . push args + 68/push "def"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-next-stream-line-equal-skips-newline"/imm32 + 68/push 1/imm32 + 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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-next-stream-line-equal-always-fails-after-Eof: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write nothing + # eax = next-stream-line-equal?(_test-stream, "") + # . . push args + 68/push ""/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-next-stream-line-equal-always-fails-after-Eof"/imm32 + 68/push 1/imm32 + 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 + # eax = next-stream-line-equal?(_test-stream, "") + # . . push args + 68/push ""/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-next-stream-line-equal-always-fails-after-Eof/2"/imm32 + 68/push 1/imm32 + 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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +# helper for later tests +check-next-stream-line-equal: # f: (addr stream byte), s: (addr array byte), msg: (addr array byte) + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 50/push-eax + # eax = next-stream-line-equal?(f, s) + # . . push args + 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 . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call next-stream-line-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) + 68/push 1/imm32 + 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 + # . restore registers + 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 + +# . . vim:nowrap:textwidth=0 diff --git a/baremetal/112read-byte.subx b/baremetal/112read-byte.subx index e6a54fdd..f86498bb 100644 --- a/baremetal/112read-byte.subx +++ b/baremetal/112read-byte.subx @@ -3,8 +3,6 @@ # . 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 -# TODO: read-byte-buffered - # Return next byte value in eax, with top 3 bytes cleared. # Abort on reaching end of stream. read-byte: # s: (addr stream byte) -> result/eax: byte diff --git a/baremetal/115write-byte.subx b/baremetal/115write-byte.subx index d69663bc..af32f610 100644 --- a/baremetal/115write-byte.subx +++ b/baremetal/115write-byte.subx @@ -35,4 +35,34 @@ $append-byte:end: 5d/pop-to-ebp c3/return +test-append-byte-single: + # - check that append-byte writes to first byte of 'file' + # setup + # . clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # append-byte(_test-stream, 'A') + # . . push args + 68/push 0x41/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call append-byte/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-stream-equal(_test-stream, "A", msg) + # . . push args + 68/push "F - test-append-byte-single"/imm32 + 68/push "A"/imm32 + 68/push _test-stream/imm32 + # . . call + e8/call check-stream-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . end + c3/return + # . . vim:nowrap:textwidth=0 diff --git a/baremetal/120allocate.subx b/baremetal/120allocate.subx index 2aaa8e75..95356e7f 100644 --- a/baremetal/120allocate.subx +++ b/baremetal/120allocate.subx @@ -50,4 +50,34 @@ $zero-out:end: 5d/pop-to-ebp c3/return +test-zero-out: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # region/ecx = 34, 35, 36, 37 + 68/push 0x37363534/imm32 + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # zero-out(ecx, 3) + # . . push args + 68/push 3/imm32/size + 51/push-ecx + # . . call + e8/call zero-out/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # first 3 bytes cleared, fourth left alone + # . check-ints-equal(*ecx, 0x37000000, msg) + # . . push args + 68/push "F - test-zero-out"/imm32 + 68/push 0x37000000/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 + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + # . . vim:nowrap:textwidth=0 |