about summary refs log tree commit diff stats
path: root/subx/067parse-hex.subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-07-21 22:34:15 -0700
committerKartik Agaram <vc@akkartik.com>2019-07-21 23:29:38 -0700
commit0d219f0a732d81dad124906f5594a06b023fa3a0 (patch)
tree1e450a89e25e609c900c57edfb88ded4e96cf8da /subx/067parse-hex.subx
parentac8a9396b96259ed2d068abf30863540a21648f3 (diff)
downloadmu-0d219f0a732d81dad124906f5594a06b023fa3a0.tar.gz
5438 - raise error on uppercase hex
We can now translate layers 49-56 using the self-hosted translator
(`translate` and `ntranslate`).

As a follow-up to commit 5404, the self-hosted translator is a little
more strict than the C++ translator in 3 places:

a) All .subx files must define a data segment.

b) All .subx files must define an `Entry` label.

c) All numbers must be in *lowercase* hex.

In all cases, where programs work with the C++ translator but violate
the self-hosted translator's assumptions, we must make sure we raise
errors rather than silently emit bad code.
Diffstat (limited to 'subx/067parse-hex.subx')
-rw-r--r--subx/067parse-hex.subx75
1 files changed, 70 insertions, 5 deletions
diff --git a/subx/067parse-hex.subx b/subx/067parse-hex.subx
index bbfc4ec9..45d168d9 100644
--- a/subx/067parse-hex.subx
+++ b/subx/067parse-hex.subx
@@ -795,15 +795,80 @@ test-hex-above-f:
     c3/return
 
 from-hex-char:  # in/EAX : byte -> out/EAX : nibble
-    # no error checking; accepts argument in EAX
-    # if (EAX <= '9') return EAX - '0'
+$from-hex-char:check0:
+    # if (EAX < '0') goto abort
+    3d/compare-EAX-with  0x30/imm32/0
+    7c/jump-if-lesser  $from-hex-char:abort/disp8
+$from-hex-char:check1:
+    # if (EAX > 'f') goto abort
+    3d/compare-EAX-with  0x66/imm32/f
+    7f/jump-if-greater  $from-hex-char:abort/disp8
+$from-hex-char:check2:
+    # if (EAX > '9') goto next check
     3d/compare-EAX-with  0x39/imm32/9
-    7f/jump-if-greater  $from-hex-char:else/disp8
+    7f/jump-if-greater  $from-hex-char:check3/disp8
+$from-hex-char:digit:
+    # return EAX - '0'
     2d/subtract-from-EAX  0x30/imm32/0
     c3/return
-$from-hex-char:else:
-    # otherwise return EAX - 'a' + 10
+$from-hex-char:check3:
+    # if (EAX < 'a') goto abort
+    3d/compare-EAX-with  0x61/imm32/a
+    7c/jump-if-lesser  $from-hex-char:abort/disp8
+$from-hex-char:letter:
+    # return EAX - ('a'-10)
     2d/subtract-from-EAX  0x57/imm32/a-10
     c3/return
 
+$from-hex-char:abort:
+    # . _write(2/stderr, error)
+    # . . push args
+    68/push  "invalid hex char: "/imm32
+    68/push  2/imm32/stderr
+    # . . call
+    e8/call  _write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . clear-stream(Stderr+4)
+    # . . save EAX
+    50/push-EAX
+    # . . push args
+    b8/copy-to-EAX  Stderr/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
+    # . . restore EAX
+    58/pop-to-EAX
+    # . print-int32-buffered(Stderr, EAX)
+    # . . push args
+    50/push-EAX
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  print-int32-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . flush(Stderr)
+    # . . push args
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  flush/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+    # . _write(2/stderr, "\n")
+    # . . push args
+    68/push  "\n"/imm32
+    68/push  2/imm32/stderr
+    # . . call
+    e8/call  _write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . syscall(exit, 1)
+    bb/copy-to-EBX  1/imm32
+    b8/copy-to-EAX  1/imm32/exit
+    cd/syscall  0x80/imm8
+    # never gets here
+
 # . . vim:nowrap:textwidth=0