1 ## port of https://github.com/akkartik/crenshaw/blob/master/tutor2.1.pas 2 # corresponds to the section "single digits" in https://compilers.iecc.com/crenshaw/tutor2.txt 3 # 4 # To run (from the subx directory): 5 # $ subx translate *.subx apps/crenshaw2.1.subx -o crenshaw 2.1 6 # $ echo '3' |subx run apps/crenshaw2.1 |xxd - 7 # Expected output: 8 # TODO 9 # 10 # The output is the code a function would need to include, returning the 11 # result in EAX. 12 # 13 # Major note: byte strings are not null-terminated. Instead they're prefixed 14 # with a 32-bit length. 15 16 == code 17 # instruction effective address operand displacement immediate 18 # op subop mod rm32 base index scale r32 19 # 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 20 21 # main: 22 # abort("Integer") 23 # push args 24 68/push "Integer"/imm32 25 # call 26 e8/call abort/disp32 27 # discard arg 28 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 29 # syscall(exit, 0) 30 bb/copy-to-EBX 0/imm32 31 b8/copy-to-EAX 1/imm32/exit 32 cd/syscall 0x80/imm8 33 34 ## helpers 35 36 # print error message and exit 37 # really maps to the 'Expected' function in Crenshaw 38 abort: # s : (address array byte) -> <void> 39 # error(s) 40 # push args 41 ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . . 4/disp8 . # push *(ESP+4) 42 # call 43 e8/call error/disp32 44 # discard arg 45 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 46 # syscall(exit, 1) 47 bb/copy-to-EBX 1/imm32 48 b8/copy-to-EAX 1/imm32/exit 49 cd/syscall 0x80/imm8 50 51 # print out "Error: #{s} expected\n" to stderr 52 error: # s : (address array byte) -> <void> 53 # write(2/stderr, "Error: ") 54 # push args 55 68/push "Error: "/imm32 56 68/push 2/imm32/stderr 57 # call 58 e8/call write/disp32 59 # discard arg 60 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 61 # write(2/stderr, s) 62 # push args 63 ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . . 4/disp8 . # push *(ESP+4) 64 68/push 2/imm32/stderr 65 # call 66 e8/call write/disp32 67 # discard arg 68 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 69 # write(2/stderr, " expected") 70 # push args 71 68/push " expected"/imm32 72 68/push 2/imm32/stderr 73 # call 74 e8/call write/disp32 75 # discard arg 76 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 77 # write(2/stderr, "\n") 78 # push args 79 68/push Newline/imm32 80 68/push 2/imm32/stderr 81 # call 82 e8/call write/disp32 83 # discard arg 84 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 85 # end 86 c3/return 87 88 # vim:nowrap:textwidth=0