This seems like the final helper we need for Phase 2. Now to build the
business logic itself.
This commit is contained in:
Kartik Agaram 2019-02-02 15:21:48 -08:00
parent 4cb7d1fb77
commit cb82bd2364
3 changed files with 1588 additions and 577 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -21,7 +21,7 @@
# . 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
# for debugging: run a single test
#? e8/call test-has-metadata-true/disp32
#? e8/call test-emit-non-number-with-metadata/disp32
#? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX
#? eb/jump $main:end/disp8
@ -134,11 +134,6 @@ $main:end:
# next-token(stream, slice, delim char) -> slice'
# slice-equal?(slice, string)
# helpers:
# emit(out : &buffered-file, word : &slice, width : int)
# if slice is all hex digits, parse and print appropriate digits
# otherwise just write-slice
convert: # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> <void>
# pseudocode:
# line = new-stream(512, 1)
@ -618,6 +613,338 @@ test-has-metadata-multiple-false:
5d/pop-to-EBP
c3/return
# if the name of 'word' is all hex digits, parse and emit it in 'width' bytes
# of hex otherwise just write-slice
emit: # out : (address buffered-file), word : (address slice), width : int
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# . save registers
50/push-EAX
56/push-ESI
57/push-EDI
# ESI = word
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI
# var name/EDI : (address slice) = {0, 0}
68/push 0/imm32/end
68/push 0/imm32/start
89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI
# name = next-token-from-slice(word->start, word->end, '/')
# . . push args
57/push-EDI
68/push 0x2f/imm32/slash
ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4)
ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI
# . . call
e8/call next-token-from-slice/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# if !is-hex-int?(name) write-slice(out, word) and return
# . is-hex-int?(name)
# . . push args
57/push-EDI
# . . call
e8/call is-hex-int?/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# . if EAX == 0
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
75/jump-if-not-equal $emit:hex-int/disp8
# . write-slice(out, word)
# . . push args
56/push-ESI
ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8)
# . . call
e8/call write-slice/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# . return
eb/jump $emit:end/disp8
# otherwise emit-hex(out, parse-hex-int(name), width)
$emit:hex-int:
# . n/EAX = parse-hex-int(name)
# . . push args
57/push-EDI
# . . call
e8/call parse-hex-int/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# . emit-hex(out, n, width)
# . . push args
ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16)
50/push-EAX
ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8)
# . . call
e8/call emit-hex/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
$emit:end:
# . reclaim locals
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# . restore registers
5f/pop-to-EDI
5e/pop-to-ESI
58/pop-to-EAX
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-emit-number:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# 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
# . clear-stream(_test-buffered-file+4)
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# . . call
e8/call clear-stream/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# var slice/ECX = "-2"
68/push _test-slice-negative-two-end/imm32/end
68/push _test-slice-negative-two/imm32/start
89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX
# emit(_test-buffered-file, slice, 2)
# . . push args
68/push 2/imm32
51/push-ECX
68/push _test-buffered-file/imm32
# . . call
e8/call emit/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# flush(_test-buffered-file)
# . . push args
68/push _test-buffered-file/imm32
# . . call
e8/call flush/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check(_test-stream->data == 'fe ff ')
# . check-ints-equal(_test-stream->data[0..3], 'fe f', msg)
# . . push args
68/push "F - test-emit-number/1"/imm32
68/push 0x66206566/imm32
# . . 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
# . check-ints-equal(_test-stream->data[4..7], 'f ', msg)
# . . push args
68/push "F - test-emit-number/2"/imm32
68/push 0x2066/imm32
# . . push *_test-stream->data
b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16)
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-emit-number-with-metadata:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# 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
# . clear-stream(_test-buffered-file+4)
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# . . call
e8/call clear-stream/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# var slice/ECX = "-2/foo"
68/push _test-slice-negative-two-metadata-end/imm32/end
68/push _test-slice-negative-two/imm32/start
89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX
# emit(_test-buffered-file, slice, 2)
# . . push args
68/push 2/imm32
51/push-ECX
68/push _test-buffered-file/imm32
# . . call
e8/call emit/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# flush(_test-buffered-file)
# . . push args
68/push _test-buffered-file/imm32
# . . call
e8/call flush/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# the '/foo' will have no impact on the output
# check(_test-stream->data == 'fe ff ')
# . check-ints-equal(_test-stream->data[0..3], 'fe f', msg)
# . . push args
68/push "F - test-emit-number-with-metadata/1"/imm32
68/push 0x66206566/imm32
# . . 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
# . check-ints-equal(_test-stream->data[4..7], 'f ', msg)
# . . push args
68/push "F - test-emit-number-with-metadata/2"/imm32
68/push 0x2066/imm32
# . . push *_test-stream->data
b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16)
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-emit-non-number:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# 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
# . clear-stream(_test-buffered-file+4)
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# . . call
e8/call clear-stream/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# var slice/ECX = "xyz"
68/push _test-slice-non-number-word-end/imm32/end
68/push _test-slice-non-number-word/imm32/start
89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX
# emit(_test-buffered-file, slice, 2)
# . . push args
68/push 2/imm32
51/push-ECX
68/push _test-buffered-file/imm32
# . . call
e8/call emit/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# flush(_test-buffered-file)
# . . push args
68/push _test-buffered-file/imm32
# . . call
e8/call flush/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check(_test-stream->data == 'xyz')
# . check-ints-equal(_test-stream->data[0..3], 'xyz', msg)
# . . push args
68/push "F - test-emit-non-number"/imm32
68/push 0x7a7978/imm32
# . . 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
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-emit-non-number-with-metadata:
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# 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
# . clear-stream(_test-buffered-file+4)
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# . . call
e8/call clear-stream/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# var slice/ECX = "xyz/"
68/push _test-slice-non-number-word-metadata-end/imm32/end
68/push _test-slice-non-number-word/imm32/start
89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX
# emit(_test-buffered-file, slice, 2)
# . . push args
68/push 2/imm32
51/push-ECX
68/push _test-buffered-file/imm32
# . . call
e8/call emit/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# flush(_test-buffered-file)
# . . push args
68/push _test-buffered-file/imm32
# . . call
e8/call flush/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check(_test-stream->data == 'xyz/')
# . check-ints-equal(_test-stream->data[0..3], 'xyz/', msg)
# . . push args
68/push "F - test-emit-non-number-with-metadata"/imm32
68/push 0x2f7a7978/imm32
# . . 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
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# print 'n' in hex in 'width' bytes in lower-endian order, with a space after every byte
emit-hex: # out : (address buffered-file), n : int, width : int
# . prolog
@ -907,5 +1234,13 @@ test-emit-hex-negative:
_test-slice-negative-two:
2d/- 32/2
_test-slice-negative-two-end:
2f/slash 66/f 6f/o 6f/o
_test-slice-negative-two-metadata-end:
_test-slice-non-number-word:
78/x 79/y 7a/z
_test-slice-non-number-word-end:
2f/slash
_test-slice-non-number-word-metadata-end:
# . . vim:nowrap:textwidth=0