From 1639687ba098aa81b0584f7dd609cb9690dc5a04 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 14 Feb 2019 16:24:20 -0800 Subject: [PATCH] 4961 --- subx/051test.subx | 2 +- subx/052kernel-string-equal.subx | 56 +++++++------ subx/054string-equal.subx | 43 +++++----- subx/055stream.subx | 4 +- subx/056trace.subx | 15 ++-- subx/057write.subx | 2 +- subx/058stream-equal.subx | 36 ++++----- subx/059stop.subx | 7 +- subx/061read-byte.subx | 2 +- subx/065hex.subx | 6 +- subx/067write-buffered.subx | 4 +- subx/069allocate.subx | 2 +- subx/071read-line.subx | 8 +- subx/072slice.subx | 40 ++++++--- subx/apps/crenshaw2-1 | Bin 17612 -> 17607 bytes subx/apps/crenshaw2-1.subx | 16 ++-- subx/apps/crenshaw2-1b | Bin 18171 -> 18166 bytes subx/apps/crenshaw2-1b.subx | 22 ++--- subx/apps/factorial | Bin 16530 -> 16525 bytes subx/apps/factorial.subx | 2 +- subx/apps/handle | Bin 17323 -> 17318 bytes subx/apps/hex | Bin 20591 -> 20586 bytes subx/apps/hex.subx | 32 ++++---- subx/apps/pack | Bin 20768 -> 20763 bytes subx/apps/pack.subx | 24 +++--- subx/examples/ex10.subx | 1 - subx/examples/ex11 | Bin 1117 -> 1111 bytes subx/examples/ex11.subx | 135 ++++++++++++++++--------------- subx/examples/ex3.subx | 2 +- subx/examples/ex8.subx | 2 +- subx/opcodes | 1 + 31 files changed, 254 insertions(+), 210 deletions(-) diff --git a/subx/051test.subx b/subx/051test.subx index 08d1d6f6..2ae907c1 100644 --- a/subx/051test.subx +++ b/subx/051test.subx @@ -32,7 +32,7 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> # load first 2 args into EAX and EBX 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX - # if EAX == EBX success + # if (EAX == EBX) success 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX 75/jump-if-unequal $check-ints-equal:else/disp8 # . _write(2/stderr, '.') diff --git a/subx/052kernel-string-equal.subx b/subx/052kernel-string-equal.subx index b61c3303..840b4460 100644 --- a/subx/052kernel-string-equal.subx +++ b/subx/052kernel-string-equal.subx @@ -30,19 +30,26 @@ # reason for the name: the only place we should have null-terminated ascii strings is from commandline args kernel-string-equal?: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean # pseudocode: - # initialize n = b->length - # initialize s1 = s - # initialize s2 = b->data + # n = benchmark->length + # s1 = s + # s2 = benchmark->data # i = 0 - # for (i = 0; i < n; ++n) + # while (i < n) # c1 = *s1 # c2 = *s2 - # if c1 == 0 - # return false - # if c1 != c2 - # return false + # if (c1 == 0) return false + # if (c1 != c2) return false + # ++s1, ++s2, ++i # return *s1 == 0 # + # registers: + # i: ECX + # n: EDX + # s1: EDI + # s2: ESI + # c1: EAX + # c2: EBX + # # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP @@ -52,24 +59,25 @@ kernel-string-equal?: # s : null-terminated ascii string, benchmark : length-pr 53/push-EBX 56/push-ESI 57/push-EDI - # initialize s into EDI + # s1/EDI = s 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI - # initialize benchmark length n into EDX + # n/EDX = benchmark->length 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX 8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX - # initialize benchmark data into ESI + # s2/ESI = benchmark->data 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI 81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 4/imm32 # add to ESI - # initialize loop counter i into ECX + # i/ECX = c1/EAX = c2/EBX = 0 b9/copy-to-ECX 0/imm32/exit - # while (i/ECX < n/EDX) -$kernel-string-equal?:loop: - 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX - 74/jump-if-equal $kernel-string-equal?:break/disp8 - # c1/EAX, c2/EBX = *s, *benchmark b8/copy-to-EAX 0/imm32 - 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX bb/copy-to-EBX 0/imm32 +$kernel-string-equal?:loop: + # if (i >= n) break + 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX + 7d/jump-if-greater-or-equal $kernel-string-equal?:break/disp8 + # c1 = *s1 + 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX + # c2 = *s2 8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX # if (c1 == 0) return false 3d/compare-EAX 0/imm32 @@ -77,22 +85,21 @@ $kernel-string-equal?:loop: # if (c1 != c2) return false 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX 75/jump-if-not-equal $kernel-string-equal?:false/disp8 - # ++s1, ++s2, ++i + # ++i 41/inc-ECX - 46/inc-ESI + # ++s1 47/inc-EDI - # end while + # ++s2 + 46/inc-ESI eb/jump $kernel-string-equal?:loop/disp8 $kernel-string-equal?:break: - # if (*s/EDI == 0) return true - b8/copy-to-EAX 0/imm32 + # return *s1 == 0 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX 3d/compare-EAX 0/imm32 75/jump-if-not-equal $kernel-string-equal?:false/disp8 $kernel-string-equal?:true: b8/copy-to-EAX 1/imm32 eb/jump $kernel-string-equal?:end/disp8 - # return false $kernel-string-equal?:false: b8/copy-to-EAX 0/imm32 $kernel-string-equal?:end: @@ -253,6 +260,7 @@ test-compare-kernel-string-with-longer-array: Null-kernel-string: 00/null + _test-Abc-kernel-string: 41/A 62/b 63/c 00/null diff --git a/subx/054string-equal.subx b/subx/054string-equal.subx index fdfca84e..f69c0c0f 100644 --- a/subx/054string-equal.subx +++ b/subx/054string-equal.subx @@ -13,18 +13,27 @@ b8/copy-to-EAX 1/imm32/exit cd/syscall 0x80/imm8 -string-equal?: # s : string, benchmark : string -> EAX : boolean +string-equal?: # s : (address string), benchmark : (address string) -> EAX : boolean # pseudocode: - # if s->length != b->length return false - # for i = 0; i < s->length; ++i - # if s[i] != b[i] return false + # lens = s->length + # if (lens != benchmark->length) return false + # i = 0 + # currs = s->data + # currb = benchmark->data + # while (i < s->length) + # c1 = *currs + # c2 = *currb + # if (c1 != c2) return false + # ++i, ++currs, ++currb # return true + # # registers: # i: ECX - # s->length: EDX - # b->length: EBX - # b[i]: EBX - # s[i]: EAX + # lens: EDX + # currs: EAX + # currb: EBX + # c1: ESI + # c2: EDI # # . prolog 55/push-EBP @@ -34,17 +43,16 @@ string-equal?: # s : string, benchmark : string -> EAX : boolean 52/push-EDX 53/push-EBX 56/push-ESI - # var s/EAX : (address array byte) + # EAX = s 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX - # var benchmark/EBX : (address array byte) + # EBX = benchmark 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX - # if s->length != b->length return false - # EDX = s->length + # lens/EDX = s->length 8b/copy 0/mod/indirect 0/rm32/EAX . . . 2/r32/EDX . . # copy *EAX to EDX - # compare s->length and b->length +$string-equal?:lengths: + # if (lens != benchmark->length) return false 39/compare 0/mod/indirect 3/rm32/EBX . . . 2/r32/EDX . . # compare *EBX with EDX 75/jump-if-not-equal $string-equal?:false/disp8 -$string-equal?:lengths: # var i/ECX : int = 0 b9/copy-to-ECX 0/imm32 # EBX = &b[i] @@ -52,7 +60,7 @@ $string-equal?:lengths: # EAX = &s[i] 40/inc-EAX $string-equal?:loop: - # if i >= s->length return true + # if (i >= lens) return true 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX 7d/jump-if-greater-or-equal $string-equal?:true/disp8 # if b[i] != s[i] return false @@ -63,16 +71,15 @@ $string-equal?:loop: 75/jump-if-not-equal $string-equal?:false/disp8 # ++i 41/inc-ECX + # ++c1 40/inc-EAX + # ++c2 43/inc-EBX - # loop eb/jump $string-equal?:loop/disp8 $string-equal?:true: - # return true b8/copy-to-EAX 1/imm32 eb/jump $string-equal?:end/disp8 $string-equal?:false: - # return false b8/copy-to-EAX 0/imm32 $string-equal?:end: # . restore registers diff --git a/subx/055stream.subx b/subx/055stream.subx index 0d196311..f5d24876 100644 --- a/subx/055stream.subx +++ b/subx/055stream.subx @@ -42,7 +42,7 @@ clear-stream: # f : (address stream) -> 81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 0xc/imm32 # add to EAX # while (true) $clear-stream:loop: - # if EAX >= ECX break + # if (EAX >= ECX) break 39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX with ECX 7d/jump-if-greater-or-equal $clear-stream:end/disp8 # *EAX = 0 @@ -76,3 +76,5 @@ $rewind-stream:end: 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 5d/pop-to-EBP c3/return + +# . . vim:nowrap:textwidth=0 diff --git a/subx/056trace.subx b/subx/056trace.subx index 96e5646b..aa73bbdd 100644 --- a/subx/056trace.subx +++ b/subx/056trace.subx @@ -99,7 +99,7 @@ trace: # t : (address trace-stream), line : string e8/call _append-3/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - # if EAX == 0 return + # if (EAX == 0) return 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EDX 74/jump-if-equal $trace:end/disp8 # t->write += EAX @@ -153,9 +153,8 @@ clear-trace-stream: # t : (address trace-stream) c7 0/subop/copy 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 0/imm32 # copy to *(EAX+4) # EAX = t->data 81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 0xc/imm32 # add to EAX - # while (true) $clear-trace-stream:loop: - # if EAX >= ECX break + # if (EAX >= ECX) break 39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX with ECX 7d/jump-if-greater-or-equal $clear-trace-stream:end/disp8 # *EAX = 0 @@ -328,18 +327,20 @@ _append-4: # out : address, outend : address, in : address, inend : address -> # ECX = inend 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 0x14/disp8 . # copy *(EBP+20) to ECX $_append-4:loop: - # if ESI/in >= ECX/inend break + # if (in >= inend) break 39/compare 3/mod/direct 6/rm32/ESI . . . 1/r32/ECX . . # compare ESI with ECX 7d/jump-if-greater-or-equal $_append-4:end/disp8 - # if EDI/out >= EDX/outend break (for now silently ignore filled up buffer) + # if (out >= outend) break # for now silently ignore filled up buffer 39/compare 3/mod/direct 7/rm32/EDI . . . 2/r32/EDX . . # compare EDI with EDX 7d/jump-if-greater-or-equal $_append-4:end/disp8 - # copy one byte from ESI/in to EDI/out + # *out = *in 8a/copy-byte 0/mod/indirect 6/rm32/ESI . . . 3/r32/BL . . # copy byte at *ESI to BL 88/copy-byte 0/mod/indirect 7/rm32/EDI . . . 3/r32/BL . . # copy byte at BL to *EDI - # updates + # ++num_bytes_appended 40/increment-EAX + # ++in 46/increment-ESI + # ++out 47/increment-EDI eb/jump $_append-4:loop/disp8 $_append-4:end: diff --git a/subx/057write.subx b/subx/057write.subx index 3f2f8a11..c1712996 100644 --- a/subx/057write.subx +++ b/subx/057write.subx @@ -32,7 +32,7 @@ write: # f : fd or (address stream), s : (address array byte) -> # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # if (f < 0x08000000) _write(f, s), return # f can't be a user-mode address, so treat it as a kernel file descriptor + # if (f < 0x08000000) _write(f, s) and return # f can't be a user-mode address, so treat it as a kernel file descriptor 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x08000000/imm32 # compare *(EBP+8) 7d/jump-if-greater-or-equal $write:fake/disp8 # . . push args diff --git a/subx/058stream-equal.subx b/subx/058stream-equal.subx index e4c1962e..203e5415 100644 --- a/subx/058stream-equal.subx +++ b/subx/058stream-equal.subx @@ -32,7 +32,7 @@ stream-data-equal?: # f : (address stream), s : (address string) -> EAX : boole 81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 0xc/imm32 # add to ESI # EDI = s 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI - # if (f->write != s->length) return false; + # if (f->write != s->length) return false 39/compare 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # compare *EDI and EAX 75/jump-if-not-equal $stream-data-equal?:false/disp8 # currs/EDI = s->data @@ -235,25 +235,25 @@ next-stream-line-equal?: # f : (address stream), s : (address string) -> EAX : # pseudocode: # currf = f->read # bound: f->write # currs = 0 # bound : s->length - # while true - # if currf >= f->write + # while true: + # if (currf >= f->write) # return currs >= s->length - # if f[currf] == '\n' + # if (f[currf] == '\n') # ++currf # return currs >= s->length - # if currs >= s->length return false # the current line of f still has data to match - # if f[currf] != s[currs] return false + # if (currs >= s->length) return false # the current line of f still has data to match + # if (f[currf] != s[currs]) return false # ++currf # ++currs # # collapsing the two branches that can return true: # currf = f->read # bound: f->write # currs = 0 # bound : s->length - # while true - # if currf >= f->write break - # if f[currf] == '\n' break - # if currs >= s->length return false # the current line of f still has data to match - # if f[currf] != s[currs] return false + # while true: + # if (currf >= f->write) break + # if (f[currf] == '\n') break + # if (currs >= s->length) return false # the current line of f still has data to match + # if (f[currf] != s[currs]) return false # ++currf # ++currs # ++currf # skip '\n' @@ -261,12 +261,12 @@ next-stream-line-equal?: # f : (address stream), s : (address string) -> EAX : # Here the final `++currf` is sometimes unnecessary (if we're already at the end of the stream) # # registers: - # f : ESI - # s : EDI - # currf : ECX - # currs : EDX - # f[currf] : EAX - # s[currs] : EBX + # f: ESI + # s: EDI + # currf: ECX + # currs: EDX + # f[currf]: EAX + # s[currs]: EBX # # . prolog 55/push-EBP @@ -312,7 +312,7 @@ $next-stream-line-equal?:loop: $next-stream-line-equal?:break: # ++currf 41/increment-ECX - # if currs >= s->length return true + # if (currs >= s->length) return true 3b/compare 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # compare EDX with *EDI 7c/jump-if-lesser $next-stream-line-equal?:false/disp8 $next-stream-line-equal?:true: diff --git a/subx/059stop.subx b/subx/059stop.subx index f9e67f9e..4478dab3 100644 --- a/subx/059stop.subx +++ b/subx/059stop.subx @@ -100,19 +100,20 @@ stop: # ed : (address exit-descriptor), value : int # no prolog; one way or another, we're going to clobber registers # EAX = ed 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX 4/disp8 . # copy *(ESP+4) to EAX - # exit(value) if ed->target == 0 + # if (ed->target == 0) really exit 81 7/subop/compare 0/mod/indirect 0/rm32/EAX . . . . . 0/imm32 # compare *EAX 75/jump-if-not-equal $stop:fake/disp8 - # syscall(exit, value) + # . syscall(exit, value) 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 3/r32/EBX 8/disp8 . # copy *(ESP+8) to EBX b8/copy-to-EAX 1/imm32/exit cd/syscall 0x80/imm8 $stop:fake: + # otherwise: # ed->value = value+1 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(ESP+8) to ECX 41/inc-ECX 89/copy 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy ECX to *(EAX+4) - # non-local jump to ed->target + # perform a non-local jump to ed->target 8b/copy 0/mod/indirect 0/rm32/EAX . . . 4/r32/ESP . . # copy *EAX to ESP $stop:end: c3/return # doesn't return to caller diff --git a/subx/061read-byte.subx b/subx/061read-byte.subx index c62b035e..a915d436 100644 --- a/subx/061read-byte.subx +++ b/subx/061read-byte.subx @@ -74,7 +74,7 @@ read-byte: # f : (address buffered-file) -> byte-or-eof/EAX e8/call read/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # if EAX = 0 return 0xffffffff + # if (EAX == 0) return 0xffffffff 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX 75/jump-if-not-equal $read-byte:from-stream/disp8 b8/copy-to-EAX 0xffffffff/imm32 diff --git a/subx/065hex.subx b/subx/065hex.subx index 6ba2ef7e..9096680b 100644 --- a/subx/065hex.subx +++ b/subx/065hex.subx @@ -71,7 +71,7 @@ $is-hex-int?:loop: e8/call is-hex-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # if EAX == false return false + # if (EAX == false) return false 3d/compare-with-EAX 0/imm32 74/jump-if-equal $is-hex-int?:end/disp8 # ++curr @@ -738,7 +738,7 @@ test-hex-above-f: from-hex-char: # in/EAX : byte -> out/EAX : num # no error checking; accepts argument in EAX - # if EAX <= '9' return EAX - '0' + # if (EAX <= '9') return EAX - '0' 3d/compare-EAX 0x39/imm32/9 7f/jump-if-greater $from-hex-char:else/disp8 2d/subtract-from-EAX 0x30/imm32/0 @@ -750,7 +750,7 @@ $from-hex-char:else: to-hex-char: # in/EAX : nibble -> out/EAX : byte # no error checking; accepts argument in EAX - # if EAX <= 9 return EAX + '0' + # if (EAX <= 9) return EAX + '0' 3d/compare-EAX 0x9/imm32/9 7f/jump-if-greater $to-hex-char:else/disp8 05/add-to-EAX 0x30/imm32/0 diff --git a/subx/067write-buffered.subx b/subx/067write-buffered.subx index 3825a7f3..50ec7988 100644 --- a/subx/067write-buffered.subx +++ b/subx/067write-buffered.subx @@ -18,8 +18,8 @@ write-buffered: # f : (address buffered-file), msg : (address array byte) -> data # inend = &msg->data[msg->length] - # while in < inend - # if f->write >= f->length + # while (in < inend) + # if (f->write >= f->length) # flush(f) # clear-stream(f) # f->data[f->write] = *in diff --git a/subx/069allocate.subx b/subx/069allocate.subx index 37b01d21..1d9e043a 100644 --- a/subx/069allocate.subx +++ b/subx/069allocate.subx @@ -164,7 +164,7 @@ allocate-region: # ad : (address allocation-descriptor), n : int -> new-ad : (a e8/call allocate/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # if EAX == 0 abort + # if (EAX == 0) abort 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX 74/jump-if-equal $allocate-region:abort/disp8 # earmark 8 bytes at the start for a new allocation descriptor diff --git a/subx/071read-line.subx b/subx/071read-line.subx index 3efa96e0..61513aa9 100644 --- a/subx/071read-line.subx +++ b/subx/071read-line.subx @@ -23,7 +23,7 @@ read-line: # f : (address buffered-file), s : (address stream byte) -> eof?/EAX # s->data[s->write] = AL # ++f->read # ++s->write - # if AL == '\n' break + # if (AL == '\n') break # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP @@ -65,8 +65,8 @@ $read-line:loop: e8/call read/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # if f->write == 0 return true - # . if EAX == 0 return true + # if (f->write == 0) return true + # . if (EAX == 0) return true 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX 75/jump-if-not-equal $read-line:from-stream/disp8 b8/copy-to-EAX 0xffffffff/imm32 @@ -81,7 +81,7 @@ $read-line:from-stream: 41/increment-ECX # ++s->write 42/increment-EDX - # if AL == '\n' return false + # if (AL == '\n') return false 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX 75/jump-if-not-equal $read-line:loop/disp8 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX diff --git a/subx/072slice.subx b/subx/072slice.subx index fa244219..20a39aa4 100644 --- a/subx/072slice.subx +++ b/subx/072slice.subx @@ -21,7 +21,7 @@ slice-empty?: # s : (address slice) -> EAX : boolean 51/push-ECX # ECX = s 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX - # if s->start == s->end return true + # if (s->start == s->end) return true # . EAX = s->start 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX # . compare EAX with s->end @@ -96,6 +96,24 @@ test-slice-empty-false: c3/return slice-equal?: # s : (address slice), p : (address string) -> EAX : boolean + # pseudocode: + # currs = s->start + # maxs = s->end + # if (maxs - currs != p->length) return false + # currp = p->data + # while (currs < maxs) + # if (*currs != *currp) return false + # ++currs + # ++currp + # return true + # + # registers: + # EAX : *currs + # ECX : *currp + # EDX : currs + # EBX : currp + # ESI : maxs + # # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP @@ -106,37 +124,37 @@ slice-equal?: # s : (address slice), p : (address string) -> EAX : boolean 56/push-ESI # ESI = s 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI - # curr/EDX = s->start + # currs/EDX = s->start 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX - # max/ESI = s->end + # maxs/ESI = s->end 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI # EBX = p 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX - # EAX = s->end - s->start + # EAX = maxs - currs 89/copy 3/mod/direct 0/rm32/EAX . . . 6/r32/ESI . . # copy ESI to EAX 29/subtract 3/mod/direct 0/rm32/EAX . . . 2/r32/EDX . . # subtract EDX from EAX - # if (EAX != p->length) return false; + # if (EAX != p->length) return false 39/compare 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # compare *EBX and EAX 75/jump-if-not-equal $slice-equal?:false/disp8 - # skip p->length + # currp/EBX = p->data 81 0/subop/add 3/mod/direct 3/rm32/EBX . . . . . 4/imm32 # add to EBX # EAX = ECX = 0 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX $slice-equal?:loop: - # if (curr >= max) return true + # if (currs >= maxs) return true 39/compare 3/mod/direct 2/rm32/EDX . . . 6/r32/ESI . . # compare EDX and ESI 7d/jump-if-greater-or-equal $slice-equal?:true/disp8 - # AL = *p + # AL = *currp 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL - # CL = *curr + # CL = *currs 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 1/r32/CL . . # copy byte at *EDX to CL # if (EAX != ECX) return false 39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX and ECX 75/jump-if-not-equal $slice-equal?:false/disp8 - # ++p + # ++currp 43/increment-EBX - # ++curr + # ++currs 42/increment-EDX eb/jump $slice-equal?:loop/disp8 $slice-equal?:false: diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index 3391c3146216f88f33679c4dec2c7e3f7b3b18e7..73a344418fdae942ed5ee2f7b70bcb22e4bfd2d6 100755 GIT binary patch literal 17607 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 TR=6eOMGo7{q?koy_}u>o-vEh- diff --git a/subx/apps/crenshaw2-1.subx b/subx/apps/crenshaw2-1.subx index 7c279955..3fe51fd7 100644 --- a/subx/apps/crenshaw2-1.subx +++ b/subx/apps/crenshaw2-1.subx @@ -37,7 +37,7 @@ # main: run tests if necessary, call 'compile' if not # . prolog 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # - if argc > 1 and argv[1] == "test" then return run_tests() + # - if argc > 1 and argv[1] == "test", then return run_tests() # . argc > 1 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 7e/jump-if-lesser-or-equal $run-main/disp8 @@ -199,8 +199,8 @@ $compile:end: # 'in' into it on exit. get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> # pseudocode: - # if !is-digit?(Look) expected(ed, err, "integer") - # if out->write >= out->length + # if (!is-digit?(Look)) expected(ed, err, "integer") + # if (out->write >= out->length) # write(err, "Error: too many digits in number\n") # stop(ed, 1) # out->data[out->write] = LSB(Look) @@ -221,7 +221,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # - if is-digit?(Look) expected(ed, err, "integer") + # - if (is-digit?(Look)) expected(ed, err, "integer") # . EAX = is-digit?(Look) # . . push args ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look @@ -229,7 +229,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a e8/call is-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # . if EAX == 0 + # . if (EAX == 0) 3d/compare-EAX 0/imm32 75/jump-if-not-equal $get-num:main/disp8 # . expected(ed, err, "integer") @@ -259,7 +259,7 @@ $get-num:main: 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX # EDX = out->length 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX - # if out->write >= out->length error + # if (out->write >= out->length) error 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX 7d/jump-if-lesser $get-num:stage2/disp8 # . error(ed, err, msg) # TODO: show full number @@ -559,10 +559,10 @@ is-digit?: # c : int -> EAX : boolean 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # EAX = false b8/copy-to-EAX 0/imm32 - # if c < '0' return false + # if (c < '0') return false 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x30/imm32 # compare *(EBP+8) 7c/jump-if-lesser $is-digit?:end/disp8 - # if c > '9' return false + # if (c > '9') return false 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x39/imm32 # compare *(EBP+8) 7f/jump-if-greater $is-digit?:end/disp8 # otherwise return true diff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b index 24c37657b07194395ea486debf9276661c76e552..80c9e4f03442b274a7304ec11dc15a6fc4bad253 100755 GIT binary patch literal 18166 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 1 and argv[1] == "test" then return run_tests() + # - if argc > 1 and argv[1] == "test", then return run_tests() # . argc > 1 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 7e/jump-if-lesser-or-equal $run-main/disp8 @@ -200,15 +200,15 @@ $compile:end: # 'in' (rest). We leave the next byte from 'in' into 'Look' on exit. get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> # pseudocode: - # if !is-digit?(Look) expected(ed, err, "integer") + # if (!is-digit?(Look)) expected(ed, err, "integer") # do - # if out->write >= out->length + # if (out->write >= out->length) # write(err, "Error: too many digits in number\n") # stop(ed, 1) # out->data[out->write] = LSB(Look) # ++out->write # Look = get-char(in) - # while is-digit?(Look) + # while (is-digit?(Look)) # This is complicated because I don't want to hard-code the error strategy in # a general helper like write-byte. Maybe I should just create a local helper. # @@ -226,7 +226,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # - if is-digit?(Look) expected(ed, err, "integer") + # - if (is-digit?(Look)) expected(ed, err, "integer") # . EAX = is-digit?(Look) # . . push args ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look @@ -234,7 +234,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a e8/call is-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # . if EAX == 0 + # . if (EAX == 0) 3d/compare-EAX 0/imm32 75/jump-if-not-equal $get-num:main/disp8 # . expected(ed, err, "integer") @@ -265,7 +265,7 @@ $get-num:main: # EDX = out->length 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX $get-num:loop: - # if out->write >= out->length error + # if (out->write >= out->length) error 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX 7d/jump-if-lesser $get-num:loop-stage2/disp8 # . error(ed, err, msg) # TODO: show full number @@ -291,7 +291,7 @@ $get-num:loop-stage2: e8/call get-char/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # if is-digit?(Look) loop + # if (is-digit?(Look)) loop # . EAX = is-digit?(Look) # . . push args ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look @@ -299,7 +299,7 @@ $get-num:loop-stage2: e8/call is-digit?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # . if EAX loop + # . if (EAX != 0) loop 3d/compare-EAX 0/imm32 0f 85/jump-if-not-equal $get-num:loop/disp32 $get-num:loop-end: @@ -756,10 +756,10 @@ is-digit?: # c : int -> EAX : boolean 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # EAX = false b8/copy-to-EAX 0/imm32 - # if c < '0' return false + # if (c < '0') return false 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x30/imm32 # compare *(EBP+8) 7c/jump-if-lesser $is-digit?:end/disp8 - # if c > '9' return false + # if (c > '9') return false 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x39/imm32 # compare *(EBP+8) 7f/jump-if-greater $is-digit?:end/disp8 # otherwise return true diff --git a/subx/apps/factorial b/subx/apps/factorial index 01112b12e1b8bc210ecff2040c9ccba2db3c931f..83a5e14f231a39e794750e7fa66900e629473a39 100755 GIT binary patch literal 16525 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 diff --git a/subx/apps/factorial.subx b/subx/apps/factorial.subx index a239d419..912285e2 100644 --- a/subx/apps/factorial.subx +++ b/subx/apps/factorial.subx @@ -21,7 +21,7 @@ # main: # . prolog 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # - if argc > 1 and argv[1] == "test" then return run_tests() + # - if argc > 1 and argv[1] == "test", then return run_tests() # . argc > 1 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 7e/jump-if-lesser-or-equal $run-main/disp8 diff --git a/subx/apps/handle b/subx/apps/handle index 164fbd1a8874c2a9871f4c922e4787214d4fb6ce..d79ed98e30bbbd7dd6bb3446d2911835f15adf01 100755 GIT binary patch literal 17318 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 diff --git a/subx/apps/hex b/subx/apps/hex index 5edc02a3b6f1d1c2f09d0df2b532b331345b9aed..a95008307991db98871b79345289ab39bfa98a80 100755 GIT binary patch literal 20586 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�ntCA?WEuW*c4wVwXHWh1fEGQZ= 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 A!vFvP diff --git a/subx/apps/hex.subx b/subx/apps/hex.subx index 2c1606ed..d841fd8b 100644 --- a/subx/apps/hex.subx +++ b/subx/apps/hex.subx @@ -25,7 +25,7 @@ # main: run tests if necessary, convert stdin if not # . prolog 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # - if argc > 1 and argv[1] == "test" then return run_tests() + # - if argc > 1 and argv[1] == "test", then return run_tests() # . argc > 1 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 7e/jump-if-lesser-or-equal $run-main/disp8 @@ -73,7 +73,7 @@ convert: # in : (address buffered-file), out : (address buffered-file), err : ( # pseudocode: # repeatedly # EAX = convert-next-octet(in, err, ed) - # if EAX == 0xffffffff break # eof + # if (EAX == 0xffffffff) break # eof # write-byte(out, AL) # flush(out) # @@ -92,7 +92,7 @@ $convert:loop: 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 == 0xffffffff break + # if (EAX == 0xffffffff) break 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX 74/jump-if-equal $convert:loop-end/disp8 # write-byte(out, AL) @@ -489,10 +489,10 @@ scan-next-byte: # in : (address buffered-file), err : (address buffered-file), # pseudocode: # repeatedly # EAX = read-byte(in) - # if EAX == 0xffffffff return EAX - # if is-hex-digit?(EAX) return EAX - # if EAX == ' ' or '\t' or '\n' continue - # if EAX == '#' skip-until-newline(in) + # if (EAX == 0xffffffff) return EAX + # if (is-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) # # . prolog @@ -510,7 +510,7 @@ $scan-next-byte:loop: # if (EAX == 0xffffffff) return EAX 3d/compare-with-EAX 0xffffffff/imm32 74/jump-if-equal $scan-next-byte:end/disp8 - # if is-hex-digit?(EAX) return EAX + # if (is-hex-digit?(EAX)) return EAX # . save EAX for now 50/push-EAX # . is-hex-digit?(EAX) @@ -527,17 +527,17 @@ $scan-next-byte:loop: # . check whether to return 75/jump-if-not-equal $scan-next-byte:end/disp8 $scan-next-byte:check1: - # if EAX == ' ' continue + # if (EAX == ' ') continue 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x20/imm32 # compare EAX 74/jump-if-equal $scan-next-byte:loop/disp8 - # if EAX == '\t' continue + # if (EAX == '\t') continue 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x9/imm32 # compare EAX 74/jump-if-equal $scan-next-byte:loop/disp8 - # if EAX == '\n' continue + # if (EAX == '\n') continue 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX 74/jump-if-equal $scan-next-byte:loop/disp8 $scan-next-byte:check2: - # if EAX == '#' skip-until-newline(in) + # if (EAX == '#') skip-until-newline(in) 3d/compare-with-EAX 0x23/imm32 75/jump-if-not-equal $scan-next-byte:check3/disp8 # . skip-until-newline(in) @@ -1413,8 +1413,8 @@ skip-until-newline: # in : (address buffered-file) -> # push EAX # repeatedly: # EAX = read-byte(in) - # if EAX == 0xffffffff break - # if EAX == 0x0a break + # if (EAX == 0xffffffff) break + # if (EAX == 0x0a) break # pop EAX # . prolog 55/push-EBP @@ -1429,10 +1429,10 @@ $skip-until-newline:loop: e8/call read-byte/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # . if EAX == 0xffffffff break + # . if (EAX == 0xffffffff) break 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX 74/jump-if-equal $skip-until-newline:end/disp8 - # . if EAX != 0xa/newline loop + # . if (EAX != 0xa/newline) loop 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX 75/jump-if-not-equal $skip-until-newline:loop/disp8 $skip-until-newline:end: diff --git a/subx/apps/pack b/subx/apps/pack index 075dc69b0daf680ae14858b285e35678211d40d9..e55b170ad3c46c25e8bca1648c0fae3b0cb5e549 100755 GIT binary patch literal 20763 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 1 and argv[1] == "test" then return run_tests() + # - if argc > 1 and argv[1] == "test", then return run_tests() # . argc > 1 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 7e/jump-if-lesser-or-equal $run-main/disp8 @@ -88,7 +88,7 @@ convert: # in : (address buffered-file), out : (address buffered-file) -> # pseudocode: # word-slice = next-word - # if *word-slice->start == '#' + # if (*word-slice->start == '#') # write-stream-buffered(out, line) # return - # if starts-with(word-slice, '==') + # if (starts-with(word-slice, '==')) # write-stream-buffered(out, line) # return # @@ -599,7 +599,7 @@ next-word: # line : (address stream byte), out : (address slice) 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/EAX 0xc/disp8 . # copy ESI+ECX+12 to EAX 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI - # if line->data[line->read] == '#': out->end = &line->data[line->write]), skip rest of stream and return + # if (line->data[line->read] == '#') out->end = &line->data[line->write]), skip rest of stream and return # . EAX = line->data[line->read] 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/AL 0xc/disp8 . # copy byte at *(ESI+ECX+12) to AL @@ -770,8 +770,8 @@ has-metadata?: # word : (address slice), s : (address string) -> EAX : boolean # curr = twig->end # while true: # twig = next-token-from-slice(curr, word->end, '/') - # if twig.empty() break - # if slice-equal?(twig, s) return true + # if (twig.empty()) break + # if (slice-equal?(twig, s)) return true # curr = twig->end # return false # . prolog @@ -813,7 +813,7 @@ $has-metadata?:loop: e8/call next-token-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - # if slice-empty?(twig) return false + # if (slice-empty?(twig)) return false # . EAX = slice-empty?(twig) # . . push args 57/push-EDI @@ -824,7 +824,7 @@ $has-metadata?:loop: # . if (EAX != 0) return false 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX 75/compare-if-not-equal $has-metadata?:false/disp8 - # if slice-equal?(twig, s) return true + # if (slice-equal?(twig, s)) return true # . EAX = slice-equal?(twig, s) # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) @@ -1058,7 +1058,7 @@ emit: # out : (address buffered-file), word : (address slice), width : int e8/call next-token-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - # if !is-hex-int?(name) write-slice(out, word) and return + # if (!is-hex-int?(name)) write-slice(out, word) and return # . is-hex-int?(name) # . . push args 57/push-EDI @@ -1066,7 +1066,7 @@ emit: # out : (address buffered-file), word : (address slice), width : int e8/call is-hex-int?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # . if EAX == 0 + # . if (EAX == 0) 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX 75/jump-if-not-equal $emit:hex-int/disp8 # . write-slice(out, word) diff --git a/subx/examples/ex10.subx b/subx/examples/ex10.subx index 3ae1eae7..07b5b4bb 100644 --- a/subx/examples/ex10.subx +++ b/subx/examples/ex10.subx @@ -38,7 +38,6 @@ argv-equal: # (s1, s2) : null-terminated ascii strings -> EAX : boolean # initialize s1 (ECX) and s2 (EDX) 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX 4/disp8 . # copy *(ESP+4) to ECX 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 2/r32/EDX 8/disp8 . # copy *(ESP+8) to EDX - # while (true) $argv-equal:loop: # c1/EAX, c2/EBX = *s1, *s2 b8/copy-to-EAX 0/imm32 diff --git a/subx/examples/ex11 b/subx/examples/ex11 index cdabbf0ab16d318c8a75dd18c710f7c5160e6a7a..0ffafb6f8b170dd2535643bc7a716c3529cac187 100755 GIT binary patch delta 390 zcmcc1ah+p=i>xsd0|N-NG5~=90|O(FS`Op`G1u~mi6V?#6U($zcYtJfg9yuuwIW^Y zU2?V{PKl)DjZ#rZcemFsy4Yd+RT*1Bf*^wfUho5{ z#v?pH_Th}TaJA_OwO>GjKxv@b$3POM)_@r(ycT4xHA1a9NDyM~c8FSOAayt+3$Bqe-R0|^2Z b0nKHHsGTgvB*GXpS({0LartH+CP5|uqq=R> delta 404 zcmcc4ahGF)i>xIR0|N-NG5~=90|O(FS_|X@G1uCOi6V>w6U(&fEiabH?EtChV&4s> z=)!zLFw{jgqZ9J0Nhj6tU5o(_!)EYz7N&~6G f88R#|_q8Gvt4#jSsLB{IS(QnFaqVU|CP5|uGg5RF diff --git a/subx/examples/ex11.subx b/subx/examples/ex11.subx index 7fb83eb6..49e0c753 100644 --- a/subx/examples/ex11.subx +++ b/subx/examples/ex11.subx @@ -28,7 +28,28 @@ # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array # reason for the name: the only place we should have null-terminated ascii strings is from commandline args -kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean +kernel-string-equal?: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean + # pseudocode: + # n = benchmark->length + # s1 = s + # s2 = benchmark->data + # i = 0 + # while (i < n) + # c1 = *s1 + # c2 = *s2 + # if (c1 == 0) return false + # if (c1 != c2) return false + # ++s1, ++s2, ++i + # return *s1 == 0 + # + # registers: + # i: ECX + # n: EDX + # s1: EDI + # s2: ESI + # c1: EAX + # c2: EBX + # # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP @@ -38,72 +59,57 @@ kernel-string-equal: # s : null-terminated ascii string, benchmark : length-pre 53/push-EBX 56/push-ESI 57/push-EDI - - # pseudocode: - # initialize n = b->length - # initialize s1 = s - # initialize s2 = b->data - # i = 0 - # for (i = 0; i < n; ++n) - # c1 = *s1 - # c2 = *s2 - # if c1 == 0 - # return false - # if c1 != c2 - # return false - # return *s1 == 0 - # initialize s into EDI + # s1/EDI = s 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI - # initialize benchmark length n into EDX + # n/EDX = benchmark->length 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX 8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX - # initialize benchmark data into ESI + # s2/ESI = benchmark->data 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI 81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 4/imm32 # add to ESI - # initialize loop counter i into ECX + # i/ECX = c1/EAX = c2/EBX = 0 b9/copy-to-ECX 0/imm32/exit - # while (i/ECX < n/EDX) -$kernel-string-equal:loop: - 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX - 74/jump-if-equal $kernel-string-equal:break/disp8 - # c1/EAX, c2/EBX = *s, *benchmark b8/copy-to-EAX 0/imm32 - 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX bb/copy-to-EBX 0/imm32 +$kernel-string-equal?:loop: + # if (i >= n) break + 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX + 7d/jump-if-greater-or-equal $kernel-string-equal?:break/disp8 + # c1 = *s1 + 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX + # c2 = *s2 8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX # if (c1 == 0) return false 3d/compare-EAX 0/imm32 - 74/jump-if-equal $kernel-string-equal:false/disp8 + 74/jump-if-equal $kernel-string-equal?:false/disp8 # if (c1 != c2) return false 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX - 75/jump-if-not-equal $kernel-string-equal:false/disp8 - # ++s1, ++s2, ++i + 75/jump-if-not-equal $kernel-string-equal?:false/disp8 + # ++i 41/inc-ECX - 46/inc-ESI + # ++s1 47/inc-EDI - # end while - eb/jump $kernel-string-equal:loop/disp8 -$kernel-string-equal:break: - # if (*s/EDI == 0) return true - b8/copy-to-EAX 0/imm32 + # ++s2 + 46/inc-ESI + eb/jump $kernel-string-equal?:loop/disp8 +$kernel-string-equal?:break: + # return *s1 == 0 8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX - 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX - 75/jump-if-not-equal $kernel-string-equal:false/disp8 + 3d/compare-EAX 0/imm32 + 75/jump-if-not-equal $kernel-string-equal?:false/disp8 +$kernel-string-equal?:true: b8/copy-to-EAX 1/imm32 -$kernel-string-equal:true: - eb/jump $kernel-string-equal:end/disp8 - # return false -$kernel-string-equal:false: + eb/jump $kernel-string-equal?:end/disp8 +$kernel-string-equal?:false: b8/copy-to-EAX 0/imm32 - -$kernel-string-equal:end: +$kernel-string-equal?:end: # . restore registers 5f/pop-to-EDI 5e/pop-to-ESI 5b/pop-to-EBX 5a/pop-to-EDX 59/pop-to-ECX - # end + # . epilog 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 5d/pop-to-EBP c3/return @@ -111,12 +117,12 @@ $kernel-string-equal:end: # - tests test-compare-null-kernel-string-with-empty-array: - # EAX = kernel-string-equal(Null-kernel-string, "") + # EAX = kernel-string-equal?(Null-kernel-string, "") # . . push args 68/push ""/imm32 68/push Null-kernel-string/imm32 # . . call - e8/call kernel-string-equal/disp32 + e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # check-ints-equal(EAX, 1, msg) @@ -131,12 +137,12 @@ test-compare-null-kernel-string-with-empty-array: c3/return test-compare-null-kernel-string-with-non-empty-array: - # EAX = kernel-string-equal(Null-kernel-string, "Abc") + # EAX = kernel-string-equal?(Null-kernel-string, "Abc") # . . push args 68/push "Abc"/imm32 68/push Null-kernel-string/imm32 # . . call - e8/call kernel-string-equal/disp32 + e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # check-ints-equal(EAX, 0, msg) @@ -151,12 +157,12 @@ test-compare-null-kernel-string-with-non-empty-array: c3/return test-compare-kernel-string-with-equal-array: - # EAX = kernel-string-equal(Abc-kernel-string, "Abc") + # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Abc") # . . push args 68/push "Abc"/imm32 - 68/push Abc-kernel-string/imm32 + 68/push _test-Abc-kernel-string/imm32 # . . call - e8/call kernel-string-equal/disp32 + e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # check-ints-equal(EAX, 1, msg) @@ -171,12 +177,12 @@ test-compare-kernel-string-with-equal-array: c3/return test-compare-kernel-string-with-inequal-array: - # EAX = kernel-string-equal(Abc-kernel-string, "Adc") + # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Adc") # . . push args 68/push "Adc"/imm32 - 68/push Abc-kernel-string/imm32 + 68/push _test-Abc-kernel-string/imm32 # . . call - e8/call kernel-string-equal/disp32 + e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # check-ints-equal(EAX, 0, msg) @@ -191,12 +197,12 @@ test-compare-kernel-string-with-inequal-array: c3/return test-compare-kernel-string-with-empty-array: - # EAX = kernel-string-equal(Abc-kernel-string, "") + # EAX = kernel-string-equal?(_test-Abc-kernel-string, "") # . . push args 68/push ""/imm32 - 68/push Abc-kernel-string/imm32 + 68/push _test-Abc-kernel-string/imm32 # . . call - e8/call kernel-string-equal/disp32 + e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # check-ints-equal(EAX, 0, msg) @@ -211,12 +217,12 @@ test-compare-kernel-string-with-empty-array: c3/return test-compare-kernel-string-with-shorter-array: - # EAX = kernel-string-equal(Abc-kernel-string, "Ab") + # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Ab") # . . push args 68/push "Ab"/imm32 - 68/push Abc-kernel-string/imm32 + 68/push _test-Abc-kernel-string/imm32 # . . call - e8/call kernel-string-equal/disp32 + e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # check-ints-equal(EAX, 0, msg) @@ -231,12 +237,12 @@ test-compare-kernel-string-with-shorter-array: c3/return test-compare-kernel-string-with-longer-array: - # EAX = kernel-string-equal(Abc-kernel-string, "Abcd") + # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Abcd") # . . push args 68/push "Abcd"/imm32 - 68/push Abc-kernel-string/imm32 + 68/push _test-Abc-kernel-string/imm32 # . . call - e8/call kernel-string-equal/disp32 + e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # check-ints-equal(EAX, 0, msg) @@ -263,7 +269,7 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean # load args into EAX, EBX and ECX 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX - # if EAX == b/EBX print('.') and return + # if (EAX == b/EBX) print('.') and return 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX 75/jump-if-unequal $check-ints-equal:else/disp8 # . write-stderr('.') @@ -344,7 +350,8 @@ Newline: # for kernel-string-equal tests Null-kernel-string: 00/null -Abc-kernel-string: + +_test-Abc-kernel-string: 41/A 62/b 63/c 00/null # . . vim:nowrap:textwidth=0 diff --git a/subx/examples/ex3.subx b/subx/examples/ex3.subx index ceeaef00..6a4f7b01 100644 --- a/subx/examples/ex3.subx +++ b/subx/examples/ex3.subx @@ -18,7 +18,7 @@ b9/copy-to-ECX 1/imm32 $loop: - # while (counter <= 10) + # if (counter > 10) break 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0xa/imm32 # compare ECX 7f/jump-if-greater $exit/disp8 # result += counter diff --git a/subx/examples/ex8.subx b/subx/examples/ex8.subx index 0ae75760..f45813ec 100644 --- a/subx/examples/ex8.subx +++ b/subx/examples/ex8.subx @@ -42,7 +42,7 @@ ascii-length: # s : (address array byte) -> n/EAX $ascii-length-loop: # var c/ECX = *s 8a/copy 0/mod/* 2/rm32/EDX . . . 1/r32/ECX . . # copy byte at *EDX to lower byte of ECX - # if c == '\0' break + # if (c == '\0') break 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX 74/jump-if-equal $ascii-length-ret/disp8 # ++s diff --git a/subx/opcodes b/subx/opcodes index 3437f30a..0eb0792b 100644 --- a/subx/opcodes +++ b/subx/opcodes @@ -74,6 +74,7 @@ Opcodes currently supported by SubX: bf: copy imm32 to EDI (mov) c1: shift rm32 by imm8 bits depending on subop (sal/sar/shl/shr) c3: return from most recent unfinished call (ret) + c6: copy imm8 to r8/m8-at-r32 (mov) c7: copy imm32 to rm32 (mov) cd: software interrupt (int) d3: shift rm32 by CL bits depending on subop (sal/sar/shl/shr)