1436 lines
73 KiB
Plaintext
1436 lines
73 KiB
Plaintext
# Read a text file containing whitespace-separated pairs of ascii hex bytes
|
|
# from stdin, and convert them into binary bytes (octets) on stdout. Ignore
|
|
# comments between '#' and newline.
|
|
#
|
|
# To run:
|
|
# $ bootstrap/bootstrap translate [01]*.subx subx-params.subx hex.subx -o hex
|
|
# $ echo '80 81 82 # comment' |bootstrap/bootstrap run hex |xxd -
|
|
# Expected output:
|
|
# 00000000: 8081 82
|
|
#
|
|
# Only hex bytes and comments are permitted. Outside of comments all words
|
|
# must be exactly 2 characters long and contain only characters [0-9a-f]. No
|
|
# uppercase hex.
|
|
|
|
== 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: # run tests if necessary, convert stdin if not
|
|
# . prologue
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
|
|
# 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
|
|
|
|
# - if argc > 1 and argv[1] == "test", then return run_tests()
|
|
# if (argc <= 1) goto interactive
|
|
81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0/disp8 1/imm32 # compare *ebp
|
|
7e/jump-if-<= $subx-hex-main:interactive/disp8
|
|
# if (!kernel-string-equal?(argv[1], "test")) goto interactive
|
|
# . eax = kernel-string-equal?(argv[1], "test")
|
|
# . . push args
|
|
68/push "test"/imm32
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
|
|
# . . call
|
|
e8/call kernel-string-equal?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . if (eax == false) goto interactive
|
|
3d/compare-eax-and 0/imm32/false
|
|
74/jump-if-= $subx-hex-main:interactive/disp8
|
|
# run-tests()
|
|
e8/call run-tests/disp32
|
|
# 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
|
|
eb/jump $subx-hex-main:end/disp8
|
|
$subx-hex-main:interactive:
|
|
# - otherwise convert stdin
|
|
# . subx-hex(Stdin, Stdout, Stderr, 0)
|
|
# . . push args
|
|
68/push 0/imm32/exit-descriptor
|
|
68/push Stderr/imm32
|
|
68/push Stdout/imm32
|
|
68/push Stdin/imm32
|
|
# . . call
|
|
e8/call subx-hex/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
|
|
# syscall_exit(0)
|
|
bb/copy-to-ebx 0/imm32
|
|
$subx-hex-main:end:
|
|
e8/call syscall_exit/disp32
|
|
|
|
# the main entry point
|
|
subx-hex: # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
|
|
# pseudocode:
|
|
# while true
|
|
# eax = convert-next-octet(in, err, ed)
|
|
# if (eax == Eof) break
|
|
# write-byte-buffered(out, AL)
|
|
# flush(out)
|
|
#
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
50/push-eax
|
|
$subx-hex:loop:
|
|
# eax = convert-next-octet(in, err, ed)
|
|
# . . push args
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20)
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
|
|
# . . call
|
|
e8/call convert-next-octet/disp32
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# if (eax == Eof) break
|
|
3d/compare-eax-and 0xffffffff/imm32/Eof
|
|
74/jump-if-= $subx-hex:loop-end/disp8
|
|
# write-byte-buffered(out, AL)
|
|
# . . push args
|
|
50/push-eax
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
|
# . . call
|
|
e8/call write-byte-buffered/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# loop
|
|
eb/jump $subx-hex:loop/disp8
|
|
$subx-hex:loop-end:
|
|
# flush(out)
|
|
# . . push args
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
|
# . . call
|
|
e8/call flush/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
$subx-hex: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
|
|
|
|
# read bytes from 'in' until a sequence of two lowercase hex (0-9, a-f) bytes
|
|
# skip spaces and newlines
|
|
# on '#' skip bytes until newline
|
|
# raise an error and abort on all other unexpected bytes
|
|
# return in eax an _octet_ containing the binary value of the two hex characters
|
|
# return Eof on reaching end of file
|
|
convert-next-octet: # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor) -> byte-or-Eof/eax
|
|
# pseudocode:
|
|
# eax = scan-next-byte(in, err, ed)
|
|
# if (eax == Eof) return
|
|
# ecx = from-hex-char(eax)
|
|
# eax = scan-next-byte(in, err, ed)
|
|
# if (eax == Eof) error("partial byte found.")
|
|
# eax = from-hex-char(eax)
|
|
# eax = (ecx << 4) | eax
|
|
# return
|
|
#
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
51/push-ecx
|
|
# eax = scan-next-byte(in, err, ed)
|
|
# . . push args
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
|
|
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 scan-next-byte/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# if (eax == Eof) return
|
|
3d/compare-eax-and 0xffffffff/imm32/Eof
|
|
74/jump-if-= $convert-next-octet:end/disp8
|
|
# eax = from-hex-char(eax)
|
|
e8/call from-hex-char/disp32
|
|
# ecx = eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx
|
|
# eax = scan-next-byte(in, err, ed)
|
|
# . . push args
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
|
|
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 scan-next-byte/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# if (eax == Eof) error(ed, err, "partial byte found.")
|
|
3d/compare-eax-and 0xffffffff/imm32/Eof
|
|
75/jump-if-!= $convert-next-octet:convert/disp8
|
|
# . error-byte(ed, err, msg, '.') # reusing error-byte to avoid creating _yet_ another helper
|
|
# . . push args
|
|
68/push 0x2e/imm32/period/dummy
|
|
68/push "convert-next-octet: partial byte found"/imm32
|
|
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 . . . . 0x10/disp8 . # push *(ebp+16)
|
|
# . . call
|
|
e8/call error-byte/disp32 # never returns
|
|
$convert-next-octet:convert:
|
|
# eax = from-hex-char(eax)
|
|
e8/call from-hex-char/disp32
|
|
# eax = (ecx << 4) | eax
|
|
# . ecx <<= 4
|
|
c1/shift 4/subop/left 3/mod/direct 1/rm32/ecx . . . . . 4/imm8 # shift ecx left by 4 bits
|
|
# . eax |= ecx
|
|
09/or 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # eax = bitwise OR with ecx
|
|
$convert-next-octet: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
|
|
|
|
test-convert-next-octet:
|
|
# - check that the first two bytes of the input are assembled into the resulting octet
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to "abc"
|
|
# . 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
|
|
# initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call convert-next-octet/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to convert-next-octet
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that convert-next-octet didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-convert-next-octet: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-convert-next-octet:end/disp8
|
|
# check-ints-equal(eax, 0xab, msg)
|
|
# . . push args
|
|
68/push "F - test-convert-next-octet"/imm32
|
|
68/push 0xab/imm32/ab
|
|
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-convert-next-octet:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-convert-next-octet-handles-Eof:
|
|
# - check that reaching end of file returns Eof
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# don't initialize '_test-stream'
|
|
# initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call convert-next-octet/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to convert-next-octet
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that convert-next-octet didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-convert-next-octet: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-convert-next-octet-handles-Eof:end/disp8
|
|
# check-ints-equal(eax, Eof, msg)
|
|
# . . push args
|
|
68/push "F - test-convert-next-octet-handles-Eof"/imm32
|
|
68/push 0xffffffff/imm32/Eof
|
|
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-convert-next-octet-handles-Eof:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-convert-next-octet-aborts-on-single-hex-byte:
|
|
# - check that a single unaccompanied hex byte aborts
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to "a"
|
|
# . write(_test-stream, "a")
|
|
# . . push args
|
|
68/push "a"/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
|
|
# initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call convert-next-octet/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to convert-next-octet
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that convert-next-octet aborted
|
|
# . check-ints-equal(ed->value, 2, msg)
|
|
# . . push args
|
|
68/push "F - test-convert-next-octet-aborts-on-single-hex-byte: unexpected abort"/imm32
|
|
68/push 2/imm32
|
|
# . . push ed->value
|
|
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
|
|
$test-convert-next-octet-aborts-on-single-hex-byte:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
# read whitespace until a hex byte, and return it
|
|
# return Eof if file ends without finding a hex byte
|
|
# on '#' skip all bytes until newline
|
|
# abort on any other byte
|
|
scan-next-byte: # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor) -> byte-or-Eof/eax
|
|
# pseudocode:
|
|
# while true
|
|
# eax = read-byte-buffered(in)
|
|
# if (eax == Eof) return eax
|
|
# if (hex-digit?(eax)) return eax
|
|
# if (eax == ' ' or '\t' or '\n') continue
|
|
# if (eax == '#') skip-until-newline(in)
|
|
# else error-byte(ed, err, "invalid byte: " eax)
|
|
#
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
$scan-next-byte:loop:
|
|
# eax = read-byte-buffered(in)
|
|
# . . push args
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
|
|
# . . call
|
|
e8/call read-byte-buffered/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# if (eax == Eof) return eax
|
|
3d/compare-with-eax 0xffffffff/imm32/Eof
|
|
74/jump-if-= $scan-next-byte:end/disp8
|
|
# if (hex-digit?(eax)) return eax
|
|
# . save eax for now
|
|
50/push-eax
|
|
# . hex-digit?(eax)
|
|
# . . push args
|
|
50/push-eax
|
|
# . . call
|
|
e8/call hex-digit?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# . compare with 'false'
|
|
3d/compare-with-eax 0/imm32/false
|
|
# . restore eax (does not affect flags)
|
|
58/pop-to-eax
|
|
# . check whether to return
|
|
75/jump-if-!= $scan-next-byte:end/disp8
|
|
$scan-next-byte:check1:
|
|
# if (eax == ' ') continue
|
|
3d/compare-eax-and 0x20/imm32/space
|
|
74/jump-if-= $scan-next-byte:loop/disp8
|
|
# if (eax == '\t') continue
|
|
3d/compare-eax-and 9/imm32/tab
|
|
74/jump-if-= $scan-next-byte:loop/disp8
|
|
# if (eax == '\n') continue
|
|
3d/compare-eax-and 0xa/imm32/newline
|
|
74/jump-if-= $scan-next-byte:loop/disp8
|
|
$scan-next-byte:check2:
|
|
# if (eax == '#') skip-until-newline(in)
|
|
3d/compare-with-eax 0x23/imm32/hash
|
|
75/jump-if-!= $scan-next-byte:check3/disp8
|
|
# . skip-until-newline(in)
|
|
# . . push args
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
|
|
# . . call
|
|
e8/call skip-until-newline/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
eb/jump $scan-next-byte:loop/disp8
|
|
$scan-next-byte:check3:
|
|
# otherwise error-byte(ed, err, msg, eax)
|
|
# . . push args
|
|
50/push-eax
|
|
68/push "scan-next-byte: invalid byte"/imm32
|
|
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 . . . . 0x10/disp8 . # push *(ebp+16)
|
|
# . . call
|
|
e8/call error-byte/disp32 # never returns
|
|
$scan-next-byte:end:
|
|
# . restore registers
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-scan-next-byte:
|
|
# - check that the first byte of the input is returned
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to "abc"
|
|
# . 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
|
|
# initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call scan-next-byte/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to scan-next-byte
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that scan-next-byte didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-scan-next-byte:end/disp8
|
|
# check-ints-equal(eax, 0x61/a, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte"/imm32
|
|
68/push 0x61/imm32/a
|
|
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-scan-next-byte:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-scan-next-byte-skips-whitespace:
|
|
# - check that the first byte after whitespace is returned
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to input with leading whitespace
|
|
# . write(_test-stream, text)
|
|
# . . 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
|
|
# initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call scan-next-byte/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to scan-next-byte
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that scan-next-byte didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-skips-whitespace: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-scan-next-byte-skips-whitespace:end/disp8
|
|
# check-ints-equal(eax, 0x61/a, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-skips-whitespace"/imm32
|
|
68/push 0x61/imm32/a
|
|
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-scan-next-byte-skips-whitespace:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-scan-next-byte-skips-comment:
|
|
# - check that the first byte after a comment (and newline) is returned
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to input with leading comment
|
|
# . write(_test-stream, comment)
|
|
# . . push args
|
|
68/push "#x\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
|
|
# . write(_test-stream, real text)
|
|
# . . 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
|
|
# initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call scan-next-byte/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to scan-next-byte
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that scan-next-byte didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-scan-next-byte-skips-comment:end/disp8
|
|
# check-ints-equal(eax, 0x61/a, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-skips-comment"/imm32
|
|
68/push 0x61/imm32/a
|
|
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-scan-next-byte-skips-comment:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-scan-next-byte-skips-comment-and-whitespace:
|
|
# - check that the first byte after a comment and any further whitespace is returned
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to input with leading comment and more whitespace after newline
|
|
# . write(_test-stream, comment)
|
|
# . . push args
|
|
68/push "#x\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
|
|
# . write(_test-stream, real text)
|
|
# . . 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
|
|
# initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call scan-next-byte/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to scan-next-byte
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that scan-next-byte didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-scan-next-byte-skips-comment-and-whitespace:end/disp8
|
|
# check-ints-equal(eax, 0x61/a, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32
|
|
68/push 0x61/imm32/a
|
|
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-scan-next-byte-skips-comment-and-whitespace:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-scan-next-byte-skips-whitespace-and-comment:
|
|
# - check that the first byte after any whitespace and comments is returned
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . 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
|
|
# . clear-stream(_test-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to input with leading whitespace and comment
|
|
# . write(_test-stream, comment)
|
|
# . . push args
|
|
68/push " #x\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
|
|
# . write(_test-stream, real text)
|
|
# . . 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
|
|
# initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call scan-next-byte/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to scan-next-byte
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that scan-next-byte didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-scan-next-byte-skips-whitespace-and-comment:end/disp8
|
|
# check-ints-equal(eax, 0x61/a, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32
|
|
68/push 0x61/imm32/a
|
|
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-scan-next-byte-skips-whitespace-and-comment:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-scan-next-byte-reads-final-byte:
|
|
# - check that the final byte in input is returned
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to input with single character
|
|
# . write(_test-stream, character)
|
|
# . . push args
|
|
68/push "a"/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
|
|
# initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call scan-next-byte/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to scan-next-byte
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that scan-next-byte didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-scan-next-byte-reads-final-byte:end/disp8
|
|
# check-ints-equal(eax, 0x61/a, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-reads-final-byte"/imm32
|
|
68/push 0x61/imm32/a
|
|
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-scan-next-byte-reads-final-byte:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-scan-next-byte-handles-Eof:
|
|
# - check that the right sentinel value is returned when there's no data remaining to be read
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# leave '_test-stream' empty
|
|
# initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call scan-next-byte/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to scan-next-byte
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that scan-next-byte didn't abort
|
|
# . check-ints-equal(ed->value, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-handles-Eof: unexpected abort"/imm32
|
|
68/push 0/imm32
|
|
# . . push ed->value
|
|
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
|
|
# return if abort
|
|
81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4)
|
|
75/jump-if-!= $test-scan-next-byte-handles-Eof:end/disp8
|
|
# check-ints-equal(eax, Eof, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-handles-Eof"/imm32
|
|
68/push 0xffffffff/imm32/Eof
|
|
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-scan-next-byte-handles-Eof:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-scan-next-byte-aborts-on-invalid-byte:
|
|
# - check that the a bad byte immediately aborts
|
|
# This test uses exit-descriptors. Use ebp for setting up local variables.
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# clear all streams
|
|
# . 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/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-error-stream)
|
|
# . . push args
|
|
68/push _test-error-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-error-buffered-file->buffer)
|
|
# . . push args
|
|
68/push $_test-error-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to "x"
|
|
# . write(_test-stream, "x")
|
|
# . . push args
|
|
68/push "x"/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
|
|
# initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
|
|
# . var ed/ecx: exit-descriptor
|
|
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# . tailor-exit-descriptor(ed, 12)
|
|
# . . push args
|
|
68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte
|
|
51/push-ecx/ed
|
|
# . . call
|
|
e8/call tailor-exit-descriptor/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
|
|
# . . push args
|
|
51/push-ecx/ed
|
|
68/push _test-error-buffered-file/imm32
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call scan-next-byte/disp32
|
|
# registers except esp may be clobbered at this point
|
|
# pop args to scan-next-byte
|
|
# . . discard first 2 args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . . restore ed
|
|
59/pop-to-ecx
|
|
# check that scan-next-byte aborted
|
|
# . check-ints-equal(ed->value, 2, msg)
|
|
# . . push args
|
|
68/push "F - test-scan-next-byte-aborts-on-invalid-byte"/imm32
|
|
68/push 2/imm32
|
|
# . . push ed->value
|
|
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
|
|
$test-scan-next-byte-aborts-on-invalid-byte:end:
|
|
# . epilogue
|
|
# don't restore esp from ebp; manually reclaim locals
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
skip-until-newline: # in: (addr buffered-file)
|
|
# pseudocode:
|
|
# push eax
|
|
# while true
|
|
# eax = read-byte-buffered(in)
|
|
# if (eax == Eof) break
|
|
# if (eax == 0x0a) break
|
|
# pop eax
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
50/push-eax
|
|
$skip-until-newline:loop:
|
|
# . eax = read-byte-buffered(in)
|
|
# . . push args
|
|
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
|
|
# . . call
|
|
e8/call read-byte-buffered/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# . if (eax == Eof) break
|
|
3d/compare-eax-and 0xffffffff/imm32/Eof
|
|
74/jump-if-= $skip-until-newline:end/disp8
|
|
# . if (eax != 0xa/newline) loop
|
|
3d/compare-eax-and 0xa/imm32/newline
|
|
75/jump-if-!= $skip-until-newline:loop/disp8
|
|
$skip-until-newline: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
|
|
|
|
test-skip-until-newline:
|
|
# - check that the read pointer points after the newline
|
|
# 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->buffer)
|
|
# . . push args
|
|
68/push $_test-buffered-file->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# initialize '_test-stream' to "abc\nde"
|
|
# . write(_test-stream, "abc")
|
|
# . . push args
|
|
68/push "abc\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
|
|
# . write(_test-stream, "de")
|
|
# . . push args
|
|
68/push "de"/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
|
|
# skip-until-newline(_test-buffered-file)
|
|
# . . push args
|
|
68/push _test-buffered-file/imm32
|
|
# . . call
|
|
e8/call skip-until-newline/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(_test-buffered-file->read, 4, msg)
|
|
# . . push args
|
|
68/push "F - test-skip-until-newline"/imm32
|
|
68/push 4/imm32
|
|
b8/copy-to-eax _test-buffered-file/imm32
|
|
ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 8/disp8 . # push *(eax+8)
|
|
# . . 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
|
|
|
|
# . . vim:nowrap:textwidth=0
|