diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-12-04 21:57:51 -0800 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-12-04 23:02:53 -0800 |
commit | 18d5bab2b66406ee1e329ef099b375d98f0c2dd8 (patch) | |
tree | 00c29a0b83fc049a9362bd5cb1337926257329e1 /127next-word.subx | |
parent | 8a8db34f259f12b06f7b87e4f4c1b5530425ff29 (diff) | |
download | mu-18d5bab2b66406ee1e329ef099b375d98f0c2dd8.tar.gz |
7329 - snapshot: advent day 4 part 2
I've found two bugs in SubX libraries: 1. next-word had an out-of-bounds read 2. next-word was skipping comments, because that's what I need during bootstrapping. I've created a new variant called next-raw-word that doesn't skip comments. These really need better names. We're now at the point where 4b.mu has the right structure and returns identical result to 4a.mu.
Diffstat (limited to '127next-word.subx')
-rw-r--r-- | 127next-word.subx | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/127next-word.subx b/127next-word.subx index 6705437f..5af326d4 100644 --- a/127next-word.subx +++ b/127next-word.subx @@ -5,7 +5,8 @@ # . 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 -# (re)compute the bounds of the next word in the line +# (re)compute the bounds of the next word in the line (surrounded by whitespace, +# treating '#' comments as a single word) # return empty string on reaching end of file next-word: # line: (addr stream byte), out: (addr slice) # . prologue @@ -56,6 +57,7 @@ $next-word:comment: 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy esi+eax+12 to eax 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) # . line->read = line->write + 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax 89/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy eax to *(esi+4) # . return eb/jump $next-word:end/disp8 @@ -298,3 +300,63 @@ test-next-word-returns-empty-string-on-newline: 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return + +# (re)compute the bounds of the next word in the line (separated by whitespace) +# return empty string on reaching end of file +next-raw-word: # line: (addr stream byte), out: (addr slice) + # . 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 + 56/push-esi + 57/push-edi + # esi = line + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi + # edi = out + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi + # skip-chars-matching-whitespace(line) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call skip-chars-matching-whitespace/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +$next-raw-word:check0: + # if (line->read >= line->write) clear out and return + # . eax = line->read + 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) to eax + # . if (eax < line->write) goto next check + 3b/compare 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # compare eax with *esi + 7c/jump-if-< $next-raw-word:word-exists/disp8 + # . return out + c7 0/subop/copy 0/mod/direct 7/rm32/edi . . . . . 0/imm32 # copy to *edi + c7 0/subop/copy 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 0/imm32 # copy to *(edi+4) + eb/jump $next-raw-word:end/disp8 +$next-raw-word:word-exists: + # out->start = &line->data[line->read] + 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 0xc/disp8 . # copy esi+ecx+12 to eax + 89/copy 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # copy eax to *edi + # skip-chars-not-matching-whitespace(line) # including trailing newline + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call skip-chars-not-matching-whitespace/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # out->end = &line->data[line->read] + 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 0xc/disp8 . # copy esi+ecx+12 to eax + 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) +$next-raw-word:end: + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 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 |