diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-12-03 23:26:56 -0800 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-12-03 23:26:56 -0800 |
commit | 5f3b3e7aea4174f13da9b430538564c68257b647 (patch) | |
tree | 64b0ca70a7508aa10a008ad7d996f5d4f38214c8 /subx/063print-byte.subx | |
parent | ee73f5eb31e9dd5a185da097bd990ac94c3d282b (diff) | |
download | mu-5f3b3e7aea4174f13da9b430538564c68257b647.tar.gz |
4830
New helper: printing a byte in textual (hex) form. This required adding instructions for bitwise shift operations.
Diffstat (limited to 'subx/063print-byte.subx')
-rw-r--r-- | subx/063print-byte.subx | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/subx/063print-byte.subx b/subx/063print-byte.subx new file mode 100644 index 00000000..89f9e103 --- /dev/null +++ b/subx/063print-byte.subx @@ -0,0 +1,139 @@ +# Print the (hex) textual representation of the lowest byte of a number. + +== 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 + +# main: + e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. + # 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 + b8/copy-to-EAX 1/imm32 + cd/syscall 0x80/imm8 + +print-byte: # f : (address buffered-file), n : num -> <void> + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # . save registers + 50/push-EAX + # AL = convert upper nibble to hex + 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 0/r32/EAX 0xc/disp8 . # copy *(EBP+12) to EAX + c1/shift 5/subop/logic-right 3/mod/direct 0/rm32/EAX . . . . . 4/imm8 # shift EAX right by 4 bits, while padding zeroes + # . hex-char(AL) + # . . push args + 50/push-EAX + # . . call + e8/call hex-char/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # write-byte(f, AL) + # . . push args + 50/push-EAX + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8) + # . . call + e8/call write-byte/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # AL = convert lower nibble to hex + 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 0/r32/EAX 0xc/disp8 . # copy *(EBP+12) to EAX + 25/and-EAX 0xf/imm32 + # . hex-char(AL) + # . . push args + 50/push-EAX + # . . call + e8/call hex-char/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # write-byte(f, AL) + # . . push args + 50/push-EAX + ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8) + # . . call + e8/call write-byte/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . restore registers + 59/pop-to-ECX + 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 + +# extract lowest 4 bits and convert to 8-byte ascii +# return 0xffffffff if more than 4 bits are set +hex-char: # n : num -> char_or_error/EAX + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # EAX = n + 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX + # if it's <= 9 add '0' to it + 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x9/imm32 # compare EAX + 7f/jump-if-greater $hex-char:check2/disp8 + 05/add-to-EAX 0x30/imm32/'0' + eb/jump $hex-char:end/disp8 +$hex-char:check2: + # else if it's <= 15 add ('a' - 10) to it + 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xf/imm32 # compare EAX + 7f/jump-if-greater $hex-char:error/disp8 + 05/add-to-EAX 0x57/imm32 # 'a' - 10 + eb/jump $hex-char:end/disp8 +$hex-char:error: + # otherwise return 0xffffffff + b8/copy-to-EAX 0xffffffff/imm32 +$hex-char:end: + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-print-byte: + # - check that print-byte prints the hex textual representation + # 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 + # print-byte(_test-buffered-file, 0xa) # exercises digit, non-digit as well as leading zero + # . . push args + 68/push 0xa/imm32 + 68/push _test-buffered-file/imm32 + # . . call + e8/call print-byte/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/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-ints-equal(*_test-stream->data, '0a', msg) + # . . push args + 68/push "F - test-print-byte"/imm32 + 68/push 0x6130/imm32/0a + # . . 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 |