0d246473c5
Our infrastructure for displaying errors is far more rudimentary in baremetal. Many ways things can go wrong. But making the attempt seems better than not. I'm also making some effort to keep it easy to see what has been copied over from the top-level, by not modifying copied code to use syntax sugar and so on. It may not be an important enough reason to mix notations in a single file.
81 lines
4.0 KiB
Plaintext
81 lines
4.0 KiB
Plaintext
# Write a single byte to a stream.
|
|
#
|
|
# We need to do this in machine code because streams need to be opaque types,
|
|
# and we don't yet support opaque types in Mu.
|
|
|
|
== 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
|
|
|
|
# Write lower byte of 'n' to 'f'.
|
|
append-byte: # f: (addr stream byte), n: int
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
51/push-ecx
|
|
57/push-edi
|
|
# edi = f
|
|
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
|
|
# ecx = f->write
|
|
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
|
|
# if (f->write >= f->size) abort
|
|
3b/compare 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(edi+8)
|
|
7d/jump-if->= $append-byte:abort/disp8
|
|
$append-byte:to-stream:
|
|
# write to stream
|
|
# f->data[f->write] = LSB(n)
|
|
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
|
|
8a/copy-byte 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/AL 0xc/disp8 . # copy byte at *(ebp+12) to AL
|
|
88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy AL to *(edi+ecx+12)
|
|
# ++f->write
|
|
ff 0/subop/increment 0/mod/indirect 7/rm32/edi . . . . . . # increment *edi
|
|
$append-byte:end:
|
|
# . restore registers
|
|
5f/pop-to-edi
|
|
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
|
|
|
|
$append-byte:abort:
|
|
(draw-text-wrapping-down-then-right-from-cursor-over-full-screen 0 "append-byte: out of space\n" 3) # 3=cyan
|
|
{
|
|
eb/jump loop/disp8
|
|
}
|
|
# never gets here
|
|
|
|
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
|