diff --git a/050_write.subx b/050_write.subx index 4a48e825..13f3cddf 100644 --- a/050_write.subx +++ b/050_write.subx @@ -11,6 +11,26 @@ Entry: # just exit; can't test _write just yet b8/copy-to-eax 1/imm32/exit cd/syscall 0x80/imm8 +# Since this is the first file of SubX code, a note about type comments. +# Eventually we'll build a slightly higher-level safe language atop SubX. +# Even though we don't have the safe language yet, we'll start thinking in +# terms of the higher-level types in comments. +# +# Mu will have two kinds of addresses: +# - 'ref' which is used to point to a unique element, because machine +# code can't store large types in registers. +# - 'handle' which can point to a heap allocation, different heap allocations +# at different times, or even at times nothing at all. +# +# The type 'address' can be obtained from either a ref or handle, but it can +# only be stored on the stack (say to pass objects by reference). +# Conversely, a ref can't be copied into another ref, only to an address (which +# by construction has a shorter lifetime). +# +# Beginnings of a lattice of types: +# You can convert a ref or handle to an address, but not the other way around. +# You can convert addresses to ints, but not the other way around. + _write: # fd : int, s : (address array byte) # . prologue 55/push-ebp diff --git a/051test.subx b/051test.subx index 846e6cee..ac0f32a5 100644 --- a/051test.subx +++ b/051test.subx @@ -80,26 +80,26 @@ $check-ints-equal:end: # length-prefixed string containing just a single newline # convenient to have when printing messages and so on -Newline: - # size +Newline: # (ref array byte) + # size : int 1/imm32 # data 0a/newline # every test failure increments this counter -Num-test-failures: +Num-test-failures: # int 0/imm32 # length-prefixed string containing just a single space -Space: - # size +Space: # (ref array byte) + # size : int 1/imm32 # data 20/space # length-prefixed string containing just a single slash -Slash: - # size +Slash: # (ref array byte) + # size : int 1/imm32 # data 2f/slash diff --git a/052kernel-string-equal.subx b/052kernel-string-equal.subx index 357591e1..57b5b1ec 100644 --- a/052kernel-string-equal.subx +++ b/052kernel-string-equal.subx @@ -1,9 +1,11 @@ # Checking null-terminated ascii strings. # -# By default we create strings with a 4-byte length prefix rather than a null suffix. -# However we still need null-prefixed strings when interacting with the Linux -# kernel in a few places. This layer implements a function for comparing -# a null-terminated 'kernel string' with a length-prefixed 'SubX string'. +# By default we create strings as arrays of bytes, and all arrays have a 4-byte +# length prefix. +# +# However, we sometimes need to deal with null-prefixed strings when interacting +# with the Linux kernel. This layer implements a function for comparing a +# null-terminated 'kernel string' with a length-prefixed 'SubX string'. # # To run (from the subx directory): # $ ./subx translate 05[0-2]*.subx -o /tmp/tmp52 @@ -28,7 +30,7 @@ Entry: # run all tests # 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 : (address kernel-string), benchmark : (address array byte) -> eax : boolean # pseudocode: # n = benchmark->length # s1 = s @@ -59,17 +61,19 @@ kernel-string-equal?: # s : null-terminated ascii string, benchmark : length-pr 53/push-ebx 56/push-esi 57/push-edi - # s1/edi = s + # var s1/edi : (address byte) = s 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi - # n/edx = benchmark->length + # var n/edx : int = 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 - # s2/esi = benchmark->data + # var s2/esi : (address byte) = 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 - # i/ecx = c1/eax = c2/ebx = 0 + # var i/ecx : int = 0 b9/copy-to-ecx 0/imm32/exit + # var c1/eax : byte = 0 b8/copy-to-eax 0/imm32 + # var c2/ebx : byte = 0 bb/copy-to-ebx 0/imm32 $kernel-string-equal?:loop: # if (i >= n) break @@ -258,10 +262,10 @@ test-compare-kernel-string-with-longer-array: == data -Null-kernel-string: +Null-kernel-string: # (address kernel-string) 00/null -_test-Abc-kernel-string: +_test-Abc-kernel-string: # (address kernel-string) 41/A 62/b 63/c 00/null # . . vim:nowrap:textwidth=0 diff --git a/053new-segment.subx b/053new-segment.subx index 719413ab..ba2487d5 100644 --- a/053new-segment.subx +++ b/053new-segment.subx @@ -17,7 +17,7 @@ # . 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 Entry: # manual test - # var ad/ecx : (address allocation-descriptor) = {0, 0} + # var ad/ecx : (ref allocation-descriptor) 68/push 0/imm32/limit 68/push 0/imm32/curr 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -29,7 +29,7 @@ Entry: # manual test e8/call new-segment/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # eax = ad->curr + # var eax : (address _) = ad->curr 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax # write to *eax to check that we have access to the newly-allocated segment c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0x34/imm32 # copy to *eax @@ -38,7 +38,7 @@ Entry: # manual test b8/copy-to-eax 1/imm32/exit cd/syscall 0x80/imm8 -new-segment: # len : int, ad : (address allocation-descriptor) +new-segment: # len : int, ad : (ref allocation-descriptor) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -72,7 +72,7 @@ $new-segment:end: == data # various constants used here were found in the Linux sources (search for file mman-common.h) -_mmap-new-segment: # type mmap_arg_struct +_mmap-new-segment: # (ref mmap_arg_struct) # addr 0/imm32 $_mmap-new-segment:len: diff --git a/054string-equal.subx b/054string-equal.subx index 484844d9..c63688a1 100644 --- a/054string-equal.subx +++ b/054string-equal.subx @@ -13,12 +13,12 @@ Entry: # run all tests b8/copy-to-eax 1/imm32/exit cd/syscall 0x80/imm8 -string-equal?: # s : (address string), benchmark : (address string) -> eax : boolean +string-equal?: # s : (address array byte), benchmark : (address array byte) -> eax : boolean # pseudocode: # if (s->length != benchmark->length) return false # currs = s->data # currb = benchmark->data - # maxs = s->data + s->length + # maxs = &s->data[s->length] # while currs < maxs # c1 = *currs # c2 = *currb @@ -51,14 +51,15 @@ $string-equal?:lengths: # if (ecx != benchmark->length) return false 39/compare 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # compare *edi and ecx 75/jump-if-not-equal $string-equal?:false/disp8 - # currs/esi = s->data + # var currs/esi : (address byte) = s->data 81 0/subop/add 3/mod/direct 6/rm32/esi . . . . . 4/imm32 # add to esi - # maxs/ecx = s->data + s->length + # var maxs/ecx : (address byte) = &s->data[s->length] 01/add 3/mod/direct 1/rm32/ecx . . . 6/r32/esi . . # add esi to ecx - # currb/edi = benchmark->data + # var currb/edi : (address byte) = benchmark->data 81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi - # c1/eax = c2/edx = 0 + # var c1/eax : byte = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + # var c2/edx : byte = 0 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx $string-equal?:loop: # if (currs >= maxs) return true @@ -175,13 +176,13 @@ test-compare-inequal-strings-equal-lengths: c3/return # helper for later tests -check-strings-equal: # s : (address string), expected : (address string), msg : (address string) +check-strings-equal: # s : (address array byte), expected : (address array byte), msg : (address array byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 50/push-eax - # eax = string-equal?(s, expected) + # var eax : boolean = string-equal?(s, expected) # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) diff --git a/055stream.subx b/055stream.subx index c60be1d5..6568602a 100644 --- a/055stream.subx +++ b/055stream.subx @@ -3,7 +3,7 @@ # A stream looks like this: # write : int # index at which writes go # read : int # index that we've read until -# data : (array byte) # prefixed by length as usual +# data : (ref array byte) # prefixed by length as usual # # some primitives for operating on streams: # - clear-stream (clears everything but the data length) @@ -14,7 +14,7 @@ # . 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 -clear-stream: # f : (address stream) +clear-stream: # f : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -23,23 +23,23 @@ clear-stream: # f : (address stream) 51/push-ecx # eax = f 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax - # ecx = f->length + # var count/ecx : int = f->length 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 8/disp8 . # copy *(eax+8) to ecx - # ecx = &f->data[f->length] + # var max/ecx : (address byte) = &f->data[f->length] 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 0xc/disp8 . # copy eax+ecx+12 to ecx # f->write = 0 c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0/imm32 # copy to *eax # f->read = 0 c7 0/subop/copy 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 0/imm32 # copy to *(eax+4) - # eax = f->data + # var curr/eax : (address byte) = f->data 81 0/subop/add 3/mod/direct 0/rm32/eax . . . . . 0xc/imm32 # add to eax $clear-stream:loop: - # if (eax >= ecx) break + # if (curr >= max) break 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 73/jump-if-greater-or-equal-unsigned $clear-stream:end/disp8 - # *eax = 0 + # *curr = 0 c6 0/subop/copy-byte 0/mod/direct 0/rm32/eax . . . . . 0/imm8 # copy byte to *eax - # ++eax + # ++curr 40/increment-eax eb/jump $clear-stream:loop/disp8 $clear-stream:end: @@ -51,7 +51,7 @@ $clear-stream:end: 5d/pop-to-ebp c3/return -rewind-stream: # f : (address stream) +rewind-stream: # f : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp diff --git a/056trace.subx b/056trace.subx index 2bcdde1e..0a09bd4f 100644 --- a/056trace.subx +++ b/056trace.subx @@ -14,9 +14,9 @@ == data -# We'll save the address of the trace segment here. -Trace-stream: +Trace-stream: # (handle stream byte) 0/imm32 + # we don't have safe handles (fat pointers) yet Trace-segment: 0/imm32/curr @@ -24,7 +24,7 @@ Trace-segment: # Fake trace-stream for tests. # Also illustrates the layout of the real trace-stream (segment). -_test-trace-stream: +_test-trace-stream: # (ref stream byte) # current write index 0/imm32 # current read index @@ -60,7 +60,7 @@ initialize-trace-stream: # n : int 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # copy Trace-segment->curr to *Trace-stream 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Trace-segment/disp32 # copy *Trace-segment to eax - # watch point to catch Trace-stream leaks +#? # watch point to catch Trace-stream leaks #? $watch-1: 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Trace-stream/disp32 # copy eax to *Trace-stream # Trace-stream->length = n - 12 @@ -79,7 +79,7 @@ $initialize-trace-stream:end: # Append a string to the given trace stream. # Silently give up if it's already full. Or truncate the string if there isn't enough room. -trace: # line : (address string) +trace: # line : (address array byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -90,13 +90,13 @@ trace: # line : (address string) 53/push-ebx 56/push-esi 57/push-edi - # edi = *Trace-stream + # var edi : (address stream byte) = *Trace-stream 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 7/r32/edi Trace-stream/disp32 # copy *Trace-stream to edi # esi = line 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # ecx = t->write + # var ecx : int = t->write 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx - # edx = t->length + # var edx : int = t->length 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # copy *(edi+8) to edx # eax = _append-3(&t->data[t->write], &t->data[t->length], line) # . . push line @@ -302,7 +302,7 @@ $check-trace-scans-to:end: c3/return # Start scanning from Trace-stream->read for 'line'. If found, update Trace-stream->read and return true. -trace-scan: # line : (address string) -> result/eax : boolean +trace-scan: # line : (address array byte) -> result/eax : boolean # pseudocode: # push Trace-stream->read # while true: @@ -340,8 +340,8 @@ $trace-scan:loop: e8/call next-line-matches?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # if (eax == 0) continue - 3d/compare-eax-and 0/imm32 + # if (eax == false) continue + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $trace-scan:continue/disp8 $trace-scan:true: # skip-next-line(Trace-stream) @@ -554,7 +554,7 @@ test-trace-scan-failure-leaves-read-index-untouched: # . end c3/return -next-line-matches?: # t : (address stream), line : (address string) -> result/eax : boolean +next-line-matches?: # t : (address stream byte), line : (address array byte) -> result/eax : boolean # pseudocode: # while true: # if (currl >= maxl) break @@ -575,58 +575,58 @@ next-line-matches?: # t : (address stream), line : (address string) -> result/e 57/push-edi # edx = line 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx - # currl/esi = line->data + # var currl/esi : (address byte) = line->data # . esi = line/edx->data 8d/copy-address 1/mod/*+disp8 2/rm32/edx . . . 6/r32/esi 4/disp8 . # copy edx+4 to esi - # maxl/ecx = line->data + line->size + # var maxl/ecx : (address byte) = &line->data[line->size] # . eax = line/edx->size 8b/copy 0/mod/indirect 2/rm32/edx . . 0/r32/eax . . # copy *edx to eax - # . maxl/ecx = line->data/esi + line->size/eax + # . maxl = &line->data[line->size] 8d/copy-address 0/mod/indirect 4/rm32/sib 6/base/esi 0/index/eax . 1/r32/ecx . . # copy edx+eax to ecx # edi = t 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi - # ebx = t->data + # var ebx : (address byte) = t->data 8d/copy-address 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 0xc/disp8 . # copy edi+12 to ebx - # maxt/edx = t->data + t->write + # var maxt/edx : (address byte) = &t->data[t->write] # . eax = t->write 8b/copy 0/mod/indirect 7/rm32/edi . . 0/r32/eax . . # copy *edi to eax - # . maxt/edx = t->data/ebx + t->write/eax + # . maxt = &t->data[t->write] 8d/copy-address 0/mod/indirect 4/rm32/sib 3/base/ebx 0/index/eax . 2/r32/edx . . # copy ebx+eax to edx - # currt/edi = t->data + t->read + # var currt/edi : (address byte) = &t->data[t->read] # . eax = t/edi->read 8b/copy 1/mod/*+disp8 7/rm32/edi . . 0/r32/eax 4/disp8 . # copy *(edi+4) to eax - # . currt/edi = t->data/ebx + t->read/eax + # . currt = &t->data[t->read] 8d/copy-address 0/mod/indirect 4/rm32/sib 3/base/ebx 0/index/eax . 7/r32/edi . . # copy ebx+eax to edi $next-line-matches?:loop: - # if (currl/esi >= maxl/ecx) break + # if (currl >= maxl) break 39/compare 3/mod/direct 6/rm32/esi . . . 1/r32/ecx . . # compare esi and ecx 73/jump-if-greater-or-equal-unsigned $next-line-matches?:break/disp8 - # if (currt/edi >= maxt/edx) return false + # if (currt >= maxt) return false # . eax = false b8/copy-to-eax 0/imm32/false 39/compare 3/mod/direct 7/rm32/edi . . . 2/r32/edx . . # compare edi and edx 73/jump-if-greater-or-equal-unsigned $next-line-matches?:end/disp8 - # if (*currt/edi != *currl/esi) return false + # if (*currt != *currl) return false 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 31/xor 3/mod/direct 3/rm32/eax . . . 3/r32/eax . . # clear ebx - # . eax = (char) *currt/edi + # . eax : byte = *currt 8a/copy-byte 0/mod/indirect 7/rm32/edi . . 0/r32/eax . . # copy *edi to eax - # . ebx = (char) *currl/esi + # . ebx : byte = *currl 8a/copy-byte 0/mod/indirect 6/rm32/esi . . 3/r32/ebx . . # copy *esi to ebx # . eax >= ebx 39/compare 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # compare eax and ebx # . eax = false b8/copy-to-eax 0/imm32/false 75/jump-if-not-equal $next-line-matches?:end/disp8 - # ++currt/edi + # ++currt 47/increment-edi - # ++currl/esi + # ++currl 46/increment-esi eb/jump $next-line-matches?:loop/disp8 $next-line-matches?:break: # return *currt == '\n' 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - # . eax = (char) *currt + # . eax : byte = *currt 8a/copy-byte 0/mod/indirect 7/rm32/edi . . 0/r32/eax . . # copy *edi to eax 3d/compare-eax-and 0xa/imm32/newline # . eax = false @@ -730,11 +730,11 @@ test-next-line-matches?-match: c3/return # move t->read to _after_ next newline -skip-next-line: # t : (address stream) +skip-next-line: # t : (address stream byte) # pseudocode: - # max = t->data + t->write + # max = &t->data[t->write] # i = t->read - # curr = t->data + t->read + # curr = &t->data[t->read] # while true # if (curr >= max) break # ++i @@ -752,37 +752,37 @@ skip-next-line: # t : (address stream) 53/push-ebx # ecx = t 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx - # edx = t/ecx->data + # edx = t->data 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 0xc/disp8 . # copy ecx+12 to edx - # eax = t/ecx->write + # eax = t->write 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax - # max/ebx = t->data/edx + t->write/eax + # var max/ebx : (address byte) = &t->data[t->write] 8d/copy-address 0/mod/indirect 4/rm32/sib 2/base/edx 0/index/eax . 3/r32/ebx . . # copy edx+eax to ebx - # eax = t/ecx->read + # eax = t->read 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to edx - # curr/ecx = t->data/edx + t->read/eax + # var curr/ecx : (address byte) = &t->data[t->read] 8d/copy-address 0/mod/indirect 4/rm32/sib 2/base/edx 0/index/eax . 1/r32/ecx . . # copy edx+eax to ecx - # i/edx = eax + # var i/edx : int = t->read 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx $skip-next-line:loop: - # if (curr/ecx >= max/ebx) break + # if (curr >= max) break 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx and ebx 73/jump-if-greater-or-equal-unsigned $skip-next-line:end/disp8 - # ++i/edx + # ++i 42/increment-edx - # if (*curr/ecx == '\n') break + # if (*curr == '\n') break 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax 3d/compare-eax-and 0a/imm32/newline 74/jump-if-equal $skip-next-line:end/disp8 - # ++curr/ecx + # ++curr 41/increment-ecx # loop eb/jump $skip-next-line:loop/disp8 $skip-next-line:end: # ecx = t 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx - # t/ecx->read = i/edx + # t->read = i 89/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy edx to *(ecx+4) # . restore registers 5b/pop-to-ebx @@ -858,7 +858,7 @@ $clear-trace-stream:end: # - helpers # 3-argument variant of _append -_append-3: # out : address, outend : address, s : (array byte) -> num_bytes_appended/eax +_append-3: # out : (address byte), outend : (address byte), s : (address array byte) -> num_bytes_appended/eax # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -890,7 +890,7 @@ $_append-3:end: c3/return # 4-argument variant of _append -_append-4: # out : address, outend : address, in : address, inend : address -> num_bytes_appended/eax +_append-4: # out : (address byte), outend : (address byte), in : (address byte), inend : (address byte) -> num_bytes_appended/eax : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -900,7 +900,7 @@ _append-4: # out : address, outend : address, in : address, inend : address -> 53/push-ebx 56/push-esi 57/push-edi - # eax/num_bytes_appended = 0 + # num_bytes_appended = 0 b8/copy-to-eax 0/imm32 # edi = out 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi @@ -956,7 +956,7 @@ $_append-4:abort: == data -_test-stream-line-ABABA: +_test-stream-line-ABABA: # (ref stream byte) # write 8/imm32 # read @@ -966,7 +966,7 @@ _test-stream-line-ABABA: # data 41 42 41 42 41 0a 00 00 # 8 bytes -_test-stream-empty: +_test-stream-empty: # (ref stream byte) # write 0/imm32 # read @@ -976,7 +976,7 @@ _test-stream-empty: # data 00 00 00 00 00 00 00 00 # 8 bytes -_test-stream-filled: +_test-stream-filled: # (ref stream byte) # write 8/imm32 # read diff --git a/057write.subx b/057write.subx index b1ec1688..db3cb5cc 100644 --- a/057write.subx +++ b/057write.subx @@ -21,7 +21,7 @@ # . 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 # TODO: come up with a way to signal when a write to disk fails -write: # f : fd or (address stream), s : (address array byte) +write: # f : fd or (address stream byte), s : (address array byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -145,7 +145,7 @@ test-write-appends: == data -_test-stream: +_test-stream: # (ref stream byte) # current write index 0/imm32 # current read index diff --git a/058stream-equal.subx b/058stream-equal.subx index 25330a52..bc3bc4d0 100644 --- a/058stream-equal.subx +++ b/058stream-equal.subx @@ -6,7 +6,7 @@ # . 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 # compare all the data in a stream (ignoring the read pointer) -stream-data-equal?: # f : (address stream), s : (address string) -> eax : boolean +stream-data-equal?: # f : (address stream byte), s : (address array byte) -> eax : boolean # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -19,20 +19,21 @@ stream-data-equal?: # f : (address stream), s : (address string) -> eax : boole 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi # eax = f->write 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax - # maxf/edx = f->data + f->write + # var maxf/edx : (address byte) = &f->data[f->write] 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 2/r32/edx 0xc/disp8 . # copy esi+eax+12 to edx - # currf/esi = f->data + # var currf/esi : (address byte) = f->data 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 $stream-data-equal?:compare-lengths: + # 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 + # var currs/edi : (address byte) = s->data 81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi - # eax = ecx = 0 + # var eax : byte = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + # var ecx : byte = 0 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx $stream-data-equal?:loop: # if (currf >= maxf) return true @@ -190,7 +191,7 @@ test-stream-data-equal-length-check: c3/return # helper for later tests -check-stream-equal: # f : (address stream), s : (address string), msg : (address string) +check-stream-equal: # f : (address stream byte), s : (address array byte), msg : (address array byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -226,7 +227,7 @@ $check-stream-equal:end: # on success, set f->read to after the next newline # on failure, leave f->read unmodified # this function is usually used only in tests, so we repeatedly write f->read -next-stream-line-equal?: # f : (address stream), s : (address string) -> eax : boolean +next-stream-line-equal?: # f : (address stream byte), s : (address array byte) -> eax : boolean # pseudocode: # currf = f->read # bound: f->write # currs = 0 # bound : s->length @@ -273,30 +274,31 @@ next-stream-line-equal?: # f : (address stream), s : (address string) -> eax : 57/push-edi # esi = f 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # currf/ecx = f->read + # var currf/ecx : int = f->read 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx # edi = s 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi - # currs/edx = 0 + # var currs/edx : int = 0 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx - # eax = ebx = 0 + # var c1/eax : byte = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + # var c2/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx $next-stream-line-equal?:loop: # if (currf >= f->write) break 3b/compare 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # compare ecx with *esi 7d/jump-if-greater-or-equal $next-stream-line-equal?:break/disp8 - # AL = *(f->data + f->read) + # c1 = f->data[f->read] 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 - # if (eax == '\n') break + # if (c1 == '\n') break 3d/compare-eax-and 0xa/imm32/newline 74/jump-if-equal $next-stream-line-equal?:break/disp8 # if (currs >= s->length) return false 3b/compare 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # compare edx with *edi 7d/jump-if-greater-or-equal $next-stream-line-equal?:false/disp8 - # BL = *(s->data + currs) + # c2 = s->data[currs] 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 2/index/edx . 3/r32/BL 4/disp8 . # copy byte at *(edi+edx+4) to BL - # if (eax != ebx) return false + # if (c1 != c2) return false 39/compare 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # compare eax and ebx 75/jump-if-not-equal $next-stream-line-equal?:false/disp8 # ++currf diff --git a/059stop.subx b/059stop.subx index 628c813d..7c1c776b 100644 --- a/059stop.subx +++ b/059stop.subx @@ -123,7 +123,7 @@ test-stop-skips-returns-on-exit: # Make room for an exit descriptor on the stack. That's almost always the # right place for it, available only as long as it's legal to use. Once this # containing function returns we'll need a new exit descriptor. - # var ed/eax : (address exit-descriptor) + # var ed/eax : (ref exit-descriptor) 68/push 0/imm32 68/push 0/imm32 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax diff --git a/060read.subx b/060read.subx index 1fe37da7..34658b7b 100644 --- a/060read.subx +++ b/060read.subx @@ -45,7 +45,7 @@ # . 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 -read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/eax +read: # f : fd or (address stream byte), s : (address stream byte) -> num-bytes-read/eax : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -191,12 +191,11 @@ $_buffer-4:end: 5d/pop-to-ebp c3/return - # idea: a clear-if-empty method on streams that clears only if f->read == f->write # Unclear how I'd use it, though. Callers seem to need the check anyway. # Maybe a better helper would be 'empty-stream?' -_read: # fd : int, s : (address stream) -> num-bytes-read/eax +_read: # fd : int, s : (address stream byte) -> num-bytes-read/eax : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -427,7 +426,7 @@ test-read-returns-0-on-end-of-file: == data -_test-tmp-stream: +_test-tmp-stream: # (ref stream byte) # current write index 0/imm32 # current read index diff --git a/061read-byte.subx b/061read-byte.subx index 4806a9f5..a90c05da 100644 --- a/061read-byte.subx +++ b/061read-byte.subx @@ -11,8 +11,8 @@ # The buffered file for standard input. Also illustrates the layout for # buffered-file: a pointer to the backing store, followed by a 'buffer' stream -Stdin: - # file descriptor or (address stream) +Stdin: # (ref buffered-file) + # file descriptor or (address stream byte) 0/imm32 # standard input $Stdin->buffer: # inlined fields for a stream @@ -73,8 +73,7 @@ read-byte-buffered: # f : (address buffered-file) -> byte-or-Eof/eax b8/copy-to-eax 0xffffffff/imm32/Eof eb/jump $read-byte-buffered:end/disp8 $read-byte-buffered:from-stream: - # read byte from stream - # AL = f->data[f->read] + # byte-or-Eof = f->data[f->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 0x10/disp8 . # copy byte at *(esi+ecx+16) to AL # ++f->read @@ -272,8 +271,8 @@ test-read-byte-buffered-refills-buffer: == data # a test buffered file for _test-stream -_test-buffered-file: - # file descriptor or (address stream) +_test-buffered-file: # (ref buffered-file) + # file descriptor or (address stream byte) _test-stream/imm32 $_test-buffered-file->buffer: # current write index @@ -285,7 +284,7 @@ $_test-buffered-file->buffer: # data 00 00 00 00 00 00 # 6 bytes -_test-input-stream: +_test-input-stream: # (ref stream byte) # current write index 0/imm32 # current read index @@ -311,8 +310,8 @@ _test-input-stream: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # a test buffered file for _test-input-stream -_test-input-buffered-file: - # file descriptor or (address stream) +_test-input-buffered-file: # (ref buffered-file) + # file descriptor or (address stream byte) _test-input-stream/imm32 $_test-input-buffered-file->buffer: # current write index diff --git a/062write-stream.subx b/062write-stream.subx index 12d3c7e2..2dab3fe8 100644 --- a/062write-stream.subx +++ b/062write-stream.subx @@ -15,7 +15,7 @@ #? b8/copy-to-eax 1/imm32/exit #? cd/syscall 0x80/imm8 -write-stream: # f : fd or (address stream), s : (address stream) +write-stream: # f : fd or (address stream byte), s : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -75,7 +75,7 @@ $write-stream:end: 5d/pop-to-ebp c3/return -_write-stream: # fd : int, s : (address stream) +_write-stream: # fd : int, s : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -242,7 +242,7 @@ test-write-stream-appends: == data -_test-stream2: +_test-stream2: # (ref stream byte) # current write index 4/imm32 # current read index diff --git a/063error.subx b/063error.subx index 1d77b3f0..bb1a8b71 100644 --- a/063error.subx +++ b/063error.subx @@ -6,7 +6,7 @@ # . 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(out, "Error: "+msg+"\n") then stop(ed, 1) -error: # ed : (address exit-descriptor), out : fd or (address stream), msg : (address array byte) +error: # ed : (address exit-descriptor), out : fd or (address stream byte), msg : (address array byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp diff --git a/064write-byte.subx b/064write-byte.subx index ec849c6d..2e7a36f3 100644 --- a/064write-byte.subx +++ b/064write-byte.subx @@ -7,8 +7,8 @@ == data # The buffered file for standard output. -Stdout: - # file descriptor or (address stream) +Stdout: # (ref buffered-file) + # file descriptor or (address stream byte) 1/imm32 # standard output $Stdout->buffer: # inlined fields for a stream @@ -205,7 +205,7 @@ test-write-byte-buffered-multiple-flushes: # - variant without buffering # Write lower byte of 'n' to 'f'. -append-byte: # f : (address stream), n : int +append-byte: # f : (address stream byte), n : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -283,7 +283,7 @@ test-append-byte-single: == data -_test-output-stream: +_test-output-stream: # (ref stream byte) # current write index 0/imm32 # current read index @@ -325,8 +325,8 @@ _test-output-stream: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # a test buffered file for _test-output-stream -_test-output-buffered-file: - # file descriptor or (address stream) +_test-output-buffered-file: # (ref buffered-file) + # file descriptor or (address stream byte) _test-output-stream/imm32 $_test-output-buffered-file->buffer: # current write index @@ -338,7 +338,7 @@ $_test-output-buffered-file->buffer: # data 00 00 00 00 00 00 # 6 bytes -_test-error-stream: +_test-error-stream: # (ref stream byte) # current write index 0/imm32 # current read index @@ -356,8 +356,8 @@ _test-error-stream: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # a test buffered file for _test-error-stream -_test-error-buffered-file: - # file descriptor or (address stream) +_test-error-buffered-file: # (ref buffered-file) + # file descriptor or (address stream byte) _test-error-stream/imm32 $_test-error-buffered-file->buffer: # current write index diff --git a/065write-buffered.subx b/065write-buffered.subx index bc829a51..8c7ae9c5 100644 --- a/065write-buffered.subx +++ b/065write-buffered.subx @@ -38,9 +38,9 @@ write-buffered: # f : (address buffered-file), msg : (address array byte) 57/push-edi # eax = msg 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax - # in/esi = msg->data + # var in/esi : (address byte) = msg->data 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 6/r32/esi 4/disp8 . # copy eax+4 to esi - # inend/ecx = &msg->data[msg->length] + # var inend/ecx : (address byte) = &msg->data[msg->length] 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 0/mod/indirect 4/rm32/sib 6/base/esi 1/index/ecx . 1/r32/ecx . . # copy esi+ecx to ecx # edi = f @@ -206,8 +206,8 @@ test-write-buffered-with-intermediate-flush: == data # The buffered file for standard error. -Stderr: - # file descriptor or (address stream) +Stderr: # (ref buffered-file) + # file descriptor or (address stream byte) 2/imm32 # standard error $Stderr->buffer: # inlined fields for a stream diff --git a/066print-int.subx b/066print-int.subx index cf043635..a1f968f7 100644 --- a/066print-int.subx +++ b/066print-int.subx @@ -5,7 +5,8 @@ # . 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 -to-hex-char: # in/eax : nibble -> out/eax : byte +# convert the lowest nibble of eax to ascii and return it in the lowest byte of eax +to-hex-char: # in/eax : int -> out/eax : int # no error checking; accepts argument in eax # if (eax <= 9) return eax + '0' 3d/compare-eax-with 0x9/imm32/9 @@ -17,7 +18,7 @@ $to-hex-char:else: 05/add-to-eax 0x57/imm32/a-10 c3/return -append-byte-hex: # f : (address stream), n : int +append-byte-hex: # f : (address stream byte), n : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -174,7 +175,7 @@ test-print-byte-buffered: # . end c3/return -print-int32: # f : (address stream), n : int +print-int32: # f : (address stream byte), n : int # pseudocode: # write(f, "0x") # ecx = 28 diff --git a/067parse-hex.subx b/067parse-hex.subx index b5694b8c..105943ca 100644 --- a/067parse-hex.subx +++ b/067parse-hex.subx @@ -18,7 +18,7 @@ is-hex-int?: # in : (address slice) -> eax : boolean 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # edx = s->end 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx - # curr/ecx = s->start + # var curr/ecx : (address byte) = s->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 1/r32/ecx . . # copy *ecx to ecx # if s is empty return false b8/copy-to-eax 0/imm32/false @@ -56,7 +56,7 @@ $is-hex-int?:loop: # if (curr >= in->end) return true 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-greater-or-equal-unsigned $is-hex-int?:true/disp8 - # eax = is-hex-digit?(*curr) + # var eax : boolean = is-hex-digit?(*curr) # . . push args 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 50/push-eax @@ -93,7 +93,7 @@ test-is-hex-int: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -127,7 +127,7 @@ test-is-hex-int-handles-letters: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -161,7 +161,7 @@ test-is-hex-int-with-trailing-char: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -195,7 +195,7 @@ test-is-hex-int-with-leading-char: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -224,7 +224,7 @@ test-is-hex-int-empty: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var slice/ecx = "" + # var slice/ecx : (ref slice) = "" 68/push 0/imm32 68/push 0/imm32 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -258,7 +258,7 @@ test-is-hex-int-handles-0x-prefix: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -292,7 +292,7 @@ test-is-hex-int-handles-negative: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -326,7 +326,7 @@ test-is-hex-int-handles-negative-0x-prefix: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -351,7 +351,7 @@ test-is-hex-int-handles-negative-0x-prefix: 5d/pop-to-ebp c3/return -parse-hex-int: # in : (address slice) -> result/eax +parse-hex-int: # in : (address slice) -> result/eax : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -360,18 +360,18 @@ parse-hex-int: # in : (address slice) -> result/eax 52/push-edx 53/push-ebx 56/push-esi - # result/ebx = 0 + # var result/ebx : int = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - # ecx = s + # ecx = in 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx - # edx = s->end + # edx = in->end 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx - # curr/ecx = s->start + # var curr/ecx : (address byte) = in->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 1/r32/ecx . . # copy *ecx to ecx - # negate?/esi = false + # var negate?/esi : boolean = false 31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi $parse-hex-int:negative: - # . if (*curr == '-') negate = true + # if (*curr == '-') ++curr, negate = true 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 3d/compare-eax-and 0x2d/imm32/- @@ -403,7 +403,7 @@ $parse-hex-int:loop: # if (curr >= in->end) break 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-greater-or-equal-unsigned $parse-hex-int:negate/disp8 - # eax = from-hex-char(*curr) + # var eax : int = from-hex-char(*curr) # . . copy arg to eax 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL # . . call @@ -416,10 +416,12 @@ $parse-hex-int:loop: # loop eb/jump $parse-hex-int:loop/disp8 $parse-hex-int:negate: - 81 7/subop/compare 3/mod/direct 6/rm32/esi . . . . . 0/imm32 # compare esi + # if (negate?) result = -result + 81 7/subop/compare 3/mod/direct 6/rm32/esi . . . . . 0/imm32/false # compare esi 74/jump-if-equal $parse-hex-int:end/disp8 f7 3/subop/negate 3/mod/direct 3/rm32/ebx . . . . . . # negate ebx $parse-hex-int:end: + # return result 89/copy 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # copy ebx to eax # . restore registers 5e/pop-to-esi @@ -440,7 +442,7 @@ test-parse-hex-int-single-digit: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -474,7 +476,7 @@ test-parse-hex-int-multi-digit: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -508,7 +510,7 @@ test-parse-hex-int-0x-prefix: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -542,7 +544,7 @@ test-parse-hex-int-zero: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -576,7 +578,7 @@ test-parse-hex-int-0-prefix: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -610,7 +612,7 @@ test-parse-hex-int-negative: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx diff --git a/068error-byte.subx b/068error-byte.subx index 5284c034..5490f890 100644 --- a/068error-byte.subx +++ b/068error-byte.subx @@ -6,7 +6,7 @@ # . 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 #? Entry: # manual test -#? # . var ed/eax : exit-descriptor +#? # . var ed/eax : (ref exit-descriptor) #? 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp #? 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax #? # . configure ed to really exit() @@ -68,7 +68,7 @@ error-byte: # ed : (address exit-descriptor), out : (address buffered-file), ms e8/call write-buffered/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . flush(out) + # flush(out) # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) # . . call diff --git a/069allocate.subx b/069allocate.subx index df3c05db..9b4dff57 100644 --- a/069allocate.subx +++ b/069allocate.subx @@ -19,14 +19,14 @@ == data # A default allocation descriptor for programs to use. -Heap: +Heap: # (ref allocation-descriptor) # curr 0/imm32 # limit 0/imm32 # a reasonable default -Heap-size: +Heap-size: # (ref int) 0x200000/imm32/2MB == code @@ -56,7 +56,7 @@ $array-equal-main:end: # Claim the next 'n' bytes of memory starting at ad->curr and update ad->curr. # Abort if there isn't enough memory in 'ad'. -allocate: # ad : (address allocation-descriptor), n : int -> address-or-null/eax +allocate: # ad : (address allocation-descriptor), n : int -> address-or-null/eax : (address _) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -104,11 +104,11 @@ test-allocate-success: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ad/ecx : (address allocation-descriptor) = {11, 15} + # var ad/ecx : (ref allocation-descriptor) = {11, 15} 68/push 0xf/imm32/limit 68/push 0xb/imm32/curr 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # eax = allocate(ad, 3) + # var eax : (handle byte) = allocate(ad, 3) # . . push args 68/push 3/imm32 51/push-ecx @@ -143,11 +143,11 @@ _pending-test-allocate-failure: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ad/ecx : (address allocation-descriptor) = {11, 15} + # var ad/ecx : (ref allocation-descriptor) = {11, 15} 68/push 0xf/imm32/limit 68/push 0xb/imm32/curr 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # eax = allocate(ad, 6) + # var eax : (handle byte) = allocate(ad, 6) # . . push args 68/push 6/imm32 51/push-ecx @@ -180,7 +180,7 @@ _pending-test-allocate-failure: c3/return # helper: create a nested allocation descriptor (useful for tests) -allocate-region: # ad : (address allocation-descriptor), n : int -> new-ad : (address allocation-descriptor) +allocate-region: # ad : (address allocation-descriptor), n : int -> new-ad : (handle allocation-descriptor) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp diff --git a/070new-stream.subx b/070new-stream.subx index e1bea314..45076c91 100644 --- a/070new-stream.subx +++ b/070new-stream.subx @@ -5,13 +5,13 @@ # . 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 -new-stream: # ad : (address allocation-descriptor), length : int, elemsize : int -> address/eax +new-stream: # ad : (address allocation-descriptor), length : int, elemsize : int -> address/eax : (handle stream _) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 52/push-edx - # n = elemsize * length + 12 (for read, write and length) + # var n/eax : int = elemsize * length + 12 (for read, write and length) # . eax = elemsize 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax # . eax *= length @@ -24,7 +24,7 @@ new-stream: # ad : (address allocation-descriptor), length : int, elemsize : in 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx # . eax += 12 05/add-to-eax 0xc/imm32 - # allocate(ad, n) + # var eax : (handle stream _) = allocate(ad, n) # . . push args 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) @@ -68,7 +68,7 @@ test-new-stream: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var heap/ecx : (address allocation-descriptor) = {0, 0} + # var heap/ecx : (ref allocation-descriptor) 68/push 0/imm32/limit 68/push 0/imm32/curr 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -82,7 +82,7 @@ test-new-stream: 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # var start/edx = ad->curr 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - # eax = new-stream(heap, 3, 2) + # var eax : (handle stream byte) = new-stream(heap, 3, 2) # . . push args 68/push 2/imm32 68/push 3/imm32 diff --git a/071read-line.subx b/071read-line.subx index 6fe8deb7..ab336c52 100644 --- a/071read-line.subx +++ b/071read-line.subx @@ -216,7 +216,7 @@ test-read-line-buffered-reads-final-line-until-Eof: # read bytes from 'f' until (and including) a newline and store them into 's' # 's' fails to grow if and only if no data found # just abort if 's' is too small -read-line: # f : (address stream), s : (address stream byte) +read-line: # f : (address stream byte), s : (address stream byte) # pseudocode: # while true # if (s->write >= s->length) abort diff --git a/072slice.subx b/072slice.subx index 6ecdc003..30c1b356 100644 --- a/072slice.subx +++ b/072slice.subx @@ -34,7 +34,7 @@ test-slice-empty-true: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var slice/ecx = {34, 34} + # var slice/ecx : (ref slice) = {34, 34} 68/push 34/imm32/end 68/push 34/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -63,7 +63,7 @@ test-slice-empty-false: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var slice/ecx = {34, 23} + # var slice/ecx : (ref slice) = {34, 23} 68/push 23/imm32/end 68/push 34/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -88,7 +88,7 @@ test-slice-empty-false: 5d/pop-to-ebp c3/return -slice-equal?: # s : (address slice), p : (address string) -> eax : boolean +slice-equal?: # s : (address slice), p : (address array byte) -> eax : boolean # pseudocode: # if (p == 0) return (s == 0) # currs = s->start @@ -118,11 +118,11 @@ 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 - # currs/edx = s->start + # var currs/edx : (address byte) = s->start 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx - # maxs/esi = s->end + # var maxs/esi : (address byte) = s->end 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi - # eax = maxs - currs + # var slen/eax : int = 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 # ebx = p @@ -136,23 +136,24 @@ $slice-equal?:null-string: 74/jump-if-equal $slice-equal?:true/disp8 eb/jump $slice-equal?:false/disp8 $slice-equal?:nonnull-string: - # if (eax != p->length) return false + # if (slen != 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 - # currp/ebx = p->data + # var currp/ebx : (address byte) = p->data 81 0/subop/add 3/mod/direct 3/rm32/ebx . . . . . 4/imm32 # add to ebx - # eax = ecx = 0 + # var c1/eax : byte = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + # var c2/ecx : byte = 0 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx $slice-equal?:loop: # if (currs >= maxs) return true 39/compare 3/mod/direct 2/rm32/edx . . . 6/r32/esi . . # compare edx with esi 73/jump-if-greater-or-equal-unsigned $slice-equal?:true/disp8 - # AL = *currp + # c1 = *currp 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL - # CL = *currs + # c2 = *currs 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 1/r32/CL . . # copy byte at *edx to CL - # if (eax != ecx) return false + # if (c1 != c2) 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 # ++currp @@ -186,7 +187,7 @@ test-slice-equal: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -222,7 +223,7 @@ test-slice-equal-false: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -258,7 +259,7 @@ test-slice-equal-too-long: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -294,7 +295,7 @@ test-slice-equal-too-short: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -325,7 +326,7 @@ test-slice-equal-empty: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var slice/ecx + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -361,7 +362,7 @@ test-slice-equal-with-empty: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -392,7 +393,7 @@ test-slice-equal-empty-with-empty: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var slice/ecx + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -428,7 +429,7 @@ test-slice-equal-with-null: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -454,7 +455,7 @@ test-slice-equal-with-null: 5d/pop-to-ebp c3/return -slice-starts-with?: # s : (address slice), head : (address string) -> eax : boolean +slice-starts-with?: # s : (address slice), head : (address array byte) -> eax : boolean # pseudocode # lenh = head->length # if (lenh > s->end - s->start) return false @@ -487,34 +488,35 @@ slice-starts-with?: # s : (address slice), head : (address string) -> eax : boo 57/push-edi # esi = s 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # ecx = s->end - s->start + # var lens/ecx : int = s->end - s->start 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 2b/subtract 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # subtract *esi from ecx # edi = head 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi - # lenh/edx = head->length + # var lenh/edx : int = head->length 8b/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy *edi to edx - # if (lenh > s->end - s->start) return false + # if (lenh > lens) return false 39/compare 3/mod/direct 2/rm32/edx . . . 1/r32/ecx . . # compare edx with ecx 7f/jump-if-greater $slice-starts-with?:false/disp8 - # currs/esi = s->start + # var currs/esi : (address byte) = s->start 8b/subtract 0/mod/indirect 6/rm32/esi . . . 6/r32/esi . . # copy *esi to esi - # currh/edi = head->data + # var currh/edi : (address byte) = head->data 81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi - # i/ecx = 0 + # var i/ecx : int = 0 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx - # eax = ebx = 0 + # var c1/eax : byte = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + # var c2/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx $slice-starts-with?:loop: # if (i >= lenh) return true 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 7d/jump-if-greater-or-equal $slice-starts-with?:true/disp8 - # AL = *currs + # c1 = *currs 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL - # BL = *currh + # c2 = *currh 8a/copy-byte 0/mod/indirect 7/rm32/edi . . . 3/r32/BL . . # copy byte at *edi to BL - # if (*currs != *currh) return false + # if (c1 != c2) return false 39/compare 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # compare eax and ebx 75/jump-if-not-equal $slice-starts-with?:false/disp8 # ++i @@ -551,7 +553,7 @@ test-slice-starts-with-single-character: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -587,7 +589,7 @@ test-slice-starts-with-empty-string: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -623,7 +625,7 @@ test-slice-starts-with-multiple-characters: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -659,7 +661,7 @@ test-slice-starts-with-entire-string: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -695,7 +697,7 @@ test-slice-starts-with-fails: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -731,7 +733,7 @@ test-slice-starts-with-fails-2: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -759,7 +761,7 @@ test-slice-starts-with-fails-2: # write a slice to a stream # abort if the stream doesn't have enough space -write-slice: # out : (address stream), s : (address slice) +write-slice: # out : (address stream byte), s : (address slice) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -772,9 +774,9 @@ write-slice: # out : (address stream), s : (address slice) 57/push-edi # esi = s 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # curr/ecx = s->start + # var curr/ecx : (address byte) = s->start 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx - # max/esi = s->end + # var max/esi : (address byte) = s->end 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi # edi = out 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi @@ -848,7 +850,7 @@ test-write-slice: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -888,9 +890,9 @@ write-slice-buffered: # out : (address buffered-file), s : (address slice) 57/push-edi # esi = s 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # curr/ecx = s->start + # var curr/ecx : (address byte) = s->start 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx - # max/esi = s->end + # var max/esi : (address byte) = s->end 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi # edi = out 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi @@ -976,7 +978,7 @@ test-write-slice-buffered: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -1010,7 +1012,7 @@ test-write-slice-buffered: c3/return # copy a slice into a new (dynamically allocated) string -slice-to-string: # ad : (address allocation-descriptor), in : (address slice) -> out/eax : (address array) +slice-to-string: # ad : (address allocation-descriptor), in : (address slice) -> out/eax : (address array byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -1021,15 +1023,15 @@ slice-to-string: # ad : (address allocation-descriptor), in : (address slice) - 56/push-esi # esi = in 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # curr/edx = in->start + # var curr/edx : (address byte) = in->start 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx - # max/ebx = in->end + # var max/ebx : (address byte) = in->end 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 3/r32/ebx 4/disp8 . # copy *(esi+4) to ebx - # size/ecx = max - curr + 4 # total size of output string (including the initial length) + # var size/ecx : int = max - curr + 4 # total size of output string (including the initial length) 89/copy 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # copy ebx to ecx 29/subtract 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # subtract edx from ecx 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx - # out/eax = allocate(ad, size) + # var out/eax : (handle array byte) = allocate(ad, size) # . . push args 51/push-ecx ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) @@ -1040,7 +1042,7 @@ slice-to-string: # ad : (address allocation-descriptor), in : (address slice) - # if (eax == 0) abort 3d/compare-eax-and 0/imm32 74/jump-if-equal $slice-to-string:abort/disp8 - # *out = size-4 + # out->length = size-4 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax 81 5/subop/subtract 0/mod/indirect 0/rm32/eax . . . . . 4/imm32 # subtract 4 from *eax # save out @@ -1092,7 +1094,7 @@ test-slice-to-string: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var heap/edx : (address allocation-descriptor) = {0, 0} + # var heap/edx : (ref allocation-descriptor) 68/push 0/imm32/limit 68/push 0/imm32/curr 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -1109,7 +1111,7 @@ test-slice-to-string: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx diff --git a/073next-token.subx b/073next-token.subx index 35414883..567f0cce 100644 --- a/073next-token.subx +++ b/073next-token.subx @@ -7,7 +7,7 @@ # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary) # on reaching end of file, return an empty interval -next-token: # in : (address stream), delimiter : byte, out : (address slice) +next-token: # in : (address stream byte), delimiter : byte, out : (address slice) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -66,7 +66,7 @@ test-next-token: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -130,7 +130,7 @@ test-next-token-Eof: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -216,7 +216,7 @@ test-next-token-from-slice: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var out/edi : (address slice) = {0, 0} + # var out/edi : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi @@ -265,7 +265,7 @@ test-next-token-from-slice-Eof: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var out/edi : (address slice) = {0, 0} + # var out/edi : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi @@ -306,7 +306,7 @@ test-next-token-from-slice-nothing: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var out/edi : (address slice) = {0, 0} + # var out/edi : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi @@ -338,7 +338,7 @@ test-next-token-from-slice-nothing: 5d/pop-to-ebp c3/return -skip-chars-matching: # in : (address stream), delimiter : byte +skip-chars-matching: # in : (address stream byte), delimiter : byte # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -461,7 +461,7 @@ test-skip-chars-matching-none: # end c3/return -skip-chars-matching-whitespace: # in : (address stream) +skip-chars-matching-whitespace: # in : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -551,7 +551,7 @@ test-skip-chars-matching-whitespace: c3/return # minor fork of 'skip-chars-matching' -skip-chars-not-matching: # in : (address stream), delimiter : byte +skip-chars-not-matching: # in : (address stream byte), delimiter : byte # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -713,7 +713,7 @@ test-skip-chars-not-matching-all: # end c3/return -skip-chars-not-matching-whitespace: # in : (address stream) +skip-chars-not-matching-whitespace: # in : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -815,14 +815,15 @@ skip-chars-matching-in-slice: # curr : (address byte), end : (address byte), de 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx # edx = delimiter 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx - # ebx = 0 + # var c/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx $skip-chars-matching-in-slice:loop: # if (curr >= end) break 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 73/jump-if-greater-or-equal-unsigned $skip-chars-matching-in-slice:end/disp8 - # if (*curr != delimiter) break + # c = *curr 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL + # if (c != delimiter) break 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx and edx 75/jump-if-not-equal $skip-chars-matching-in-slice:end/disp8 # ++curr @@ -896,7 +897,7 @@ test-skip-chars-matching-in-slice-none: # end c3/return -skip-chars-matching-whitespace-in-slice: # in : (address stream) +skip-chars-matching-whitespace-in-slice: # curr : (address byte), end : (address byte) -> curr/eax # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -907,24 +908,24 @@ skip-chars-matching-whitespace-in-slice: # in : (address stream) 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax # ecx = end 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx - # ebx = 0 + # var c/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx $skip-chars-matching-whitespace-in-slice:loop: # if (curr >= end) break 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 0f 83/jump-if-greater-or-equal-unsigned $skip-chars-matching-in-slice:end/disp32 - # ebx = *curr + # c = *curr 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL - # if (*curr == ' ') goto body + # if (c == ' ') goto body 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x20/imm32/space # compare ebx 74/jump-if-equal $skip-chars-matching-whitespace-in-slice:body/disp8 - # if (*curr == '\n') goto body + # if (c == '\n') goto body 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0a/imm32/newline # compare ebx 74/jump-if-equal $skip-chars-matching-whitespace-in-slice:body/disp8 - # if (*curr == '\t') goto body + # if (c == '\t') goto body 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x09/imm32/tab # compare ebx 74/jump-if-equal $skip-chars-matching-whitespace-in-slice:body/disp8 - # if (*curr != '\r') break + # if (c != '\r') break 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0d/imm32/cr # compare ebx 75/jump-if-not-equal $skip-chars-matching-whitespace-in-slice:end/disp8 $skip-chars-matching-whitespace-in-slice:body: @@ -983,14 +984,15 @@ skip-chars-not-matching-in-slice: # curr : (address byte), end : (address byte) 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx # edx = delimiter 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx - # ebx = 0 + # var c/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx $skip-chars-not-matching-in-slice:loop: # if (curr >= end) break 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 73/jump-if-greater-or-equal-unsigned $skip-chars-not-matching-in-slice:end/disp8 - # if (*curr == delimiter) break + # c = *curr 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL + # if (c == delimiter) break 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx and edx 74/jump-if-equal $skip-chars-not-matching-in-slice:end/disp8 # ++curr @@ -1093,7 +1095,7 @@ test-skip-chars-not-matching-in-slice-all: # end c3/return -skip-chars-not-matching-whitespace-in-slice: # in : (address stream) +skip-chars-not-matching-whitespace-in-slice: # curr : (address byte), end : (address byte) -> curr/eax # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -1104,24 +1106,24 @@ skip-chars-not-matching-whitespace-in-slice: # in : (address stream) 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax # ecx = end 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx - # ebx = 0 + # var c/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx $skip-chars-not-matching-whitespace-in-slice:loop: # if (curr >= end) break 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 0f 83/jump-if-greater-or-equal-unsigned $skip-chars-not-matching-in-slice:end/disp32 - # ebx = *curr + # c = *curr 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL - # if (*curr == ' ') break + # if (c == ' ') break 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x20/imm32/space # compare ebx 74/jump-if-equal $skip-chars-not-matching-whitespace-in-slice:end/disp8 - # if (*curr == '\n') break + # if (c == '\n') break 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0a/imm32/newline # compare ebx 74/jump-if-equal $skip-chars-not-matching-whitespace-in-slice:end/disp8 - # if (*curr == '\t') break + # if (c == '\t') break 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x09/imm32/tab # compare ebx 74/jump-if-equal $skip-chars-not-matching-whitespace-in-slice:end/disp8 - # if (*curr == '\r') break + # if (c == '\r') break 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0d/imm32/cr # compare ebx 74/jump-if-equal $skip-chars-not-matching-whitespace-in-slice:end/disp8 # ++curr @@ -1166,7 +1168,7 @@ test-skip-chars-not-matching-whitespace-in-slice: # update line->read to end of string literal surrounded by double quotes # line->read must start out at a double-quote -skip-string: # line : (address stream) +skip-string: # line : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -1420,7 +1422,7 @@ skip-string-in-slice: # curr : (address byte), end : (address byte) -> new_curr 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # edx = end 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx - # eax = 0 + # var c/eax : byte = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax # skip initial dquote 41/increment-ecx @@ -1428,14 +1430,14 @@ $skip-string-in-slice:loop: # if (curr >= end) return curr 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-greater-unsigned-or-equal $skip-string-in-slice:return-curr/disp8 - # AL = *curr + # c = *curr 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL $skip-string-in-slice:dquote: - # if (eax == '"') break + # if (c == '"') break 3d/compare-eax-and 0x22/imm32/double-quote 74/jump-if-equal $skip-string-in-slice:break/disp8 $skip-string-in-slice:check-for-escape: - # if (eax == '\') escape next char + # if (c == '\') escape next char 3d/compare-eax-and 0x5c/imm32/backslash 75/jump-if-not-equal $skip-string-in-slice:continue/disp8 $skip-string-in-slice:escape: @@ -1594,7 +1596,7 @@ test-skip-string-in-slice-stops-at-end: # update line->read to ')' # line->read ends at ')' -skip-until-close-paren: # line : (address stream) +skip-until-close-paren: # line : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -1781,7 +1783,7 @@ test-skip-until-close-paren-works-from-mid-stream: 5d/pop-to-ebp c3/return -skip-until-close-paren-in-slice: # curr : (address byte), end : (address byte) -> new_curr/eax +skip-until-close-paren-in-slice: # curr : (address byte), end : (address byte) -> new_curr/eax : (address byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -1792,7 +1794,7 @@ skip-until-close-paren-in-slice: # curr : (address byte), end : (address byte) 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # edx = end 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx - # eax = 0 + # var c/eax : byte = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax # skip initial dquote 41/increment-ecx @@ -1800,10 +1802,10 @@ $skip-until-close-paren-in-slice:loop: # if (curr >= end) break 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-greater-unsigned-or-equal $skip-until-close-paren-in-slice:break/disp8 - # AL = *curr + # c = *curr 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL $skip-until-close-paren-in-slice:check-close: - # if (eax == ')') break + # if (c == ')') break 3d/compare-eax-and 0x29/imm32/close-paren 74/jump-if-equal $skip-until-close-paren-in-slice:break/disp8 # ++curr diff --git a/074write-stream-data.subx b/074write-stream-data.subx index 25a8f87c..074e9d29 100644 --- a/074write-stream-data.subx +++ b/074write-stream-data.subx @@ -8,7 +8,7 @@ # - construct a 'maximal slice' and pass it to write-slice-buffered # - flush the buffered-file and pass the stream directly to its fd (disabling buffering) # we'll go with the first way for now -write-stream-data: # f : (address buffered-file), s : (address stream) +write-stream-data: # f : (address buffered-file), s : (address stream byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -18,8 +18,8 @@ write-stream-data: # f : (address buffered-file), s : (address stream) 56/push-esi # esi = s 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # var slice/ecx = {s->data, s->data + s->write} - # . push s->data + s->write + # var slice/ecx : (ref slice) = {s->data, &s->data[s->write]} + # . push &s->data[s->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy esi+eax+12 to eax 50/push-eax diff --git a/075print-int-decimal.subx b/075print-int-decimal.subx index a9cfa5fc..8e8c7da4 100644 --- a/075print-int-decimal.subx +++ b/075print-int-decimal.subx @@ -5,7 +5,7 @@ # . 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 -print-int32-decimal: # out : (address stream), n : int32 +print-int32-decimal: # out : (address stream byte), n : int32 # works by generating characters from lowest to highest and pushing them # to the stack, before popping them one by one into the stream # @@ -44,11 +44,11 @@ print-int32-decimal: # out : (address stream), n : int32 52/push-edx 53/push-ebx 57/push-edi - # ten/ecx = 10 + # const ten/ecx = 10 b9/copy-to-ecx 0xa/imm32 # push sentinel 68/push 0/imm32/sentinel - # eax = abs(n) + # var eax : int = abs(n) 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax 3d/compare-eax-with 0/imm32 7d/jump-if-greater-or-equal $print-int32-decimal:read-loop/disp8 @@ -74,11 +74,11 @@ $print-int32-decimal:push-negative: $print-int32-decimal:write: # edi = out 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi - # w/edx = out->write + # var w/edx : int = out->write 8b/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy *edi to edx - # curr/ecx = &out->data[out->write] + # var curr/ecx : (address byte) = &out->data[out->write] 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/edi 2/index/edx . 1/r32/ecx 0xc/disp8 . # copy ebx+edx+12 to ecx - # max/ebx = &out->data[out->length] + # var max/ebx : (address byte) = &out->data[out->length] 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 8/disp8 . # copy *(edi+8) to ebx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/edi 3/index/ebx . 3/r32/ebx 0xc/disp8 . # copy edi+ebx+12 to ebx $print-int32-decimal:write-loop: diff --git a/076next-word.subx b/076next-word.subx index 054dfb47..34dd9c4d 100644 --- a/076next-word.subx +++ b/076next-word.subx @@ -35,7 +35,7 @@ $next-word:check0: # . if (eax < line->write) goto next check 3b/compare 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # compare eax with *esi 7c/jump-if-lesser $next-word:check-for-comment/disp8 - # . return out = {0, 0} + # . return out c7 0/subop/copy 0/mod/direct 7/rm32/edi . . . . . 0/imm32 # copy to *edi c7 0/subop/copy 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 0/imm32 # copy to *(edi+4) eb/jump $next-word:end/disp8 @@ -95,7 +95,7 @@ test-next-word: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -158,7 +158,7 @@ test-next-word-returns-whole-comment: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -221,7 +221,7 @@ test-next-word-returns-empty-string-on-eof: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx diff --git a/077subx-words.subx b/077subx-words.subx index 2b53ebb1..a166217a 100644 --- a/077subx-words.subx +++ b/077subx-words.subx @@ -25,9 +25,9 @@ has-metadata?: # word : (address slice), s : (address string) -> eax : boolean 57/push-edi # esi = word 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # edx = word->end + # var edx : (address byte) = word->end 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx - # var twig/edi : (address slice) = {0, 0} + # var twig/edi : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi @@ -41,15 +41,13 @@ has-metadata?: # word : (address slice), s : (address string) -> eax : boolean e8/call next-token-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # curr/ecx = twig->end - 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx $has-metadata?:loop: # next-token-from-slice(curr, word->end, '/', twig) # . . push args 57/push-edi 68/push 0x2f/imm32/slash 52/push-edx - 51/push-ecx + ff 6/subop/push 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 . # push *(edi+4) # . . call e8/call next-token-from-slice/disp32 # . . discard args @@ -62,8 +60,8 @@ $has-metadata?:loop: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) return false - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return false + 3d/compare-eax-and 0/imm32/false 75/jump-if-not-equal $has-metadata?:false/disp8 # if (slice-equal?(twig, s)) return true # . eax = slice-equal?(twig, s) @@ -74,15 +72,11 @@ $has-metadata?:loop: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return true - 3d/compare-eax-and 0/imm32 - 75/jump-if-not-equal $has-metadata?:true/disp8 - # curr = twig->end - 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx + # . if (eax != false) return true + 3d/compare-eax-and 0/imm32/false + # eax already contains true + 75/jump-if-not-equal $has-metadata?:end/disp8 eb/jump $has-metadata?:loop/disp8 -$has-metadata?:true: - b8/copy-to-eax 1/imm32/true - eb/jump $has-metadata?:end/disp8 $has-metadata?:false: b8/copy-to-eax 0/imm32/false $has-metadata?:end: @@ -107,7 +101,7 @@ test-has-metadata-true: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var in/esi : (address slice) = {eax, ecx} + # var in/esi : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi @@ -142,7 +136,7 @@ test-has-metadata-false: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var in/esi : (address slice) = {eax, ecx} + # var in/esi : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi @@ -177,7 +171,7 @@ test-has-metadata-ignore-name: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var in/esi : (address slice) = {eax, ecx} + # var in/esi : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi @@ -212,7 +206,7 @@ test-has-metadata-multiple-true: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var in/esi : (address slice) = {eax, ecx} + # var in/esi : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi @@ -247,7 +241,7 @@ test-has-metadata-multiple-false: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var in/esi : (address slice) = {eax, ecx} + # var in/esi : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi @@ -290,22 +284,21 @@ is-valid-name?: # in : (address slice) -> eax : boolean 56/push-esi # esi = in 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # start/ecx = in->start + # var start/ecx : (address byte) = in->start 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx - # end/eax = in->end - 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) to eax $is-valid-name?:check0: - # if (start >= end) return false - 39/compare 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # compare ecx with eax + # if (start >= in->end) return false + 3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # compare ecx with *(esi+4) 73/jump-if-greater-or-equal-unsigned $is-valid-name?:false/disp8 $is-valid-name?:check1: - # eax -= ecx + # var len/eax : int = in->end - start + 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) to eax 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax # if (eax == 2) return false 3d/compare-eax-and 2/imm32 74/jump-if-equal $is-valid-name?:false/disp8 $is-valid-name?:check2: - # c/eax = *ecx + # var c/eax : (address byte) = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL # if (c == "-") return false @@ -344,7 +337,7 @@ test-is-valid-name-digit-prefix: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -378,7 +371,7 @@ test-is-valid-name-negative-prefix: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -412,7 +405,7 @@ test-is-valid-name-0x-prefix: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -446,7 +439,7 @@ test-is-valid-name-starts-with-pre-digit: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -480,7 +473,7 @@ test-is-valid-name-starts-with-post-digit: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -514,7 +507,7 @@ test-is-valid-name-starts-with-digit: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -547,12 +540,11 @@ is-label?: # word : (address slice) -> eax : boolean 51/push-ecx # ecx = word 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx - # ecx = word->end + # var end/ecx : (address byte) = word->end 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 1/r32/ecx 4/disp8 . # copy *(ecx+4) to ecx - # return *(word->end - 1) == ':' - # . eax = 0 + # return *(end - 1) == ':' + # . eax = *(end-1) 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - # . eax = *((char *) word->end - 1) 8a/copy-byte 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/AL -1/disp8 . # copy byte at *(ecx-1) to AL # . return (eax == ':') 3d/compare-eax-and 0x3a/imm32/colon @@ -577,7 +569,7 @@ $test-is-label?:true: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -603,7 +595,7 @@ $test-is-label?:false: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx diff --git a/078emit-hex.subx b/078emit-hex.subx index 2c642481..caea7800 100644 --- a/078emit-hex.subx +++ b/078emit-hex.subx @@ -20,13 +20,13 @@ emit-hex: # out : (address buffered-file), n : int, width : int 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 3/r32/ebx 0xc/disp8 . # copy *(ebp+12) to ebx # edx = width 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx - # var curr/ecx = 0 + # var curr/ecx : int = 0 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx $emit-hex:loop: # if (curr >= width) break 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 7d/jump-if-greater-or-equal $emit-hex:end/disp8 - # print-byte-buffered(out, ebx) + # print-byte-buffered(out, ebx) # only BL used # . . push args 53/push-ebx 57/push-edi diff --git a/079emit.subx b/079emit.subx index 61ed425e..abf11dce 100644 --- a/079emit.subx +++ b/079emit.subx @@ -17,7 +17,7 @@ emit: # out : (address buffered-file), word : (address slice), width : int 57/push-edi # esi = word 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # var name/edi : (address slice) = {0, 0} + # var datum/edi : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi @@ -39,8 +39,8 @@ emit: # out : (address buffered-file), word : (address slice), width : int e8/call is-valid-name?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) - 3d/compare-eax-and 0/imm32 + # . if (eax != false) + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit:hex-int/disp8 $emit:name: # . write-slice-buffered(out, word) @@ -63,11 +63,11 @@ $emit:name: eb/jump $emit:end/disp8 # otherwise emit-hex(out, parse-hex-int(datum), width) # (Weird shit can happen here if the datum of 'word' isn't either a valid - # name or a hex number, but we're only going to be passing in real legal - # programs. We just want to make sure that valid names aren't treated as - # (valid) hex numbers.) + # name or a hex number. `emit` is mostly used by ntranslate, which is + # currently designed to only receive legal SubX programs. We just want to + # make sure that valid names aren't treated as (valid) hex numbers.) $emit:hex-int: - # . value/eax = parse-hex-int(datum) + # . var value/eax : int = parse-hex-int(datum) # . . push args 57/push-edi # . . call @@ -119,7 +119,7 @@ test-emit-number: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -178,7 +178,7 @@ test-emit-negative-number: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -236,7 +236,7 @@ test-emit-number-with-metadata: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -295,7 +295,7 @@ test-emit-non-number: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -353,7 +353,7 @@ test-emit-non-number-with-metadata: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -411,7 +411,7 @@ test-emit-non-number-with-all-hex-digits-and-metadata: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx diff --git a/080zero-out.subx b/080zero-out.subx index 2dee2665..19e8128f 100644 --- a/080zero-out.subx +++ b/080zero-out.subx @@ -5,7 +5,7 @@ # . 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 -zero-out: # start : address, len : int +zero-out: # start : (address byte), len : int # pseudocode: # curr/esi = start # i/ecx = 0 @@ -25,7 +25,7 @@ zero-out: # start : address, len : int 56/push-esi # curr/esi = start 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # i/ecx = 0 + # var i/ecx : int = 0 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx # edx = len 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx diff --git a/081table.subx b/081table.subx index 83cd9102..46329ca0 100644 --- a/081table.subx +++ b/081table.subx @@ -1,7 +1,7 @@ # A table is a stream of (key, value) rows. # -# Each row consists of a 4-byte key (address to a string) and a variable-size -# value. +# Each row consists of a 4-byte key -- a 'string_key' which is (address array +# byte) -- and a variable-size value. # # Accessing the table performs a linear scan for a key string, and always # requires passing in the row size. @@ -23,7 +23,8 @@ # . 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 # if no row is found, abort -get: # table : (address stream {string, _}), key : (address string), row-size : int, abort-message-prefix : (address string) -> eax : (address _) +# type string_key = (address array byte) +get: # table : (address stream {string_key, T}), key : string_key, row-size : int, abort-message-prefix : (address array byte) -> eax : (address T) # pseudocode: # curr = table->data # max = &table->data[table->write] @@ -42,9 +43,9 @@ get: # table : (address stream {string, _}), key : (address string), row-size : 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/ecx = table->data + # var curr/ecx : (address string_key) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # max/edx = table->data + table->write + # var max/edx : (address byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $get:search-loop: @@ -60,8 +61,8 @@ $get:search-loop: e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return eax = curr+4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return eax = curr+4 + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $get:mismatch/disp8 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax eb/jump $get:end/disp8 @@ -124,7 +125,7 @@ test-get: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # - setup: create a table with a couple of keys - # var table/ecx : (address stream {string, number}) = stream(2 rows * 8 bytes) + # var table/ecx : (ref stream {string, number} 16) # 2 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp 68/push 0x10/imm32/length 68/push 0/imm32/read @@ -197,7 +198,7 @@ $test-get:end: c3/return # if no row is found, abort -get-slice: # table : (address stream {string, _}), key : (address slice), row-size : int, abort-message-prefix : (address string) -> eax : (address _) +get-slice: # table : (address stream {string_key, T}), key : (address slice), row-size : int, abort-message-prefix : (address array byte) -> eax : (address T) # pseudocode: # curr = table->data # max = &table->data[table->write] @@ -216,9 +217,9 @@ get-slice: # table : (address stream {string, _}), key : (address slice), row-s 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/ecx = table->data + # var curr/ecx : (address string_key) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # max/edx = table->data + table->write + # var max/edx : (address byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $get-slice:search-loop: @@ -234,8 +235,8 @@ $get-slice:search-loop: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return eax = curr+4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return eax = curr+4 + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $get-slice:mismatch/disp8 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax eb/jump $get-slice:end/disp8 @@ -305,7 +306,7 @@ test-get-slice: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # - setup: create a table with a couple of keys - # var table/ecx : (address stream {string, number}) = stream(2 rows * 8 bytes) + # var table/ecx : (ref stream {string, number} 16) # 2 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp 68/push 0x10/imm32/length 68/push 0/imm32/read @@ -335,7 +336,7 @@ $test-get-slice:check1: 8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx 05/add-to-eax 4/imm32 - # var slice/edx = {eax, edx} + # var slice/edx : (ref slice) = {eax, edx} 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -365,7 +366,7 @@ $test-get-slice:check2: 8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx 05/add-to-eax 4/imm32 - # var slice/edx = {eax, edx} + # var slice/edx : (ref slice) = {eax, edx} 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -400,7 +401,7 @@ $test-get-slice:end: # return the address of the value # Beware: assume keys are immutable; they're inserted by reference # TODO: pass in an allocation descriptor -get-or-insert: # table : (address stream {string, _}), key : (address string), row-size : int -> eax : (address _) +get-or-insert: # table : (address stream {string_key, T}), key : string_key, row-size : int -> eax : (address T) # pseudocode: # curr = table->data # max = &table->data[table->write] @@ -424,9 +425,9 @@ get-or-insert: # table : (address stream {string, _}), key : (address string), 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/ecx = table->data + # var curr/ecx : (address string_key) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # max/edx = table->data + table->write + # var max/edx : (address string_key) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $get-or-insert:search-loop: @@ -442,8 +443,8 @@ $get-or-insert:search-loop: e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return eax = curr+4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return eax = curr+4 + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $get-or-insert:mismatch/disp8 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax eb/jump $get-or-insert:end/disp8 @@ -511,7 +512,7 @@ test-get-or-insert: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var table/ecx : (address stream {string, number}) = stream(2 rows * 8 bytes) + # var table/ecx : (ref stream {string, number} 16) # 2 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp 68/push 0x10/imm32/length 68/push 0/imm32/read @@ -651,7 +652,7 @@ $test-get-or-insert:end: # if there are no rows free, abort # WARNING: leaks memory # TODO: pass in an allocation descriptor -leaky-get-or-insert-slice: # table : (address stream {string, _}), key : (address slice), row-size : int -> eax : (address _) +leaky-get-or-insert-slice: # table : (address stream {string_key, T}), key : (address slice), row-size : int -> eax : (address T) # pseudocode: # curr = table->data # max = &table->data[table->write] @@ -675,9 +676,9 @@ leaky-get-or-insert-slice: # table : (address stream {string, _}), key : (addre 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/ecx = table->data + # var curr/ecx : (address string_key) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # max/edx = table->data + table->write + # var max/edx : (address string_key) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $leaky-get-or-insert-slice:search-loop: @@ -693,8 +694,8 @@ $leaky-get-or-insert-slice:search-loop: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return eax = curr+4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return eax = curr+4 + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $leaky-get-or-insert-slice:mismatch/disp8 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax eb/jump $leaky-get-or-insert-slice:end/disp8 @@ -768,7 +769,7 @@ test-leaky-get-or-insert-slice: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var table/ecx : (address stream {string, number}) = stream(2 rows * 8 bytes) + # var table/ecx : (ref stream {string, number} 16) # 2 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp 68/push 0x10/imm32/length 68/push 0/imm32/read @@ -779,7 +780,7 @@ test-leaky-get-or-insert-slice: 8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx 05/add-to-eax 4/imm32 - # var slice/edx = {eax, edx} + # var slice/edx : (ref slice) = {eax, edx} 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -872,7 +873,7 @@ $test-leaky-get-or-insert-slice:third-call: 8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx 05/add-to-eax 4/imm32 - # var slice/edx = {eax, edx} + # var slice/edx : (ref slice) = {eax, edx} 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -923,9 +924,9 @@ $test-leaky-get-or-insert-slice:end: c3/return # if no row is found, stop(ed) -get-or-stop: # table : (address stream {string, _}), key : (address string), row-size : int, - # abort-message-prefix : (address string), err : (address buffered-file), ed : (address exit-descriptor) - # -> eax : (address _) +get-or-stop: # table : (address stream {string_key, T}), key : string_key, row-size : int, + # abort-message-prefix : (address array byte), err : (address buffered-file), ed : (address exit-descriptor) + # -> eax : (address T) # pseudocode: # curr = table->data # max = &table->data[table->write] @@ -945,9 +946,9 @@ get-or-stop: # table : (address stream {string, _}), key : (address string), ro 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/ecx = table->data + # var curr/ecx : (address string_key) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # max/edx = table->data + table->write + # var max/edx : (address byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $get-or-stop:search-loop: @@ -963,8 +964,8 @@ $get-or-stop:search-loop: e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return eax = curr+4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return eax = curr+4 + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $get-or-stop:mismatch/disp8 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax eb/jump $get-or-stop:end/disp8 @@ -1050,13 +1051,13 @@ test-get-or-stop: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var table/ecx : (address stream {string, number}) = stream(2 rows * 8 bytes) + # var table/ecx : (ref stream {string, number} 16) # 2 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp 68/push 0x10/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var ed/edx : (address exit-descriptor) + # var ed/edx : (ref exit-descriptor) 68/push 0/imm32 68/push 0/imm32 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -1139,7 +1140,7 @@ $test-get-or-stop:end: c3/return # if no row is found, stop(ed) -get-slice-or-stop: # table : (address stream {string, _}), key : (address slice), row-size : int, +get-slice-or-stop: # table : (address stream {string_key, _}), key : (address slice), row-size : int, # abort-message-prefix : (address string), err : (address buffered-file), ed : (address exit-descriptor) # -> eax : (address _) # pseudocode: @@ -1161,9 +1162,9 @@ get-slice-or-stop: # table : (address stream {string, _}), key : (address slice 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/ecx = table->data + # var curr/ecx : (address string_key) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # max/edx = table->data + table->write + # var max/edx : (address byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $get-slice-or-stop:search-loop: @@ -1179,8 +1180,8 @@ $get-slice-or-stop:search-loop: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return eax = curr+4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return eax = curr+4 + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $get-slice-or-stop:mismatch/disp8 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax eb/jump $get-slice-or-stop:end/disp8 @@ -1266,17 +1267,17 @@ test-get-slice-or-stop: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var table/ecx : (address stream {string, number}) = stream(2 rows * 8 bytes) + # var table/ecx : (ref stream {string, number} 16) # 2 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp 68/push 0x10/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var ed/edx : (address exit-descriptor) + # var ed/edx : (ref exit-descriptor) 68/push 0/imm32 68/push 0/imm32 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # var slice/ebx = "code" + # var slice/ebx : (ref slice) = "code" # . (eax..ebx) = "code" b8/copy-to-eax "code"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 3/r32/ebx . . # copy *eax to ebx @@ -1378,7 +1379,7 @@ $test-get-slice-or-stop:end: c3/return # if no row is found, return null (0) -maybe-get: # table : (address stream {string, _}), key : (address string), row-size : int -> eax : (address _) +maybe-get: # table : (address stream {string_key, T}), key : string_key, row-size : int -> eax : (address T) # pseudocode: # curr = table->data # max = &table->data[table->write] @@ -1397,9 +1398,9 @@ maybe-get: # table : (address stream {string, _}), key : (address string), row- 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/ecx = table->data + # var curr/ecx : (address string_key) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # max/edx = table->data + table->write + # var max/edx : (address byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $maybe-get:search-loop: @@ -1415,8 +1416,8 @@ $maybe-get:search-loop: e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return eax = curr+4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return eax = curr+4 + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $maybe-get:mismatch/disp8 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax eb/jump $maybe-get:end/disp8 @@ -1442,7 +1443,7 @@ test-maybe-get: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # - setup: create a table with one row - # var table/ecx : (address stream {string, number}) = stream(2 rows * 8 bytes) + # var table/ecx : (ref stream {string, number} 16) # 2 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp 68/push 0x10/imm32/length 68/push 0/imm32/read @@ -1525,7 +1526,7 @@ $test-maybe-get:end: c3/return # if no row is found, return null (0) -maybe-get-slice: # table : (address stream {string, _}), key : (address slice), row-size : int -> eax : (address _) +maybe-get-slice: # table : (address stream {string_key, T}), key : (address slice), row-size : int -> eax : (address T) # pseudocode: # curr = table->data # max = &table->data[table->write] @@ -1544,9 +1545,9 @@ maybe-get-slice: # table : (address stream {string, _}), key : (address slice), 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/ecx = table->data + # var curr/ecx : (address string_key) = table->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx - # max/edx = table->data + table->write + # var max/edx : (address byte) = &table->data[table->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx $maybe-get-slice:search-loop: @@ -1562,8 +1563,8 @@ $maybe-get-slice:search-loop: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return eax = curr+4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return eax = curr+4 + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $maybe-get-slice:mismatch/disp8 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy ecx+4 to eax eb/jump $maybe-get-slice:end/disp8 @@ -1589,7 +1590,7 @@ test-maybe-get-slice: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # - setup: create a table with one row - # var table/ecx : (address stream {string, number}) = stream(2 rows * 8 bytes) + # var table/ecx : (ref stream {string, number} 16) # 2 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # subtract from esp 68/push 0x10/imm32/length 68/push 0/imm32/read @@ -1611,7 +1612,7 @@ $test-maybe-get-slice:success: 8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx 05/add-to-eax 4/imm32 - # var slice/edx = {eax, edx} + # var slice/edx : (ref slice) = {eax, edx} 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -1661,7 +1662,7 @@ $test-maybe-get-slice:failure: 8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx 05/add-to-eax 4/imm32 - # var slice/edx = {eax, edx} + # var slice/edx : (ref slice) = {eax, edx} 52/push-edx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx diff --git a/082slurp.subx b/082slurp.subx index a00f252b..51fba1e2 100644 --- a/082slurp.subx +++ b/082slurp.subx @@ -63,10 +63,10 @@ $slurp:loop: 3d/compare-eax-and 0/imm32 74/jump-if-equal $slurp:end/disp8 $slurp:from-stream: - # AL = f->data[f->read] + # var c/eax : byte = f->data[f->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 0x10/disp8 . # copy byte at *(esi+ecx+16) to AL - # s->data[s->write] = AL + # s->data[s->write] = c 88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 2/index/edx . 0/r32/AL 0xc/disp8 . # copy AL to *(edi+edx+12) # ++f->read 41/increment-ecx diff --git a/083subx-widths.subx b/083subx-widths.subx index 7bd7141f..db5b84ba 100644 --- a/083subx-widths.subx +++ b/083subx-widths.subx @@ -1,3 +1,8 @@ +# Helpers to compute widths of SubX arguments based on their metadata. +# /imm8 => 1 byte, +# /disp32 => 4 bytes, +# and so on. + == code # instruction effective address register displacement immediate # . op subop mod rm32 base index scale r32 @@ -11,12 +16,12 @@ compute-width: # word : (address array byte) -> eax : int 51/push-ecx # eax = word 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to ecx - # ecx = word + word->length + # var ecx : (address byte) = &word[word->length] 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx # eax = word->data 05/add-to-eax 4/imm32 - # var in/ecx : (address slice) = {eax, ecx} + # var in/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -54,8 +59,8 @@ compute-width-of-slice: # s : (address slice) -> eax : int e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return 4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return 4 + 3d/compare-eax-and 0/imm32/false b8/copy-to-eax 4/imm32 # ZF is set, so we can overwrite eax now 75/jump-if-not-equal $compute-width-of-slice:end/disp8 # if (has-metadata?(word, "disp32")) return 4 @@ -67,8 +72,8 @@ compute-width-of-slice: # s : (address slice) -> eax : int e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return 4 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return 4 + 3d/compare-eax-and 0/imm32/false b8/copy-to-eax 4/imm32 # ZF is set, so we can overwrite eax now 75/jump-if-not-equal $compute-width-of-slice:end/disp8 # if (has-metadata?(word, "imm16")) return 2 @@ -80,8 +85,8 @@ compute-width-of-slice: # s : (address slice) -> eax : int e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return 2 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return 2 + 3d/compare-eax-and 0/imm32/false b8/copy-to-eax 2/imm32 # ZF is set, so we can overwrite eax now 75/jump-if-not-equal $compute-width-of-slice:end/disp8 # if (has-metadata?(word, "disp16")) return 2 @@ -93,8 +98,8 @@ compute-width-of-slice: # s : (address slice) -> eax : int e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return 2 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return 2 + 3d/compare-eax-and 0/imm32/false b8/copy-to-eax 2/imm32 # ZF is set, so we can overwrite eax now 75/jump-if-not-equal $compute-width-of-slice:end/disp8 # otherwise return 1 diff --git a/084emit-hex-array.subx b/084emit-hex-array.subx index e284b2c8..29f685f9 100644 --- a/084emit-hex-array.subx +++ b/084emit-hex-array.subx @@ -15,20 +15,20 @@ emit-hex-array: # out : (address buffered-file), arr : (address array byte) 57/push-edi # edi = out 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi - # edx = arr # <== 0xbdffffe4 + # edx = arr 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx - # curr/ecx = arr->data + # var curr/ecx : (address byte) = arr->data 8d/copy-address 1/mod/*+disp8 2/rm32/edx . . . 1/r32/ecx 4/disp8 . # copy edx+4 to ecx - # max/edx = arr->data + arr->length + # var max/edx : (address byte) = &arr->data[arr->length] 8b/copy 0/mod/indirect 2/rm32/edx . . . 2/r32/edx . . # copy *edx to edx 01/add 3/mod/direct 2/rm32/edx . . . 1/r32/ecx . . # add ecx to edx - # eax = 0 + # var c/eax : byte = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax $emit-hex-array:loop: # if (curr >= width) break 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-greater-or-equal-unsigned $emit-hex-array:end/disp8 - # emit-hex(out, *curr, width=1) + # emit-hex(out, c = *curr, width=1) # . . push args 68/push 1/imm32/width 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL @@ -71,7 +71,7 @@ test-emit-hex-array: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var arr/ecx (address array byte) = [01, 02, 03] + # var arr/ecx (ref array byte) = [01, 02, 03] 68/push 0x00030201/imm32 # bytes 01 02 03 68/push 3/imm32/length 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx diff --git a/092write-int.subx b/092write-int.subx index 7ebd473a..5fe1c4d3 100644 --- a/092write-int.subx +++ b/092write-int.subx @@ -5,7 +5,7 @@ # . 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-int: # out : (address stream), n : int +write-int: # out : (address stream byte), n : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp diff --git a/093array-equal.subx b/093array-equal.subx index 95cff9dd..f10a9463 100644 --- a/093array-equal.subx +++ b/093array-equal.subx @@ -40,27 +40,29 @@ array-equal?: # a : (address array int), b : (address array int) -> eax : boole 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi # edi = b 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi - # lena/edx = a->length + # var lena/edx : int = a->length 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx $array-equal?:lengths: # if (lena != b->length) return false 39/compare 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # compare *edi and edx 75/jump-if-not-equal $array-equal?:false/disp8 - # curra/esi = a->data + # var curra/esi : (address byte) = a->data 81 0/subop/add 3/mod/direct 6/rm32/esi . . . . . 4/imm32 # add to esi - # currb/edi = b->data + # var currb/edi : (address byte) = b->data 81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi - # i/ecx = i1/eax = i2/ebx = 0 + # var i/ecx : int = 0 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx + # var vala/eax : int + # var valb/ebx : int $array-equal?:loop: # if (i >= lena) return true 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 7d/jump-if-greater-or-equal $array-equal?:true/disp8 - # i1 = *curra + # vala = *curra 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax - # i2 = *currb + # valb = *currb 8b/copy 0/mod/indirect 7/rm32/edi . . . 3/r32/ebx . . # copy *edi to ebx - # if (i1 != i2) return false + # if (vala != valb) return false 39/compare 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # compare eax and ebx 75/jump-if-not-equal $array-equal?:false/disp8 # i += 4 @@ -91,10 +93,10 @@ test-compare-empty-with-empty-array: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ecx = [] + # var ecx : (ref array _) = [] 68/push 0/imm32/size 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var edx = [] + # var edx : (ref array _) = [] 68/push 0/imm32/size 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx # eax = array-equal?(ecx, edx) @@ -123,11 +125,11 @@ test-compare-empty-with-non-empty-array: # also checks length-mismatch code pat # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ecx = [1] + # var ecx : (ref array int) = [1] 68/push 1/imm32 68/push 4/imm32/size 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var edx = [] + # var edx : (ref array int) = [] 68/push 0/imm32/size 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx # eax = array-equal?(ecx, edx) @@ -156,13 +158,13 @@ test-compare-equal-arrays: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ecx = [1, 2, 3] + # var ecx : (ref array int) = [1, 2, 3] 68/push 3/imm32 68/push 2/imm32 68/push 1/imm32 68/push 0xc/imm32/size 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var edx = [1, 2, 3] + # var edx : (ref array int) = [1, 2, 3] 68/push 3/imm32 68/push 2/imm32 68/push 1/imm32 @@ -194,13 +196,13 @@ test-compare-inequal-arrays-equal-lengths: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ecx = [1, 4, 3] + # var ecx : (ref array int) = [1, 4, 3] 68/push 3/imm32 68/push 4/imm32 68/push 1/imm32 68/push 0xc/imm32/size 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var edx = [1, 2, 3] + # var edx : (ref array int) = [1, 2, 3] 68/push 3/imm32 68/push 2/imm32 68/push 1/imm32 @@ -228,9 +230,9 @@ test-compare-inequal-arrays-equal-lengths: 5d/pop-to-ebp c3/return -parse-array-of-ints: # ad : (address allocation-descriptor), s : (address string) -> result/eax : (address array int) +parse-array-of-ints: # ad : (address allocation-descriptor), s : (address string) -> result/eax : (handle array int) # pseudocode - # end = s->data + s->length + # end = &s->data[s->length] # curr = s->data # size = 0 # while true @@ -241,7 +243,7 @@ parse-array-of-ints: # ad : (address allocation-descriptor), s : (address strin # ++size # result = allocate(ad, (size+1)*4) # result->size = (size+1)*4 - # var slice = {s->data, 0} + # var slice : (ref slice) = {s->data, 0} # out = result->data # while true # if (slice->start >= end) break @@ -264,14 +266,14 @@ parse-array-of-ints: # ad : (address allocation-descriptor), s : (address strin 57/push-edi # esi = s 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # curr/ecx = s->data + # var curr/ecx : (address byte) = s->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy esi+4 to ecx - # end/edx = s->data + s->length + # var end/edx : (address byte) = &s->data[s->length] # . edx = s->length 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx # . edx += curr 01/add 3/mod/direct 2/rm32/edx . . . 1/r32/ecx . . # add ecx to edx - # size/ebx = 0 + # var size/ebx : int = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx $parse-array-of-ints:loop1: # if (curr >= end) break @@ -308,7 +310,7 @@ $parse-array-of-ints:loop1: 81 0/subop/add 3/mod/direct 3/rm32/ebx . . . . . 4/imm32 # add to ebx eb/jump $parse-array-of-ints:loop1/disp8 $parse-array-of-ints:break1: - # result/edi = allocate(ad, size+4) + # var result/edi : (handle array int) = allocate(ad, size+4) # . eax = allocate(ad, size+4) # . . push args 89/copy 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # copy ebx to eax @@ -324,7 +326,7 @@ $parse-array-of-ints:break1: # result->size = size 89/copy 0/mod/indirect 0/rm32/eax . . . 3/r32/ebx . . # copy ebx to *eax $parse-array-of-ints:pass2: - # var slice/ecx = {s->data, 0} + # var slice/ecx : (ref slice) = {s->data, 0} # . push 0 68/push 0/imm32/end # . push s->data @@ -332,7 +334,7 @@ $parse-array-of-ints:pass2: 51/push-ecx # . bookmark 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # out/ebx = result->data + # var out/ebx : (address byte) = result->data 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 3/r32/ebx 4/disp8 . # copy eax+4 to ebx $parse-array-of-ints:loop2: # if (slice->start >= end) break @@ -373,7 +375,7 @@ $parse-array-of-ints:loop2: e8/call parse-hex-int/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # *out = eax + # . *out = eax 89/copy 0/mod/indirect 3/rm32/ebx . . . 0/r32/eax . . # copy eax to *ebx # out += 4 81 0/subop/add 3/mod/direct 3/rm32/ebx . . . . . 4/imm32 # add to ebx @@ -402,7 +404,7 @@ test-parse-array-of-ints: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ecx = [1, 2, 3] + # var ecx : (ref array int) = [1, 2, 3] 68/push 3/imm32 68/push 2/imm32 68/push 1/imm32 @@ -496,7 +498,7 @@ test-parse-array-of-ints-extra-whitespace: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ecx = [1, 2, 3] + # var ecx : (ref array int) = [1, 2, 3] 68/push 3/imm32 68/push 2/imm32 68/push 1/imm32 @@ -540,7 +542,7 @@ check-array-equal: # a : (address array int), expected : (address string), msg 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 50/push-eax - # var b/ecx = parse-array-of-ints(Heap, expected) + # var b/ecx : (handle array int) = parse-array-of-ints(Heap, expected) # . eax = parse-array-of-ints(Heap, expected) # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) @@ -580,7 +582,7 @@ test-check-array-equal: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var ecx = [1, 2, 3] + # var ecx : (ref array int) = [1, 2, 3] 68/push 3/imm32 68/push 2/imm32 68/push 1/imm32 diff --git a/094next-word-or-string.subx b/094next-word-or-string.subx index 0fe24c6a..d3734fc9 100644 --- a/094next-word-or-string.subx +++ b/094next-word-or-string.subx @@ -33,7 +33,7 @@ $next-word-or-string:check0: # . if (eax < line->write) goto next check 3b/compare 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # compare eax with *esi 7c/jump-if-lesser $next-word-or-string:check-for-comment/disp8 - # . return out = {0, 0} + # . return out c7 0/subop/copy 0/mod/direct 7/rm32/edi . . . . . 0/imm32 # copy to *edi c7 0/subop/copy 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 0/imm32 # copy to *(edi+4) eb/jump $next-word-or-string:end/disp8 @@ -111,7 +111,7 @@ test-next-word-or-string: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -184,7 +184,7 @@ test-next-word-or-string-returns-whole-comment: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -257,7 +257,7 @@ test-next-word-or-string-returns-empty-slice-on-eof: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -299,7 +299,7 @@ test-next-word-or-string-returns-string-literal: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -362,7 +362,7 @@ test-next-word-or-string-returns-string-with-escapes: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx diff --git a/095stack.subx b/095stack.subx index 2e2f182e..692dece2 100644 --- a/095stack.subx +++ b/095stack.subx @@ -16,20 +16,20 @@ clear-stack: # s : (address stack) 51/push-ecx # eax = s 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax - # ecx = &s->data[s->length] + # var max/ecx : (address byte) = &s->data[s->length] 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy *(eax+4) to eax 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 8/disp8 . # copy eax+ecx+8 to ecx # s->top = 0 c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0/imm32 # copy to *eax - # eax = s->data + # var curr/eax : (address byte) = s->data 81 0/subop/add 3/mod/direct 0/rm32/eax . . . . . 8/imm32 # add to eax $clear-stack:loop: - # if (eax >= ecx) break + # if (curr >= max) break 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 73/jump-if-greater-or-equal-unsigned $clear-stack:end/disp8 - # *eax = 0 + # *curr = 0 c6 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0/imm8 # copy byte to *eax - # ++eax + # ++curr 40/increment-eax eb/jump $clear-stack:loop/disp8 $clear-stack:end: @@ -343,7 +343,7 @@ top: # s : (address stack) -> n/eax : int # if (s->top <= 0) abort 81 7/subop/compare 0/mod/indirect 6/rm32/esi . . . . . 0/imm32 # compare *esi 7e/jump-if-lesser-or-equal $top:abort/disp8 - # eax = s->data[s->top - 4] + # n = s->data[s->top - 4] 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx 81 5/subop/subtract 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # subtract from ecx 8b/copy 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 8/disp8 . # copy *(esi+ecx+8) to eax diff --git a/apps/assort b/apps/assort index 05e615a7..b8cba438 100755 Binary files a/apps/assort and b/apps/assort differ diff --git a/apps/assort.subx b/apps/assort.subx index 123ad64e..0aa18555 100644 --- a/apps/assort.subx +++ b/apps/assort.subx @@ -50,8 +50,8 @@ Entry: # run tests if necessary, convert stdin if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto interactive - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto interactive + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-assort-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 @@ -60,7 +60,7 @@ Entry: # run tests if necessary, convert stdin if not eb/jump $subx-assort-main:end/disp8 $subx-assort-main:interactive: # - otherwise convert stdin - # var ed/eax : exit-descriptor + # var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # configure ed to really exit() @@ -97,7 +97,7 @@ subx-assort: # in : (address buffered-file), out : (address buffered-file) 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx - # var table/ecx : (address stream byte 10*8) + # var table/ecx : (ref stream {string, (address stream byte)} 80) # 10 rows * 8 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x50/imm32 # subtract from esp 68/push 0x50/imm32/length 68/push 0/imm32/read @@ -450,8 +450,10 @@ test-subx-assort: 5d/pop-to-ebp c3/return +# type string_key = (address array byte) + # beware: leaks memory (one name per segment read) -read-segments: # in : (address buffered-file), table : (address stream {string, (address stream byte)}) +read-segments: # in : (address buffered-file), table : (address stream {string_key, (handle stream byte)}) # pseudocode: # var curr-segment : (handle stream byte) = 0 # var line : (stream byte 512) @@ -494,13 +496,13 @@ read-segments: # in : (address buffered-file), table : (address stream {string, 52/push-edx 53/push-ebx 56/push-esi - # var line/ecx : (stream byte 512) + # var line/ecx : (ref stream byte 512) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var word-slice/edx = {0, 0} + # var word-slice/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -583,8 +585,8 @@ $read-segments:check1: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) continue - 3d/compare-eax-and 0/imm32 + # . if (eax != false) continue + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $read-segments:loop/disp32 $read-segments:check-for-comment: #? # print("check for comment\n") {{{ @@ -597,12 +599,12 @@ $read-segments:check-for-comment: #? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp #? # }}} # if (slice-starts-with?(word-slice, "#")) continue - # . start/esi = word-slice->start + # . var start/esi : (address byte) = word-slice->start 8b/copy 0/mod/indirect 2/rm32/edx . . . 6/r32/esi . . # copy *ecx to esi - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL - # . if (eax == '#') continue + # . if (c == '#') continue 3d/compare-eax-and 0x23/imm32/hash 0f 84/jump-if-equal $read-segments:loop/disp32 $read-segments:check-for-segment-header: @@ -664,8 +666,8 @@ $read-segments:check-for-segment-header: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto check3 - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto check3 + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $read-segments:regular-line/disp32 # segment-name = next-word-or-string(line) # . . push args @@ -715,7 +717,7 @@ $read-segments:check-for-segment-header: #? # . . discard args #? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp #? # }}} - # segment-slot/eax = leaky-get-or-insert-slice(table, segment-name, row-size=8) + # var segment-slot/eax : (address handle stream byte) = leaky-get-or-insert-slice(table, segment-name, row-size=8) # . . push args 68/push 8/imm32/row-size 52/push-edx @@ -841,10 +843,10 @@ $read-segments:end: 5d/pop-to-ebp c3/return -write-segments: # out : (address buffered-file), table : (address stream {string, (address stream byte)}) +write-segments: # out : (address buffered-file), table : (address stream {string_key, (handle stream byte)}) # pseudocode: # var curr = table->data - # var max = table->data + table->write + # var max = &table->data[table->write] # while curr < max # stream = table[i].stream # write-stream-data(out, stream) @@ -860,17 +862,17 @@ write-segments: # out : (address buffered-file), table : (address stream {strin 56/push-esi # esi = table 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # write/edx = table->write + # var write/edx : int = table->write 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx - # curr/esi = table->data + # var curr/esi : (address byte) = table->data 81 0/subop/add 3/mod/direct 6/rm32/esi . . . . . 0xc/imm32 # add to eax - # max/edx = curr + write + # var max/edx : (address byte) = curr + write 01/add 3/mod/direct 2/rm32/edx . . . 6/r32/esi . . # add esi to edx $write-segments:loop: # if (curr >= max) break 39/compare 3/mod/direct 6/rm32/esi . . . 2/r32/edx . . # compare esi with edx 73/jump-if-greater-or-equal-unsigned $write-segments:break/disp8 - # stream/eax = table[i].stream + # var stream/eax : (address stream byte) = table[i].stream 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) to eax # write-stream-data(out, stream) # . . push args diff --git a/apps/braces b/apps/braces index 7307be11..ef7eb54a 100755 Binary files a/apps/braces and b/apps/braces differ diff --git a/apps/braces.subx b/apps/braces.subx index 27810a86..95b6a7ea 100644 --- a/apps/braces.subx +++ b/apps/braces.subx @@ -77,8 +77,8 @@ $subx-braces-main:end: subx-braces: # in : (address buffered-file), out : (address buffered-file) # pseudocode: - # var line : (stream byte 512) - # var label-stack : (stack address 32) # at most 32 levels of nesting + # var line : (ref stream byte 512) + # var label-stack : (stack int 32) # at most 32 levels of nesting # var next-label-id : int = 1 # while true # clear-stream(line) @@ -123,20 +123,20 @@ subx-braces: # in : (address buffered-file), out : (address buffered-file) 57/push-edi # esi = in 8b/-> *(ebp+8) 6/r32/esi - # var line/ecx : (stream byte 512) + # var line/ecx : (ref stream byte 512) 81 5/subop/subtract %esp 0x200/imm32 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/<- %ecx 4/r32/esp - # var label-stack/edx : (stack int 32) + # var label-stack/edx : (ref stack int 32) 81 5/subop/subtract %esp 0x80/imm32 68/push 0x80/imm32/length 68/push 0/imm32/top 89/<- %edx 4/r32/esp - # next-label-id/ebx = 1 + # var next-label-id/ebx : int = 1 c7 0/subop/copy %ebx 1/imm32 - # var word-slice/edi = {0, 0} + # var word-slice/edi : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %edi 4/r32/esp @@ -201,8 +201,8 @@ $subx-braces:check-for-break: # if (!slice-starts-with?(word-slice, "break/")) goto next check # . eax = slice-starts-with?(word-slice, "break/") (slice-starts-with? %edi "break/") - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-braces:check-for-loop/disp8 $subx-braces:emit-break: (top %edx) @@ -217,8 +217,8 @@ $subx-braces:check-for-loop: # if (!slice-starts-with?(word-slice, "loop/")) emit word # . eax = slice-starts-with?(word-slice, "loop/") (slice-starts-with? %edi "loop/") - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-braces:emit-word-slice/disp8 $subx-braces:emit-loop: (top %edx) diff --git a/apps/calls b/apps/calls index 418d230e..15bbc5db 100755 Binary files a/apps/calls and b/apps/calls differ diff --git a/apps/calls.subx b/apps/calls.subx index 28e2ff63..030509ed 100644 --- a/apps/calls.subx +++ b/apps/calls.subx @@ -51,8 +51,8 @@ Entry: # run tests if necessary, convert stdin if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 - # . if (eax == 0) goto run-main - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto run-main + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-calls-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 @@ -77,8 +77,8 @@ $subx-calls-main:end: subx-calls: # in : (address buffered-file), out : (address buffered-file) # pseudocode: - # var line : (stream byte 512) - # var words : (stream slice 16) # at most function name and 15 args + # var line : (ref stream byte 512) + # var words : (ref stream slice 16) # at most function name and 15 args # while true # clear-stream(line) # read-line-buffered(in, line) @@ -105,13 +105,13 @@ subx-calls: # in : (address buffered-file), out : (address buffered-file) 51/push-ecx 52/push-edx 56/push-esi - # var line/esi : (address stream byte) = stream(512) + # var line/esi : (ref stream byte 512) 81 5/subop/subtract %esp 0x200/imm32 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/<- %esi 4/r32/esp - # var words/edx : (address stream slice) = stream(16, 8) + # var words/edx : (ref stream slice 128) # 16 rows * 8 bytes/row 81 5/subop/subtract %esp 0x80/imm32 68/push 0x80/imm32/length 68/push 0/imm32/read @@ -233,7 +233,7 @@ $subx-calls:end: parse-line: # line : (address stream byte), words : (address stream slice) # pseudocode: - # var word-slice : (address slice) + # var word-slice : (ref slice) # while true # word-slice = next-word-string-or-expression-without-metadata(line) # if slice-empty?(word-slice) @@ -246,7 +246,7 @@ parse-line: # line : (address stream byte), words : (address stream slice) 89/<- %ebp 4/r32/esp # . save registers 51/push-ecx - # var word-slice/ecx : (address slice) = {0, 0} + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -268,8 +268,8 @@ $parse-line:check1: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $parse-line:end/disp32 #? # dump word-slice {{{ #? # . write(2/stderr, "w: ") @@ -381,9 +381,9 @@ emit-call: # out : (address buffered-file), words : (address stream slice) 8b/-> *esi 1/r32/ecx 81 5/subop/subtract %ecx 8/imm32 0f 8c/jump-if-lesser $emit-call:error1/disp32 - # curr/ecx = &words->data[words->write-8] + # var curr/ecx : (address slice) = &words->data[words->write-8] 8d/copy-address *(esi+ecx+0xc) 1/r32/ecx - # min/edx = words->data + # var min/edx : (address byte) = words->data 8d/copy-address *(esi+0xc) 2/r32/edx # - emit pushes $emit-call:push-loop: @@ -391,15 +391,15 @@ $emit-call:push-loop: 39/compare %ecx 2/r32/edx 0f 8e/jump-if-lesser-or-equal $emit-call:call-instruction/disp32 # if (*curr->start in '%' '*') goto push-rm32 - # . eax = curr->start + # . var start/eax : (address byte) = curr->start 8b/-> *ecx 0/r32/eax - # . eax = (byte)*eax + # . var c/eax : byte = *eax 8b/-> *eax 0/r32/eax 81 4/subop/and %eax 0xff/imm32 - # . if (eax == '%') goto push-rm32 + # . if (c == '%') goto push-rm32 3d/compare-eax-and 0x25/imm32/percent 74/jump-if-equal $emit-call:push-rm32/disp8 - # . if (eax == '*') goto push-rm32 + # . if (c == '*') goto push-rm32 3d/compare-eax-and 0x2a/imm32/asterisk 74/jump-if-equal $emit-call:push-rm32/disp8 $emit-call:push-imm32: @@ -741,7 +741,7 @@ test-subx-calls-processes-calls: 5d/pop-to-ebp c3/return -next-word-string-or-expression-without-metadata: # line : (address stream), out : (address slice) +next-word-string-or-expression-without-metadata: # line : (address stream byte), out : (address slice) # pseudocode: # skip-chars-matching(line, ' ') # if line->read >= line->write # end of line @@ -830,7 +830,7 @@ $next-word-string-or-expression-without-metadata:check-for-comment: 8d/copy-address *(esi+ecx+0xc) 0/r32/eax 89/<- *edi 0/r32/eax # if (line->data[line->read] != '#') goto next check - # . eax = line->data[line->read] + # . var eax : byte = line->data[line->read] 31/xor %eax 0/r32/eax 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL # . if (eax != '#') goto next check @@ -1191,7 +1191,7 @@ test-next-word-string-or-expression-without-metadata: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1264,7 +1264,7 @@ test-next-word-string-or-expression-without-metadata-returns-whole-comment: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1337,7 +1337,7 @@ test-next-word-string-or-expression-without-metadata-returns-empty-slice-on-eof: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1379,7 +1379,7 @@ test-next-word-string-or-expression-without-metadata-returns-string-literal: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1442,7 +1442,7 @@ test-next-word-string-or-expression-without-metadata-returns-string-with-escapes e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1505,7 +1505,7 @@ test-next-word-string-or-expression-without-metadata-returns-whole-expression: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1568,7 +1568,7 @@ test-next-word-string-or-expression-without-metadata-returns-eol-on-trailing-clo e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1623,7 +1623,7 @@ test-next-word-string-or-expression-without-metadata-handles-comment-after-trail e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1678,7 +1678,7 @@ test-next-word-string-or-expression-without-metadata-handles-newline-after-trail e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1733,7 +1733,7 @@ test-next-word-string-or-expression-without-metadata-stops-at-close-paren: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp diff --git a/apps/crenshaw2-1 b/apps/crenshaw2-1 index 7103908f..a579ee45 100755 Binary files a/apps/crenshaw2-1 and b/apps/crenshaw2-1 differ diff --git a/apps/crenshaw2-1.subx b/apps/crenshaw2-1.subx index 2217e430..228f4696 100644 --- a/apps/crenshaw2-1.subx +++ b/apps/crenshaw2-1.subx @@ -57,8 +57,8 @@ Entry: # run tests if necessary, call 'compile' if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto run-main - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto run-main + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $run-main/disp8 # run-tests() e8/call run-tests/disp32 @@ -67,7 +67,7 @@ Entry: # run tests if necessary, call 'compile' if not eb/jump $main:end/disp8 $run-main: # - otherwise read a program from stdin and emit its translation to stdout - # var ed/eax : exit-descriptor + # var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # configure ed to really exit() @@ -90,7 +90,7 @@ $main:end: cd/syscall 0x80/imm8 # the main entry point -compile: # in : (address buffered-file), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) +compile: # in : (address buffered-file), out : fd or (address stream byte), err : fd or (address stream byte), ed : (address exit-descriptor) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -105,7 +105,7 @@ compile: # in : (address buffered-file), out : fd or (address stream), err : fd e8/call get-char/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var num/ecx : (address stream) on the stack + # var num/ecx : (ref stream byte 7) # Numbers can be 32 bits or 8 hex bytes long. One of them will be in 'Look', so we need space for 7 bytes. # Sizing the stream just right buys us overflow-handling for free inside 'get-num'. # Add 12 bytes for 'read', 'write' and 'length' fields, for a total of 19 bytes, or 0x13 in hex. @@ -187,10 +187,11 @@ $compile:end: 5d/pop-to-ebp c3/return -# Read a single digit into 'out'. Abort if there are none, or if there is no space in 'out'. -# Input comes from the global variable 'Look', and we leave the next byte from -# 'in' into it on exit. -get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) +# Read a single digit into 'out'. Abort if there are none, or if there is no +# space in 'out'. +# Input comes from the global variable 'Look' (first byte) and the argument +# 'in' (rest). We leave the next byte from 'in' into 'Look' on exit. +get-num: # in : (address buffered-file), out : (address stream byte), err : fd or (address stream byte), ed : (address exit-descriptor) # pseudocode: # if (!is-digit?(Look)) expected(ed, err, "integer") # if out->write >= out->length @@ -221,8 +222,8 @@ 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) - 3d/compare-eax-and 0/imm32 + # . if (eax == false) + 3d/compare-eax-and 0/imm32/false 75/jump-if-not-equal $get-num:main/disp8 # . expected(ed, err, "integer") # . . push args @@ -251,6 +252,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 +$get-num:loop: # 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 @@ -337,7 +339,7 @@ test-get-num-reads-single-digit: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'get-num' below - # . var ed/eax : exit-descriptor + # . var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # . tailor-exit-descriptor(ed, 16) @@ -426,7 +428,7 @@ test-get-num-aborts-on-non-digit-in-Look: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'get-num' below - # . var ed/eax : (address exit-descriptor) + # . var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # . tailor-exit-descriptor(ed, 16) @@ -468,7 +470,7 @@ test-get-num-aborts-on-non-digit-in-Look: ## helpers # write(f, "Error: "+s+" expected\n") then stop(ed, 1) -expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) +expected: # ed : (address exit-descriptor), f : fd or (address stream byte), s : (address array byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -488,7 +490,7 @@ expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (ad e8/call write/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # write(f, " expected") + # write(f, " expected\n") # . . push args 68/push " expected\n"/imm32 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) diff --git a/apps/crenshaw2-1b b/apps/crenshaw2-1b index 31b9cac1..a398a0bc 100755 Binary files a/apps/crenshaw2-1b and b/apps/crenshaw2-1b differ diff --git a/apps/crenshaw2-1b.subx b/apps/crenshaw2-1b.subx index 58467aa9..374625e9 100644 --- a/apps/crenshaw2-1b.subx +++ b/apps/crenshaw2-1b.subx @@ -57,8 +57,8 @@ Entry: # run tests if necessary, call 'compile' if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto run-main - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto run-main + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $run-main/disp8 # run-tests() e8/call run-tests/disp32 @@ -67,7 +67,7 @@ Entry: # run tests if necessary, call 'compile' if not eb/jump $main:end/disp8 $run-main: # - otherwise read a program from stdin and emit its translation to stdout - # var ed/eax : exit-descriptor + # var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # configure ed to really exit() @@ -90,7 +90,7 @@ $main:end: cd/syscall 0x80/imm8 # the main entry point -compile: # in : (address buffered-file), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) +compile: # in : (address buffered-file), out : fd or (address stream byte), err : fd or (address stream byte), ed : (address exit-descriptor) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -105,7 +105,7 @@ compile: # in : (address buffered-file), out : fd or (address stream), err : fd e8/call get-char/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var num/ecx : (address stream) on the stack + # var num/ecx : (ref stream byte 7) # Numbers can be 32 bits or 8 hex bytes long. One of them will be in 'Look', so we need space for 7 bytes. # Sizing the stream just right buys us overflow-handling for free inside 'get-num'. # Add 12 bytes for 'read', 'write' and 'length' fields, for a total of 19 bytes, or 0x13 in hex. @@ -191,7 +191,7 @@ $compile:end: # no space in 'out'. # Input comes from the global variable 'Look' (first byte) and the argument # '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) +get-num: # in : (address buffered-file), out : (address stream byte), err : fd or (address stream byte), ed : (address exit-descriptor) # pseudocode: # if (!is-digit?(Look)) expected(ed, err, "integer") # do @@ -227,8 +227,8 @@ 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) - 3d/compare-eax-and 0/imm32 + # . if (eax == false) + 3d/compare-eax-and 0/imm32/false 75/jump-if-not-equal $get-num:main/disp8 # . expected(ed, err, "integer") # . . push args @@ -292,8 +292,8 @@ $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 != 0) loop - 3d/compare-eax-and 0/imm32 + # . if (eax != false) loop + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $get-num:loop/disp32 $get-num:loop-end: # persist necessary variables from registers @@ -355,7 +355,7 @@ test-get-num-reads-single-digit: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'get-num' below - # . var ed/eax : exit-descriptor + # . var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # . tailor-exit-descriptor(ed, 16) @@ -444,7 +444,7 @@ test-get-num-aborts-on-non-digit-in-Look: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'get-num' below - # . var ed/eax : (address exit-descriptor) + # . var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # . tailor-exit-descriptor(ed, 16) @@ -527,7 +527,7 @@ test-get-num-reads-multiple-digits: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'get-num' below - # . var ed/eax : (address exit-descriptor) + # . var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # . tailor-exit-descriptor(ed, 16) @@ -616,7 +616,7 @@ test-get-num-reads-multiple-digits-followed-by-nondigit: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'get-num' below - # . var ed/eax : (address exit-descriptor) + # . var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # . tailor-exit-descriptor(ed, 16) @@ -664,7 +664,7 @@ test-get-num-reads-multiple-digits-followed-by-nondigit: ## helpers # write(f, "Error: "+s+" expected\n") then stop(ed, 1) -expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) +expected: # ed : (address exit-descriptor), f : fd or (address stream byte), s : (address array byte) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp diff --git a/apps/dquotes b/apps/dquotes index ec6808ec..ae526a6c 100755 Binary files a/apps/dquotes and b/apps/dquotes differ diff --git a/apps/dquotes.subx b/apps/dquotes.subx index 5186eda6..4b985fbb 100644 --- a/apps/dquotes.subx +++ b/apps/dquotes.subx @@ -46,8 +46,8 @@ Entry: # run tests if necessary, convert stdin if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto interactive - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto interactive + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-dquotes-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 @@ -56,7 +56,7 @@ Entry: # run tests if necessary, convert stdin if not eb/jump $subx-dquotes-main:end/disp8 $subx-dquotes-main:interactive: # - otherwise convert stdin - # var ed/eax : exit-descriptor + # var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # configure ed to really exit() @@ -84,7 +84,7 @@ $subx-dquotes-main:end: subx-dquotes: # in : (address buffered-file), out : (address buffered-file) # pseudocode: - # var line : (stream byte 512) + # var line : (ref stream byte 512) # var new-data-segment : (handle stream byte) = new-stream(Heap, Segment-size, 1) # # write(new-data-segment, "== data\n") @@ -125,13 +125,13 @@ subx-dquotes: # in : (address buffered-file), out : (address buffered-file) 53/push-ebx 56/push-esi 57/push-edi - # var line/ecx : (address stream byte) = stream(512) + # var line/ecx : (ref stream byte 512) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var word-slice/edx = {0, 0} + # var word-slice/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -193,17 +193,17 @@ $subx-dquotes:check1: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $subx-dquotes:next-line/disp32 $subx-dquotes:check-for-comment: # if (slice-starts-with?(word-slice, "#")) continue - # . start/esi = word-slice->start + # . var start/esi : (address byte) = word-slice->start 8b/copy 0/mod/indirect 2/rm32/edx . . . 6/r32/esi . . # copy *edx to esi - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL - # . if (eax == '#') continue + # . if (c == '#') continue 3d/compare-eax-and 0x23/imm32/hash 74/jump-if-equal $subx-dquotes:word-loop/disp8 $subx-dquotes:check-for-string-literal: @@ -287,7 +287,7 @@ $subx-dquotes:end: # Write out 'string-literal' in a new format to 'out-segment', assign it a new # label, and write the new label out to 'out'. -process-string-literal: # string-literal : (address slice), out : (address buffered-file), out-segment : (address stream) +process-string-literal: # string-literal : (address slice), out : (address buffered-file), out-segment : (address stream byte) # pseudocode: # print(out-segment, "_string#{Next-string-literal}:\n") # emit-string-literal-data(out-segment, string-literal) @@ -300,7 +300,7 @@ process-string-literal: # string-literal : (address slice), out : (address buff 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 51/push-ecx - # var int32-stream/ecx = stream(10) # number of decimal digits a 32-bit number can have + # var int32-stream/ecx : (ref stream byte 10) # number of decimal digits a 32-bit number can have 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa/imm32 # subtract from esp 68/push 0xa/imm32/decimal-digits-in-32bit-number 68/push 0/imm32/read @@ -846,7 +846,7 @@ test-subx-dquotes-processes-string-literals: c3/return # generate the data segment contents byte by byte for a given slice -emit-string-literal-data: # out : (address stream), word : (address slice) +emit-string-literal-data: # out : (address stream byte), word : (address slice) # pseudocode # len = string-length-at-start-of-slice(word->start, word->end) # print(out, "#{len}/imm32 ") @@ -885,14 +885,14 @@ emit-string-literal-data: # out : (address stream), word : (address slice) 56/push-esi # esi = word 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # idx/ebx = 0 + # var idx/ebx : int = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - # curr/edx = word->start + # var curr/edx : (address byte) = word->start 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx - # max/esi = word->end + # var max/esi : (address byte) = word->end 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi $emit-string-literal-data:emit-length: - # len/eax = string-length-at-start-of-slice(word->start, word->end) + # var len/eax : int = string-length-at-start-of-slice(word->start, word->end) # . . push args 56/push-esi 52/push-edx @@ -920,7 +920,7 @@ $emit-string-literal-data:emit-length: $emit-string-literal-data:loop-init: # ++curr # skip initial '"' 42/increment-edx - # c/ecx = 0 + # var c/ecx : byte = 0 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx $emit-string-literal-data:loop: # if (curr >= max) break @@ -955,15 +955,15 @@ $emit-string-literal-data:emit: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # if (is-alphanumeric?(*curr)) print(out, "/#{*curr}") - # . eax = is-alphanumeric?(CL) + # . var eax : boolean = is-alphanumeric?(CL) # . . push args 51/push-ecx # . . call e8/call is-alphanumeric?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax == 0) goto char-done - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto char-done + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-string-literal-data:char-done/disp8 # . write(out, "/") # . . push args @@ -1027,22 +1027,22 @@ is-alphanumeric?: # c : int -> eax : boolean 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # eax = c 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax - # if (eax < '0') return false + # if (c < '0') return false 3d/compare-eax-with 0x30/imm32/0 7c/jump-if-lesser $is-alphanumeric?:false/disp8 - # if (eax <= '9') return true + # if (c <= '9') return true 3d/compare-eax-with 0x39/imm32/9 7e/jump-if-lesser-or-equal $is-alphanumeric?:true/disp8 - # if (eax < 'A') return false + # if (c < 'A') return false 3d/compare-eax-with 0x41/imm32/A 7c/jump-if-lesser $is-alphanumeric?:false/disp8 - # if (eax <= 'Z') return true + # if (c <= 'Z') return true 3d/compare-eax-with 0x5a/imm32/Z 7e/jump-if-lesser-or-equal $is-alphanumeric?:true/disp8 - # if (eax < 'a') return false + # if (c < 'a') return false 3d/compare-eax-with 0x61/imm32/a 7c/jump-if-lesser $is-alphanumeric?:false/disp8 - # if (eax <= 'z') return true + # if (c <= 'z') return true 3d/compare-eax-with 0x7a/imm32/z 7e/jump-if-lesser-or-equal $is-alphanumeric?:true/disp8 # return false @@ -1381,7 +1381,7 @@ test-emit-string-literal-data-handles-newline-escape: # emit everything from a word except the initial datum emit-metadata: # out : (address buffered-file), word : (address slice) # pseudocode - # var slice = {0, word->end} + # var slice : (ref slice) = {0, word->end} # curr = word->start # if *curr == '"' # curr = skip-string-in-slice(curr, word->end) @@ -1406,11 +1406,11 @@ emit-metadata: # out : (address buffered-file), word : (address slice) 56/push-esi # esi = word 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # curr/ecx = word->start + # var curr/ecx : (address byte) = word->start 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx - # end/edx = word->end + # var end/edx : (address byte) = word->end 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx - # var slice/ebx = {0, end} + # var slice/ebx : (ref slice) = {0, end} 52/push-edx 68/push 0/imm32 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx @@ -1790,9 +1790,9 @@ string-length-at-start-of-slice: # curr : (address byte), end : (address byte) 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx # edx = end 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx - # length/eax = 0 + # var length/eax : int = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - # ebx = 0 + # var c/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx # skip initial dquote 41/increment-ecx @@ -1800,14 +1800,14 @@ $string-length-at-start-of-slice:loop: # if (curr >= end) return length 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 73/jump-if-greater-unsigned-or-equal $string-length-at-start-of-slice:end/disp8 - # BL = *curr + # c = *curr 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 3/r32/BL . . # copy byte at *ecx to BL $string-length-at-start-of-slice:dquote: - # if (ebx == '"') break + # if (c == '"') break 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x22/imm32/dquote # compare ebx 74/jump-if-equal $string-length-at-start-of-slice:end/disp8 $string-length-at-start-of-slice:check-for-escape: - # if (ebx == '\') escape next char + # if (c == '\') escape next char 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x5c/imm32/backslash # compare ebx 75/jump-if-not-equal $string-length-at-start-of-slice:continue/disp8 $string-length-at-start-of-slice:escape: diff --git a/apps/factorial b/apps/factorial index d3cee9da..dd981d0d 100755 Binary files a/apps/factorial and b/apps/factorial differ diff --git a/apps/factorial.subx b/apps/factorial.subx index 26cf3f9d..019329e3 100644 --- a/apps/factorial.subx +++ b/apps/factorial.subx @@ -45,8 +45,8 @@ Entry: # run tests if necessary, compute `factorial(5)` if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto run-main - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto run-main + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $run-main/disp8 # run-tests() e8/call run-tests/disp32 @@ -77,10 +77,10 @@ factorial: # n : int -> int/eax b8/copy-to-eax 1/imm32 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 1/imm32 # compare *(ebp+8) 7e/jump-if-<= $factorial:end/disp8 - # ebx = n-1 + # var ebx : int = n-1 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 3/r32/ebx 8/disp8 . # copy *(ebp+8) to ebx 4b/decrement-ebx - # eax = factorial(n-1) + # var eax : int = factorial(n-1) # . . push args 53/push-ebx # . . call diff --git a/apps/handle b/apps/handle index fdc96dcf..23993ca6 100755 Binary files a/apps/handle and b/apps/handle differ diff --git a/apps/handle.subx b/apps/handle.subx index 7c4657ec..07611596 100644 --- a/apps/handle.subx +++ b/apps/handle.subx @@ -44,7 +44,7 @@ $handle-main:end: b8/copy-to-eax 1/imm32/exit cd/syscall 0x80/imm8 -new: # ad : (address allocation-descriptor), n : int, out : (address handle) +new: # ad : (address allocation-descriptor), n : int, out : (handle _) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -55,7 +55,7 @@ new: # ad : (address allocation-descriptor), n : int, out : (address handle) # ecx = n+4 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx - # eax = allocate(ad, ecx) + # var eax : (handle _) = allocate(ad, ecx) # . . push args 51/push-ecx ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) @@ -96,7 +96,7 @@ test-new: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var heap/edx : (address allocation-descriptor) = {0, 0} + # var heap/edx : (ref allocation-descriptor) 68/push 0/imm32/limit 68/push 0/imm32/curr 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -110,7 +110,7 @@ test-new: 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # *Next-alloc-id = 0x34 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id - # var handle/ecx = {0, 0} + # var handle/ecx : (ref handle) 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -166,7 +166,7 @@ _pending-test-new-failure: # . *Next-alloc-id = 0x34 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id # define an allocation-descriptor with no space left - # . var ad/eax : (address allocation-descriptor) = {0x10, 0x10} + # . var ad/eax : (ref allocation-descriptor) = {0x10, 0x10} 68/push 0x10/imm32/limit 68/push 0x10/imm32/curr 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax @@ -282,7 +282,7 @@ test-lookup-success: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers - # var heap/ebx : (address allocation-descriptor) = {0, 0} + # var heap/ebx : (ref allocation-descriptor) 68/push 0/imm32/limit 68/push 0/imm32/curr 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx @@ -294,7 +294,7 @@ test-lookup-success: e8/call new-segment/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # var handle/ecx = {0, 0} + # var handle/ecx : (ref handle) 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -350,7 +350,7 @@ test-lookup-failure: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # var heap/esi : (address allocation-descriptor) = {0, 0} + # var heap/esi : (ref allocation-descriptor) 68/push 0/imm32/limit 68/push 0/imm32/curr 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi @@ -362,7 +362,7 @@ test-lookup-failure: e8/call new-segment/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # var h1/ecx = {0, 0} + # var h1/ecx : (ref handle) 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -381,7 +381,7 @@ test-lookup-failure: # reset heap->curr to mimic reclamation 89/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy ebx to *esi # second allocation that returns the same address as the first - # var h2/edx = {0, 0} + # var h2/edx : (ref handle) 68/push 0/imm32/address 68/push 0/imm32/alloc-id 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -422,7 +422,7 @@ test-lookup-failure: == data # Monotonically increasing counter for calls to 'new' -Next-alloc-id: +Next-alloc-id: # int 1/imm32 # . . vim:nowrap:textwidth=0 diff --git a/apps/hex b/apps/hex index 785d81f8..d349dea8 100755 Binary files a/apps/hex and b/apps/hex differ diff --git a/apps/hex.subx b/apps/hex.subx index 80469961..09e394bd 100644 --- a/apps/hex.subx +++ b/apps/hex.subx @@ -44,8 +44,8 @@ Entry: # run tests if necessary, convert stdin if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto interactive - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto interactive + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-hex-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 @@ -54,7 +54,7 @@ Entry: # run tests if necessary, convert stdin if not eb/jump $subx-hex-main:end/disp8 $subx-hex-main:interactive: # - otherwise convert stdin - # var ed/eax : exit-descriptor + # var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # configure ed to really exit() @@ -247,7 +247,7 @@ test-convert-next-octet: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -337,7 +337,7 @@ test-convert-next-octet-handles-Eof: 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # don't initialize '_test-stream' # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -435,7 +435,7 @@ test-convert-next-octet-aborts-on-single-hex-byte: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -604,7 +604,7 @@ test-scan-next-byte: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -702,7 +702,7 @@ test-scan-next-byte-skips-whitespace: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -808,7 +808,7 @@ test-scan-next-byte-skips-comment: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -914,7 +914,7 @@ test-scan-next-byte-skips-comment-and-whitespace: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -1022,7 +1022,7 @@ test-scan-next-byte-skips-whitespace-and-comment: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -1120,7 +1120,7 @@ test-scan-next-byte-reads-final-byte: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -1210,7 +1210,7 @@ test-scan-next-byte-handles-Eof: 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # leave '_test-stream' empty # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) @@ -1308,7 +1308,7 @@ test-scan-next-byte-aborts-on-invalid-byte: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - # . var ed/ecx : exit-descriptor + # . var ed/ecx : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx # . tailor-exit-descriptor(ed, 12) diff --git a/apps/mu b/apps/mu index e95a43f1..0e2717c7 100755 Binary files a/apps/mu and b/apps/mu differ diff --git a/apps/mu.subx b/apps/mu.subx index b0cf03c1..e4b8604b 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -7,7 +7,8 @@ # == Goals # 1. Be memory safe. It should be impossible to corrupt the heap, or to create # a bad pointer. (Requires strong type safety.) -# 2. Do as little as possible to achieve goal 1. +# 2. Do as little as possible to achieve goal 1. The translator should be +# implementable in machine code. # - minimize impedance mismatch between source language and SubX target # (e.g. programmer manages registers manually) # - checks over syntax @@ -63,9 +64,10 @@ # } # # - variable definitions on the stack. E.g.: -# - var foo: int -# - var bar: (array int 3) +# - var foo: (ref int) +# - var bar: (ref array int 3) # There's no initializer; variables are automatically initialized. +# The type of a local variable is either word-length (4 bytes) or starts with 'ref'. # # - variables definitions in a register. E.g.: # - var foo/eax : int <- add bar 1 @@ -81,20 +83,24 @@ # user-defined types: 'type' for structs, 'choice' for unions # short-lived 'address' type for efficiently writing inside nested structs # +# We don't have 'handle' types yet, but we try to distinguish 'ref', 'handle' +# and 'address' in comments. Their definitions are in layer 50, but really you +# can ignore the distinctions on a first reading of this program. +# # Formal types: # A program is a linked list of functions # A function contains: -# name: string +# name: (handle array byte) # inouts: linked list of vars <-- 'inouts' is more precise than 'inputs' -# data: (address var) -# next: (address list) +# data: (handle var) +# next: (handle list) # outputs: linked list of vars -# data: (address var) -# next: (address list) -# body: block +# data: (handle var) +# next: (handle list) +# body: (handle block) # A var-type contains: -# name: string -# type: s-expression of type ids +# name: (handle array byte) +# type: (handle s-expression type-id) # # A statement can be: # tag 0: a block @@ -105,29 +111,29 @@ # # A block contains: # tag: 0 -# statements: (address list statement) +# statements: (handle list statement) # # A regular statement contains: # tag: 1 -# operation: string -# inouts: (address list operand) -# outputs: (address list var) +# operation: (handle array byte) +# inouts: (handle list operand) +# outputs: (handle list var) # # A variable defined on the stack contains: # tag: 2 -# name: string -# type: type-tree +# name: (handle array byte) +# type: (handle s-expression type-id) # # A variable defined in a register contains: # tag: 3 -# name: string -# type: type-tree -# reg: string +# name: (handle array byte) +# type: (handle s-expression type-id) +# reg: (handle array byte) # # A named block contains: # tag: 4 -# name: string -# statements: (address list statement) +# name: (handle array byte) +# statements: (handle list statement) # == Translation: managing the stack # Now that we know what the language looks like in the large, let's think @@ -151,11 +157,11 @@ # Formal types: # live-vars: stack of vars # var: -# name: string +# name: (handle array byte) # type: s-expression? Just a type id for now. # block: int # stack-offset: int (added to ebp) -# register: string +# register: (handle array byte) # either usual register names # or '*' to indicate any register # At most one of stack-offset or register-index must be non-zero. @@ -172,11 +178,11 @@ # # Formal types: # functions: linked list of info -# name: string +# name: (handle array byte) # inouts: linked list of vars # outputs: linked list of vars # body: block (singleton linked list) -# subx-name: string +# subx-name: (handle array byte) # == Translating a single primitive instruction # A second crucial piece of the puzzle is how Mu converts fairly regular @@ -208,10 +214,10 @@ # # Accordingly, the formal data structure for a primitive looks like this: # primitives: linked list of info -# name: string +# name: (handle array byte) # mu-inouts: linked list of vars to check # mu-outputs: linked list of vars to check -# subx-name: string +# subx-name: (handle array byte) # subx-rm32: enum arg-location # subx-r32: enum arg-location # subx-imm32: enum arg-location @@ -239,31 +245,31 @@ == data -Program: # (address function) +Program: # (handle function) 0/imm32 Function-name: 0/imm32 Function-subx-name: 4/imm32 -Function-inouts: # (address list var) +Function-inouts: # (handle list var) 8/imm32 -Function-outputs: # (address list var) +Function-outputs: # (handle list var) 0xc/imm32 -Function-body: # (address block) +Function-body: # (handle block) 0x10/imm32 -Function-next: # (address function) +Function-next: # (handle function) 0x14/imm32 Function-size: 0x18/imm32/24 Primitive-name: 0/imm32 -Primitive-inouts: # (address list var) +Primitive-inouts: # (handle list var) 4/imm32 -Primitive-outputs: # (address list var) +Primitive-outputs: # (handle list var) 8/imm32 -Primitive-subx-name: # (address string) +Primitive-subx-name: # (handle array byte) 0xc/imm32 Primitive-subx-rm32: # enum arg-location 0x10/imm32 @@ -271,7 +277,7 @@ Primitive-subx-r32: # enum arg-location 0x14/imm32 Primitive-subx-imm32: # enum arg-location 0x18/imm32 -Primitive-next: # (address function) +Primitive-next: # (handle function) 0x1c/imm32 Primitive-size: 0x20/imm32/24 @@ -279,31 +285,31 @@ Primitive-size: Stmt-tag: 0/imm32 -Block-statements: # (address list statement) +Block-statements: # (handle list statement) 4/imm32 -Stmt1-operation: # string +Stmt1-operation: # (handle array byte) 4/imm32 -Stmt1-inouts: # (address list var) +Stmt1-inouts: # (handle list var) 8/imm32 -Stmt1-outputs: # (address list var) +Stmt1-outputs: # (handle list var) 0xc/imm32 -Vardef-name: # string +Vardef-name: # (handle array byte) 4/imm32 -Vardef-type: # (address tree type-id) +Vardef-type: # (handle tree type-id) 8/imm32 -Regvardef-name: # string +Regvardef-name: # (handle array byte) 4/imm32 -Regvardef-type: # (address tree type-id) +Regvardef-type: # (handle tree type-id) 8/imm32 -Regvardef-register: # string +Regvardef-register: # (handle array byte) 0xc/imm32 Named-block-name: 4/imm32 -Named-block-statements: # (address list statement) +Named-block-statements: # (handle list statement) 8/imm32 Stmt-size: @@ -621,9 +627,9 @@ test-convert-function-with-arg-and-body: parse-mu: # in : (address buffered-file) # pseudocode - # var curr-function = Program - # var line : (stream byte 512) - # var word-slice : slice + # var curr-function : (handle function) = Program + # var line : (ref stream byte 512) + # var word-slice : (ref slice) # while true # line loop # clear-stream(line) # read-line-buffered(in, line) @@ -634,7 +640,7 @@ parse-mu: # in : (address buffered-file) # else if slice-starts-with?(word-slice, "#") # comment # continue # end of line # else if slice-equal(word-slice, "fn") - # var new-function : (address function) = new function + # var new-function : (handle function) = new function # populate-mu-function-header(in, new-function) # populate-mu-function-body(in, new-function) # *curr-function = new-function @@ -650,17 +656,17 @@ parse-mu: # in : (address buffered-file) 51/push-ecx 52/push-edx 57/push-edi - # var line/ecx : (stream byte 512) + # var line/ecx : (ref stream byte 512) 81 5/subop/subtract %esp 0x200/imm32 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/<- %ecx 4/r32/esp - # var word-slice/edx : slice + # var word-slice/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %edx 4/r32/esp - # var curr-function/edi : (address function) = Program + # var curr-function/edi : (handle function) = Program bf/copy-to-edi Program/imm32 { $parse-mu:line-loop: @@ -694,7 +700,7 @@ $parse-mu:fn: (slice-equal? %edx "fn") 3d/compare-eax-and 0/imm32 0f 84/jump-if-equal break/disp32 - # var new-function/eax : (address function) = populate-mu-function() + # var new-function/eax : (handle function) = populate-mu-function() (allocate Heap *Function-size) # => eax (populate-mu-function-header %ecx %eax) (populate-mu-function-body *(ebp+8) %eax) @@ -743,9 +749,10 @@ $parse-mu:abort: # ✓ fn foo x : int { # ✓ fn foo x: int { # ✓ fn foo x: int -> y/eax: int { -populate-mu-function-header: # first-line : (address stream byte), out : (address function) +populate-mu-function-header: # first-line : (address stream byte), out : (handle function) # pseudocode: - # var name : slice = next-word(first-line) + # var name : (ref slice) + # next-word(first-line, name) # assert(name not in '{' '}' '->') # out->name = slice-to-string(name) # ## inouts @@ -755,14 +762,14 @@ populate-mu-function-header: # first-line : (address stream byte), out : (addre # if (name == '{') goto done # if (name == '->') break # assert(name != '}') - # var v : (address var) = parse-var-with-type(name, first-line) + # var v : (handle var) = parse-var-with-type(name, first-line) # out->inouts = append(out->inouts, v) # ## outputs # while true # ## name # name = next-word(first-line) # assert(name not in '{' '}' '->') - # var v : (address var) = parse-var-with-type(name, first-line) + # var v : (handle var) = parse-var-with-type(name, first-line) # out->outputs = append(out->outputs, v) # done: # @@ -775,7 +782,7 @@ populate-mu-function-header: # first-line : (address stream byte), out : (addre 57/push-edi # edi = out 8b/-> *(ebp+0xc) 7/r32/edi - # var word-slice/ecx : slice + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -875,7 +882,7 @@ test-function-header-with-arg: # setup (clear-stream _test-input-stream) (write _test-input-stream "foo n : int {\n") - # result/ecx : (address function) + # result/ecx : (ref function) 2b/subtract-> *Function-size 4/r32/esp 89/<- %ecx 4/r32/esp (zero-out %ecx *Function-size) @@ -883,9 +890,9 @@ test-function-header-with-arg: (populate-mu-function-header _test-input-stream %ecx) # check result (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name - # edx : (address list var) = result->inouts + # edx : (handle list var) = result->inouts 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - # ebx : (address var) = result->inouts->value + # ebx : (handle var) = result->inouts->value 8b/-> *edx 3/r32/ebx # List-value (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:0/type") # Var-type @@ -902,7 +909,7 @@ test-function-header-with-multiple-args: # setup (clear-stream _test-input-stream) (write _test-input-stream "foo a: int, b: int c: int {\n") - # result/ecx : (address function) + # result/ecx : (handle function) 2b/subtract-> *Function-size 4/r32/esp 89/<- %ecx 4/r32/esp (zero-out %ecx *Function-size) @@ -910,9 +917,9 @@ test-function-header-with-multiple-args: (populate-mu-function-header _test-input-stream %ecx) # check result (check-strings-equal *ecx "foo") # Function-name - # edx : (address list var) = result->inouts + # edx : (handle list var) = result->inouts 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - # ebx : (address var) = result->inouts->value + # ebx : (handle var) = result->inouts->value 8b/-> *edx 3/r32/ebx # List-value (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:0/type") # Var-type @@ -941,7 +948,7 @@ test-function-with-multiple-args-and-outputs: # setup (clear-stream _test-input-stream) (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx : int {\n") - # result/ecx : (address function) + # result/ecx : (handle function) 2b/subtract-> *Function-size 4/r32/esp 89/<- %ecx 4/r32/esp (zero-out %ecx *Function-size) @@ -949,9 +956,9 @@ test-function-with-multiple-args-and-outputs: (populate-mu-function-header _test-input-stream %ecx) # check result (check-strings-equal *ecx "foo") # Function-name - # edx : (address list var) = result->inouts + # edx : (handle list var) = result->inouts 8b/-> *(ecx+8) 2/r32/edx # Function-inouts - # ebx : (address var) = result->inouts->value + # ebx : (handle var) = result->inouts->value 8b/-> *edx 3/r32/ebx # List-value (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:0/type") # Var-type @@ -967,9 +974,9 @@ test-function-with-multiple-args-and-outputs: 8b/-> *edx 3/r32/ebx # List-value (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:2/type") # Var-type - # edx : (address list var) = result->outputs + # edx : (handle list var) = result->outputs 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs - # ebx : (address var) = result->outputs->value + # ebx : (handle var) = result->outputs->value 8b/-> *edx 3/r32/ebx # List-value (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args/output:0") # Var-name (check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/output:0/type") # Var-type @@ -991,12 +998,12 @@ test-function-with-multiple-args-and-outputs: # x: int # x: int, # ignores at most one trailing colon or comma -parse-var-with-type: # name: slice, first-line: (address stream) -> result/eax: (address var) +parse-var-with-type: # name: (address slice), first-line: (address stream byte) -> result/eax: (handle var) # pseudocode: - # var v : (address var) = allocate(Heap, Var-size) - # var s : slice + # var v : (handle var) = allocate(Heap, Var-size) + # var s : (ref slice) # next-token-from-slice(name->start, name->end, '/', s) - # var end : address = s->end + # var end : (address byte) = s->end # if (slice-ends-with(s, ":")) # decrement s->end # if (slice-ends-with(s, ",")) @@ -1030,12 +1037,12 @@ parse-var-with-type: # name: slice, first-line: (address stream) -> result/eax: 53/push-ebx 56/push-esi 57/push-edi - # var result/edi : (address var) = allocate(Heap, Var-size) + # var result/edi : (handle var) = allocate(Heap, Var-size) (allocate Heap *Var-size) 89/<- %edi 0/r32/eax # esi = name 8b/-> *(ebp+8) 6/r32/esi - # var s/ecx : slice + # var s/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1160,7 +1167,7 @@ $parse-var-with-type:abort: cd/syscall 0x80/imm8 # never gets here -next-mu-token: # in: (address stream), out: (address slice) +next-mu-token: # in: (address stream byte), out: (address slice) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -1201,7 +1208,7 @@ $next-mu-token:end: 5d/pop-to-ebp c3/return -type-for: # name: (address slice) -> result/eax: type-tree +type-for: # name: (address slice) -> result/eax: (handle s-expression type-id) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -1227,7 +1234,7 @@ test-parse-var-with-type: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1254,7 +1261,7 @@ test-parse-var-with-type-and-register: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1283,7 +1290,7 @@ test-parse-var-with-trailing-characters: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1314,7 +1321,7 @@ is-identifier?: # in : (address slice) -> result/eax : boolean (slice-empty? *(ebp+8)) # => eax 3d/compare-eax-and 0/imm32 75/jump-if-not-equal $is-identifier?:false/disp8 - # var c/eax : char = *in->start + # var c/eax : byte = *in->start 8b/-> *(ebp+8) 0/r32/eax 8b/-> *eax 0/r32/eax 8a/copy-byte *eax 0/r32/AL @@ -1354,7 +1361,7 @@ test-is-identifier-dollar: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1375,7 +1382,7 @@ test-is-identifier-underscore: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1396,7 +1403,7 @@ test-is-identifier-a: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1417,7 +1424,7 @@ test-is-identifier-z: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1438,7 +1445,7 @@ test-is-identifier-A: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1459,7 +1466,7 @@ test-is-identifier-Z: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1481,7 +1488,7 @@ test-is-identifier-@: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1503,7 +1510,7 @@ test-is-identifier-square-bracket: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1525,7 +1532,7 @@ test-is-identifier-backtick: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1547,7 +1554,7 @@ test-is-identifier-curly-brace-open: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1568,7 +1575,7 @@ test-is-identifier-curly-brace-close: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1590,7 +1597,7 @@ test-is-identifier-hyphen: 8b/-> *eax 1/r32/ecx 8d/copy-address *(eax+ecx+4) 1/r32/ecx 05/add-to-eax 4/imm32 - # var slice/ecx = {eax, ecx} + # var slice/ecx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/<- %ecx 4/r32/esp @@ -1602,7 +1609,7 @@ test-is-identifier-hyphen: 5d/pop-to-ebp c3/return -populate-mu-function-body: # in : (address buffered-file), out : (address function) +populate-mu-function-body: # in : (address buffered-file), out : (handle function) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -1614,7 +1621,7 @@ populate-mu-function-body: # in : (address buffered-file), out : (address funct 8b/-> *(ebp+8) 6/r32/esi # edi = out 8b/-> *(ebp+0xc) 7/r32/edi - # var eax : (address block) = parse-mu-block(in) + # var eax : (handle block) = parse-mu-block(in) (parse-mu-block %esi) # => eax # out->body = eax 89/<- *(edi+0x10) 0/r32/eax # Function-body @@ -1629,10 +1636,10 @@ $populate-mu-function-body:end: c3/return # parses a block, assuming that the leading '{' has already been read by the caller -parse-mu-block: # in : (address buffered-file) -> result/eax : (address block) +parse-mu-block: # in : (address buffered-file) -> result/eax : (handle block) # pseudocode: - # var line : (stream byte 512) - # var word-slice : slice + # var line : (ref stream byte 512) + # var word-slice : (ref slice) # result/eax = allocate(Heap, Stmt-size) # result->tag = 0/Block # while true # line loop @@ -1670,13 +1677,13 @@ parse-mu-block: # in : (address buffered-file) -> result/eax : (address block) 53/push-ebx 56/push-esi 57/push-edi - # var line/ecx : (stream byte 512) + # var line/ecx : (ref stream byte 512) 81 5/subop/subtract %esp 0x200/imm32 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/<- %ecx 4/r32/esp - # var word-slice/edx : slice + # var word-slice/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %edx 4/r32/esp @@ -1791,14 +1798,14 @@ $parse-mu-block:abort: cd/syscall 0x80/imm8 # never gets here -check-no-tokens-left: # line : (address stream) +check-no-tokens-left: # line : (address stream byte) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 51/push-ecx - # var s/ecx : slice = next-word(line) + # var s/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -1838,10 +1845,10 @@ $check-no-tokens-left:end: 5d/pop-to-ebp c3/return -parse-mu-named-block: # name : (address slice), first-line : (address stream), in : (address buffered-file) -> result/eax : (address stmt) +parse-mu-named-block: # name : (address slice), first-line : (address stream byte), in : (address buffered-file) -> result/eax : (handle stmt) # pseudocode: - # var line : (stream byte 512) - # var word-slice : slice + # var line : (ref stream byte 512) + # var word-slice : (ref slice) # result/eax = allocate(Heap, Stmt-size) # result->tag = 4/Named-block # result->name = name @@ -1882,7 +1889,7 @@ $parse-mu-named-block:end: 5d/pop-to-ebp c3/return -parse-mu-var-def: # line : (address stream) -> result/eax : (address stmt) +parse-mu-var-def: # line : (address stream byte) -> result/eax : (handle stmt) # pseudocode: # # . prologue @@ -1897,10 +1904,10 @@ $parse-mu-var-def:end: 5d/pop-to-ebp c3/return -parse-mu-stmt: # line : (address stream) -> result/eax : (address stmt) +parse-mu-stmt: # line : (address stream byte) -> result/eax : (handle stmt) # pseudocode: - # var name : slice - # var v : (address var) + # var name : (ref slice) + # var v : (ref var) # result = allocate(Heap, Stmt-size) # if stmt-has-outputs?(line) # while true @@ -1921,11 +1928,11 @@ parse-mu-stmt: # line : (address stream) -> result/eax : (address stmt) # . save registers 51/push-ecx 57/push-edi - # var name/ecx : (address slice) + # var name/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp - # var result/edi : (address stmt) + # result/edi : (handle stmt) (allocate Heap *Stmt-size) 89/<- %edi 0/r32/eax # result->tag = 1/stmt @@ -2017,13 +2024,13 @@ $parse-mu-stmt:abort2: cd/syscall 0x80/imm8 # never gets here -stmt-has-outputs?: # line : (address stream) -> result/eax : boolean +stmt-has-outputs?: # line : (address stream byte) -> result/eax : boolean # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 51/push-ecx - # var word-slice/ecx : slice + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp @@ -2063,7 +2070,7 @@ $stmt-has-outputs:end: 5d/pop-to-ebp c3/return -parse-var: # ad: allocation-descriptor, name: (address slice) -> result/eax: (address var) +parse-var: # ad: allocation-descriptor, name: (address slice) -> result/eax: (handle var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2099,9 +2106,9 @@ test-parse-mu-stmt: (parse-mu-stmt _test-input-stream) # check result (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation - # edx : (address list var) = result->inouts + # edx : (handle list var) = result->inouts 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts - # ebx : (address var) = result->inouts->value + # ebx : (handle var) = result->inouts->value 8b/-> *edx 3/r32/ebx # List-value (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name # . epilogue @@ -2109,7 +2116,7 @@ test-parse-mu-stmt: 5d/pop-to-ebp c3/return -new-function: # ad: allocation-descriptor, name: string, subx-name: string, inouts: (address list var), outputs: (address list var), body: (address block), next: (address function) -> result/eax: (address function) +new-function: # ad: allocation-descriptor, name: string, subx-name: string, inouts: (handle list var), outputs: (handle list var), body: (handle block), next: (handle function) -> result/eax: (handle function) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2137,7 +2144,7 @@ $new-function:end: 5d/pop-to-ebp c3/return -new-var: # ad: allocation-descriptor, name: string, type: int, block: int, stack-offset: int, register: string -> result/eax: (address var) +new-var: # ad: allocation-descriptor, name: string, type: int, block: int, stack-offset: int, register: string -> result/eax: (handle var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2163,7 +2170,7 @@ $new-var:end: 5d/pop-to-ebp c3/return -new-block: # ad: allocation-descriptor, data: (address list statement) -> result/eax: (address statement) +new-block: # ad: allocation-descriptor, data: (handle list statement) -> result/eax: (handle statement) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2182,7 +2189,7 @@ $new-block:end: 5d/pop-to-ebp c3/return -new-stmt: # ad: allocation-descriptor, operation: string, inouts: (address list var), outputs: (address list var) -> result/eax: (address statement) +new-stmt: # ad: allocation-descriptor, operation: string, inouts: (handle list var), outputs: (handle list var) -> result/eax: (handle statement) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2205,7 +2212,7 @@ $new-stmt:end: 5d/pop-to-ebp c3/return -new-vardef: # ad: allocation-descriptor, name: string, type: int -> result/eax: (address statement) +new-vardef: # ad: allocation-descriptor, name: string, type: int -> result/eax: (handle statement) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2226,7 +2233,7 @@ $new-vardef:end: 5d/pop-to-ebp c3/return -new-regvardef: # ad: allocation-descriptor, name: string, type: int, register: string -> result/eax: (address statement) +new-regvardef: # ad: allocation-descriptor, name: string, type: int, register: string -> result/eax: (handle statement) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2249,7 +2256,7 @@ $new-regvardef:end: 5d/pop-to-ebp c3/return -new-named-block: # ad: allocation-descriptor, name: string, data: (address list statement) -> result/eax: (address statement) +new-named-block: # ad: allocation-descriptor, name: string, data: (handle list statement) -> result/eax: (handle statement) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2270,7 +2277,7 @@ $new-named-block:end: 5d/pop-to-ebp c3/return -new-list: # ad: allocation-descriptor, value: _type, next: (address list _type) -> result/eax : (address list _type) +new-list: # ad: allocation-descriptor, value: _type, next: (handle list _type) -> result/eax : (handle list _type) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2290,7 +2297,7 @@ $new-list:end: 5d/pop-to-ebp c3/return -append-list: # ad: allocation-descriptor, value: _type, list: (address list _type) -> result/eax : (address list _type) +append-list: # ad: allocation-descriptor, value: _type, list: (handle list _type) -> result/eax : (handle list _type) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2326,7 +2333,7 @@ $append-list:end: 5d/pop-to-ebp c3/return -append-to-block: # ad: allocation-descriptor, block: (address block), x: (address stmt) +append-to-block: # ad: allocation-descriptor, block: (handle block), x: (handle stmt) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2373,10 +2380,10 @@ emit-subx: # out : (address buffered-file) 57/push-edi # edi = out 8b/-> *(ebp+8) 7/r32/edi - # var curr/ecx : (address function) = Program + # var curr/ecx : (handle function) = Program 8b/-> *Program 1/r32/ecx { - # if (curr == NULL) break + # if (curr == null) break 81 7/subop/compare %ecx 0/imm32 0f 84/jump-if-equal break/disp32 (emit-subx-function %edi %ecx) @@ -2394,7 +2401,7 @@ $emit-subx:end: 5d/pop-to-ebp c3/return -emit-subx-function: # out : (address buffered-file), f : (address function) +emit-subx-function: # out : (address buffered-file), f : (handle function) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2422,11 +2429,11 @@ $emit-subx-function:end: 5d/pop-to-ebp c3/return -emit-subx-block: # out : (address buffered-file), block : (address block) +emit-subx-block: # out : (address buffered-file), block : (handle block) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp - # curr/esi : (address list statement) = block->statements + # curr/esi : (handle list statement) = block->statements 8b/-> *(ebp+0xc) 6/r32/esi 8b/-> *(esi+4) 6/r32/esi # Block-statements # @@ -2451,7 +2458,7 @@ $emit-subx-block:end: 5d/pop-to-ebp c3/return -emit-subx-statement: # out : (address buffered-file), stmt : (address statement), vars : (stack var), primitives : (address primitive), functions : (address function) +emit-subx-statement: # out : (address buffered-file), stmt : (handle statement), vars : (handle stack var), primitives : (handle primitive), functions : (handle function) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2614,7 +2621,7 @@ Lit-var: 0/imm32/no-register == code -emit-subx-primitive: # out : (address buffered-file), stmt : (address statement), vars : (address variable), primitive : (address function) +emit-subx-primitive: # out : (address buffered-file), stmt : (handle statement), vars : (handle variable), primitive : (handle function) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2640,7 +2647,7 @@ $emit-subx-primitive:end: 5d/pop-to-ebp c3/return -emit-subx-rm32: # out : (address buffered-file), l : arg-location, stmt : (address statement) +emit-subx-rm32: # out : (address buffered-file), l : arg-location, stmt : (handle statement) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2660,7 +2667,7 @@ $emit-subx-rm32:end: 5d/pop-to-ebp c3/return -get-stmt-operand-from-arg-location: # stmt : (address statement), l : arg-location -> var/eax : (address variable) +get-stmt-operand-from-arg-location: # stmt : (handle statement), l : arg-location -> var/eax : (handle variable) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2720,7 +2727,7 @@ $get-stmt-operand-from-arg-location:abort: cd/syscall 0x80/imm8 # never gets here -emit-subx-r32: # out : (address buffered-file), l : arg-location, stmt : (address statement) +emit-subx-r32: # out : (address buffered-file), l : arg-location, stmt : (handle statement) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2745,7 +2752,7 @@ $emit-subx-r32:end: 5d/pop-to-ebp c3/return -emit-subx-imm32: # out : (address buffered-file), l : arg-location, stmt : (address statement) +emit-subx-imm32: # out : (address buffered-file), l : arg-location, stmt : (handle statement) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2769,7 +2776,7 @@ $emit-subx-imm32:end: 5d/pop-to-ebp c3/return -emit-subx-call: # out : (address buffered-file), stmt : (address statement), vars : (address variable), callee : (address function) +emit-subx-call: # out : (address buffered-file), stmt : (handle statement), vars : (handle variable), callee : (handle function) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2782,7 +2789,7 @@ emit-subx-call: # out : (address buffered-file), stmt : (address statement), va 8b/-> *(ebp+0x14) 1/r32/ecx (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name # - emit arguments - # var curr/ecx : (list var) = stmt->inouts + # var curr/ecx : (handle list var) = stmt->inouts 8b/-> *(ebp+0xc) 1/r32/ecx 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts { @@ -2805,7 +2812,7 @@ $emit-subx-call:end: 5d/pop-to-ebp c3/return -emit-subx-call-operand: # out : (address buffered-file), operand : (address variable) +emit-subx-call-operand: # out : (address buffered-file), operand : (handle variable) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2831,7 +2838,7 @@ $emit-subx-call-operand:end: 5d/pop-to-ebp c3/return -emit-subx-var-as-rm32: # out : (address buffered-file), operand : (address variable) +emit-subx-var-as-rm32: # out : (address buffered-file), operand : (handle variable) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2866,19 +2873,19 @@ $emit-subx-var-as-rm32:end: 5d/pop-to-ebp c3/return -find-matching-function: # functions : (address function), stmt : (address statement) -> result/eax : (address function) +find-matching-function: # functions : (address function), stmt : (handle statement) -> result/eax : (handle function) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 51/push-ecx - # var curr/ecx : (address function) = functions + # var curr/ecx : (handle function) = functions 8b/-> *(ebp+8) 1/r32/ecx { # if (curr == null) break 81 7/subop/compare %ecx 0/imm32 74/jump-if-equal break/disp8 - # if match(curr, stmt) return curr + # if match(stmt, curr) return curr { (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax 3d/compare-eax-and 0/imm32 @@ -2900,13 +2907,13 @@ $find-matching-function:end: 5d/pop-to-ebp c3/return -find-matching-primitive: # primitives : (address primitive), stmt : (address statement) -> result/eax : (address primitive) +find-matching-primitive: # primitives : (handle primitive), stmt : (handle statement) -> result/eax : (handle primitive) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 51/push-ecx - # var curr/ecx : (address primitive) = primitives + # var curr/ecx : (handle primitive) = primitives 8b/-> *(ebp+8) 1/r32/ecx { $find-matching-primitive:loop: @@ -2936,7 +2943,7 @@ $find-matching-primitive:end: 5d/pop-to-ebp c3/return -mu-stmt-matches-function?: # stmt : (address statement), function : (address opcode-info) => result/eax : boolean +mu-stmt-matches-function?: # stmt : (handle statement), function : (handle function) => result/eax : boolean # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -2954,7 +2961,7 @@ $mu-stmt-matches-function?:end: 5d/pop-to-ebp c3/return -mu-stmt-matches-primitive?: # stmt : (address statement), primitive : (address primitive) => result/eax : boolean +mu-stmt-matches-primitive?: # stmt : (handle statement), primitive : (handle primitive) => result/eax : boolean # A mu stmt matches a primitive if the name matches, all the inout vars # match, and all the output vars match. # Vars match if types match and registers match. @@ -3080,7 +3087,7 @@ $mu-stmt-matches-primitive?:end: 5d/pop-to-ebp c3/return -operand-matches-primitive?: # var : (address var), primout-var : (address var) => result/eax : boolean +operand-matches-primitive?: # var : (handle var), primout-var : (handle var) => result/eax : boolean # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -3153,30 +3160,30 @@ test-emit-subx-statement-primitive: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-foo/ecx : var + # var var-foo/ecx : (ref var) 68/push 0/imm32/no-register 68/push -8/imm32/stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "foo"/imm32 89/<- %ecx 4/r32/esp - # vars/edx : (stack 1) + # var vars/edx : (ref stack 1) 51/push-ecx/var-foo 68/push 1/imm32/data-length 68/push 1/imm32/top 89/<- %edx 4/r32/esp - # operand/ebx : (list var) + # var operand/ebx : (ref list var) 68/push 0/imm32/next 51/push-ecx/var-foo 89/<- %ebx 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 68/push 0/imm32/outputs 53/push-ebx/operands 68/push "increment"/imm32/operation 68/push 1/imm32 89/<- %esi 4/r32/esp - # primitives/ebx : primitive + # var primitives/ebx : (ref primitive) 68/push 0/imm32/next 68/push 0/imm32/no-imm32 68/push 0/imm32/no-r32 @@ -3226,41 +3233,41 @@ test-emit-subx-statement-primitive-register: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-foo/ecx : var in eax + # var var-foo/ecx : (ref var) in eax 68/push "eax"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "foo"/imm32 89/<- %ecx 4/r32/esp - # vars/edx : (stack 1) + # var vars/edx : (ref stack 1) 51/push-ecx/var-foo 68/push 1/imm32/data-length 68/push 1/imm32/top 89/<- %edx 4/r32/esp - # operand/ebx : (list var) + # var operand/ebx : (ref list var) 68/push 0/imm32/next 51/push-ecx/var-foo 89/<- %ebx 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 53/push-ebx/outputs 68/push 0/imm32/inouts 68/push "increment"/imm32/operation 68/push 1/imm32 89/<- %esi 4/r32/esp - # formal-var/ebx : var in any register + # var formal-var/ebx : (ref var) in any register 68/push Any-register/imm32 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "dummy"/imm32 89/<- %ebx 4/r32/esp - # operand/ebx : (list var) + # var operand/ebx : (ref list var) 68/push 0/imm32/next 53/push-ebx/formal-var 89/<- %ebx 4/r32/esp - # primitives/ebx : primitive + # var primitives/ebx : (ref primitive) 68/push 0/imm32/next 68/push 0/imm32/no-imm32 68/push 0/imm32/no-r32 @@ -3313,41 +3320,41 @@ test-emit-subx-statement-select-primitive: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-foo/ecx : var in eax + # var var-foo/ecx : (ref var) in eax 68/push "eax"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "foo"/imm32 89/<- %ecx 4/r32/esp - # vars/edx : (stack 1) + # var vars/edx : (ref stack 1) 51/push-ecx/var-foo 68/push 1/imm32/data-length 68/push 1/imm32/top 89/<- %edx 4/r32/esp - # real-outputs/edi : (list var) + # var real-outputs/edi : (ref list var) 68/push 0/imm32/next 51/push-ecx/var-foo 89/<- %edi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 57/push-edi/outputs 68/push 0/imm32/inouts 68/push "increment"/imm32/operation 68/push 1/imm32 89/<- %esi 4/r32/esp - # formal-var/ebx : var in any register + # var formal-var/ebx : (ref var) in any register 68/push Any-register/imm32 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "dummy"/imm32 89/<- %ebx 4/r32/esp - # formal-outputs/ebx : (list var) + # var formal-outputs/ebx : (ref list var) = {formal-var, 0} 68/push 0/imm32/next 53/push-ebx/formal-var 89/<- %ebx 4/r32/esp - # primitive1/ebx : primitive + # var primitive1/ebx : (ref primitive) 68/push 0/imm32/next 68/push 0/imm32/no-imm32 68/push 0/imm32/no-r32 @@ -3357,7 +3364,7 @@ test-emit-subx-statement-select-primitive: 68/push 0/imm32/inouts 68/push "increment"/imm32/name 89/<- %ebx 4/r32/esp - # primitives/ebx : primitive + # var primitives/ebx : (ref primitive) 53/push-ebx/next 68/push 0/imm32/no-imm32 68/push 0/imm32/no-r32 @@ -3410,41 +3417,41 @@ test-emit-subx-statement-select-primitive-2: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-foo/ecx : var in eax + # var var-foo/ecx : (ref var) in eax 68/push "eax"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "foo"/imm32 89/<- %ecx 4/r32/esp - # vars/edx : (stack 1) + # var vars/edx : (ref stack 1) 51/push-ecx/var-foo 68/push 1/imm32/data-length 68/push 1/imm32/top 89/<- %edx 4/r32/esp - # inouts/edi : (list var) + # var inouts/edi : (ref list var) 68/push 0/imm32/next 51/push-ecx/var-foo 89/<- %edi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 68/push 0/imm32/outputs 57/push-edi/inouts 68/push "increment"/imm32/operation 68/push 1/imm32 89/<- %esi 4/r32/esp - # formal-var/ebx : var in any register + # var formal-var/ebx : (ref var) in any register 68/push Any-register/imm32 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "dummy"/imm32 89/<- %ebx 4/r32/esp - # operand/ebx : (list var) + # var operand/ebx : (ref list var) 68/push 0/imm32/next 53/push-ebx/formal-var 89/<- %ebx 4/r32/esp - # primitive1/ebx : primitive + # var primitive1/ebx : primitive 68/push 0/imm32/next 68/push 0/imm32/no-imm32 68/push 0/imm32/no-r32 @@ -3454,7 +3461,7 @@ test-emit-subx-statement-select-primitive-2: 68/push 0/imm32/inouts 68/push "increment"/imm32/name 89/<- %ebx 4/r32/esp - # primitives/ebx : primitive + # var primitives/ebx : (ref primitive) 53/push-ebx/next 68/push 0/imm32/no-imm32 68/push 0/imm32/no-r32 @@ -3501,23 +3508,23 @@ test-increment-register: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-foo/ecx : var in eax + # var var-foo/ecx : (ref var) in eax 68/push "eax"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "foo"/imm32 89/<- %ecx 4/r32/esp - # vars/edx : (stack 1) + # var vars/edx : (ref stack 1) 51/push-ecx/var-foo 68/push 1/imm32/data-length 68/push 1/imm32/top 89/<- %edx 4/r32/esp - # real-outputs/edi : (list var) + # var real-outputs/edi : (ref list var) 68/push 0/imm32/next 51/push-ecx/var-foo 89/<- %edi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 57/push-edi/outputs 68/push 0/imm32/inouts @@ -3561,23 +3568,23 @@ test-increment-var: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-foo/ecx : var in eax + # var var-foo/ecx : (ref var) in eax 68/push "eax"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "foo"/imm32 89/<- %ecx 4/r32/esp - # vars/edx : (stack 1) + # var vars/edx : (ref stack 1) 51/push-ecx/var-foo 68/push 1/imm32/data-length 68/push 1/imm32/top 89/<- %edx 4/r32/esp - # inouts/edi : (list var) + # var inouts/edi : (ref list var) 68/push 0/imm32/next 51/push-ecx/var-foo 89/<- %edi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 68/push 0/imm32/outputs 57/push-edi/inouts @@ -3611,29 +3618,29 @@ test-add-reg-to-reg: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-var1/ecx : var in eax + # var var-var1/ecx : (ref var) in eax 68/push "eax"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "var1"/imm32 89/<- %ecx 4/r32/esp - # var-var2/edx : var in ecx + # var var-var2/edx : (ref var) in ecx 68/push "ecx"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "var2"/imm32 89/<- %edx 4/r32/esp - # inouts/esi : (list var2) + # var inouts/esi : (ref list var2) 68/push 0/imm32/next 52/push-edx/var-var2 89/<- %esi 4/r32/esp - # outputs/edi : (list var1) + # var outputs/edi : (ref list var1) 68/push 0/imm32/next 51/push-ecx/var-var1 89/<- %edi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 57/push-edi/outputs 56/push-esi/inouts @@ -3667,29 +3674,29 @@ test-add-reg-to-mem: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-var1/ecx : var + # var var-var1/ecx : (ref var) 68/push 0/imm32/no-register 68/push 8/imm32/stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "var1"/imm32 89/<- %ecx 4/r32/esp - # var-var2/edx : var in ecx + # var var-var2/edx : (ref var) in ecx 68/push "ecx"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "var2"/imm32 89/<- %edx 4/r32/esp - # inouts/esi : (list var2) + # var inouts/esi : (ref list var2) 68/push 0/imm32/next 52/push-edx/var-var2 89/<- %esi 4/r32/esp - # inouts = (list var1 var2) + # var inouts = (ref list var1 var2) 56/push-esi/next 51/push-ecx/var-var1 89/<- %esi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 68/push 0/imm32/outputs 56/push-esi/inouts @@ -3723,29 +3730,29 @@ test-add-mem-to-reg: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-var1/ecx : var in eax + # var var-var1/ecx : (ref var) in eax 68/push "eax"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "var1"/imm32 89/<- %ecx 4/r32/esp - # var-var2/edx : var + # var var-var2/edx : (ref var) 68/push 0/imm32/no-register 68/push 8/imm32/stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "var2"/imm32 89/<- %edx 4/r32/esp - # inouts/esi : (list var2) + # var inouts/esi : (ref list var2) 68/push 0/imm32/next 52/push-edx/var-var2 89/<- %esi 4/r32/esp - # outputs/edi : (list var1) + # var outputs/edi : (ref list var1) 68/push 0/imm32/next 51/push-ecx/var-var1 89/<- %edi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 57/push-edi/outputs 56/push-esi/inouts @@ -3779,29 +3786,29 @@ test-add-literal-to-reg: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-var1/ecx : var in eax + # var var-var1/ecx : (ref var) in eax 68/push "eax"/imm32/register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "var1"/imm32 89/<- %ecx 4/r32/esp - # var-var2/edx : var literal + # var var-var2/edx : (ref var) literal 68/push 0/imm32/no-register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 0/imm32/type-literal 68/push "0x34"/imm32 89/<- %edx 4/r32/esp - # inouts/esi : (list var2) + # var inouts/esi : (ref list var2) 68/push 0/imm32/next 52/push-edx/var-var2 89/<- %esi 4/r32/esp - # outputs/edi : (list var1) + # var outputs/edi : (ref list var1) 68/push 0/imm32/next 51/push-ecx/var-var1 89/<- %edi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 57/push-edi/outputs 56/push-esi/inouts @@ -3835,29 +3842,29 @@ test-add-literal-to-mem: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-var1/ecx : var + # var var-var1/ecx : (ref var) 68/push 0/imm32/no-register 68/push 8/imm32/stack-offset 68/push 1/imm32/block-depth 68/push 1/imm32/type-int 68/push "var1"/imm32 89/<- %ecx 4/r32/esp - # var-var2/edx : var literal + # var var-var2/edx : (ref var) literal 68/push 0/imm32/no-register 68/push 0/imm32/no-stack-offset 68/push 1/imm32/block-depth 68/push 0/imm32/type-literal 68/push "0x34"/imm32 89/<- %edx 4/r32/esp - # inouts/esi : (list var2) + # var inouts/esi : (ref list var2) 68/push 0/imm32/next 52/push-edx/var-var2 89/<- %esi 4/r32/esp - # inouts = (list var1 inouts) + # var inouts = (ref list var1 inouts) 56/push-esi/next 51/push-ecx/var-var1 89/<- %esi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 68/push 0/imm32/outputs 56/push-esi/inouts @@ -3906,30 +3913,30 @@ test-emit-subx-statement-function-call: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-foo/ecx : var + # var var-foo/ecx : (ref var) 68/push 0/imm32/no-register 68/push -8/imm32/stack-offset 68/push 0/imm32/block-depth 68/push 1/imm32/type-int 68/push "foo"/imm32 89/<- %ecx 4/r32/esp - # vars/edx = (stack 1) + # var vars/edx = (ref stack 1) 51/push-ecx/var-foo 68/push 1/imm32/data-length 68/push 1/imm32/top 89/<- %edx 4/r32/esp - # operands/esi : (list var) + # var operands/esi : (ref list var) 68/push 0/imm32/next 51/push-ecx/var-foo 89/<- %esi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 68/push 0/imm32/outputs 56/push-esi/inouts 68/push "f"/imm32/operation 68/push 1/imm32 89/<- %esi 4/r32/esp - # functions/ebx : function + # var functions/ebx : (ref function) 68/push 0/imm32/next 68/push 0/imm32/body 68/push 0/imm32/outputs @@ -3965,30 +3972,30 @@ test-emit-subx-statement-function-call-with-literal-arg: # setup (clear-stream _test-output-stream) (clear-stream $_test-output-buffered-file->buffer) - # var-foo/ecx : literal + # var var-foo/ecx : (ref var) literal 68/push 0/imm32/no-register 68/push 0/imm32/no-stack-offset 68/push 0/imm32/block-depth 68/push 0/imm32/type-literal 68/push "34"/imm32 89/<- %ecx 4/r32/esp - # vars/edx = (stack 1) + # var vars/edx = (ref stack 1) 51/push-ecx/var-foo 68/push 1/imm32/data-length 68/push 1/imm32/top 89/<- %edx 4/r32/esp - # operands/esi : (list var) + # var operands/esi : (ref list var) 68/push 0/imm32/next 51/push-ecx/var-foo 89/<- %esi 4/r32/esp - # stmt/esi : statement + # var stmt/esi : (ref statement) 68/push 0/imm32/next 68/push 0/imm32/outputs 56/push-esi/inouts 68/push "f"/imm32/operation 68/push 1/imm32 89/<- %esi 4/r32/esp - # functions/ebx : function + # var functions/ebx : (ref function) 68/push 0/imm32/next 68/push 0/imm32/body 68/push 0/imm32/outputs diff --git a/apps/mulisp.subx b/apps/mulisp.subx index 71ad170c..1cfdeb03 100644 --- a/apps/mulisp.subx +++ b/apps/mulisp.subx @@ -81,12 +81,12 @@ repl: # in : (address buffered-file), out : (address buffered-file) # . save registers 50/push-eax { - (lisp-read Stdin) # => eax : (address cell) + (lisp-read Stdin) # => eax : (handle cell) # if (eax == 0) break 3d/compare-eax-and 0/imm32 74/jump-if-equal break/disp8 # - (lisp-eval %eax) # => eax : (address cell) + (lisp-eval %eax) # => eax : (handle cell) (lisp-print Stdout %eax) eb/jump loop/disp8 } @@ -104,13 +104,13 @@ $repl:end: # arrays start with '[' # symbols start with anything else but quote, backquote, unquote or splice # only one s-expression per line -lisp-read: # in : (address buffered-file) -> eax : (address cell) +lisp-read: # in : (address buffered-file) -> eax : (handle cell) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 51/push-ecx - # var s/ecx : (stream byte 512) + # var s/ecx : (ref stream byte 512) 81 5/subop/subtract %esp 0x200/imm32 68/push 0x200/imm32/size 68/push 0/imm32/read @@ -142,14 +142,14 @@ $lisp-read:end: 5d/pop-to-ebp c3/return -# lisp-read: in : (address buffered-file) -> (address cell) +# lisp-read: in : (address buffered-file) -> (handle cell) # token tmp = next-mulisp-token(in) # if is-int(tmp) return cell(tmp) # if is-string(tmp) return cell(tmp) # if is-pair(tmp) ... # if is-array(tmp) ... -next-mulisp-token: # in : (address buffered-file), line : (address stream), result : (address slice) +next-mulisp-token: # in : (address buffered-file), line : (address stream byte), result : (address slice) # pseudocode: # if (line->read >= line->write) # read-line-buffered(in, line) @@ -194,11 +194,11 @@ $next-mulisp-token:end: 5d/pop-to-ebp c3/return -new-int-cell: # in : (address slice) -> eax : (address cell) +new-int-cell: # in : (address slice) -> eax : (handle cell) -new-string-cell: # in : (address slice) -> eax : (address cell) +new-string-cell: # in : (address slice) -> eax : (handle cell) -lisp-eval: # in : (address cell) -> eax : (address cell) +lisp-eval: # in : (address cell) -> eax : (handle cell) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp diff --git a/apps/pack b/apps/pack index 74d4ed32..005c42f8 100755 Binary files a/apps/pack and b/apps/pack differ diff --git a/apps/pack.subx b/apps/pack.subx index 6079a896..df683f84 100644 --- a/apps/pack.subx +++ b/apps/pack.subx @@ -45,8 +45,8 @@ Entry: # run tests if necessary, convert stdin if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto interactive - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto interactive + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-pack-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 @@ -55,7 +55,7 @@ Entry: # run tests if necessary, convert stdin if not eb/jump $subx-pack-main:end/disp8 $subx-pack-main:interactive: # - otherwise convert stdin - # var ed/eax : exit-descriptor + # var ed/eax : (ref exit-descriptor) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # configure ed to really exit() @@ -99,7 +99,7 @@ $subx-pack-main:end: subx-pack: # in : (address buffered-file), out : (address buffered-file) # pseudocode: - # var line : (stream byte 512) + # var line : (ref stream byte 512) # var in-code? = false # while true # clear-stream(line) @@ -128,17 +128,17 @@ subx-pack: # in : (address buffered-file), out : (address buffered-file) 51/push-ecx 52/push-edx 53/push-ebx - # var line/ecx : (address stream byte) = stream(512) + # var line/ecx : (ref stream byte 512) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var word-slice/edx = {0, 0} + # var word-slice/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # var in-code?/ebx = false + # var in-code?/ebx : boolean = false 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx $subx-pack:loop: # clear-stream(line) @@ -203,8 +203,8 @@ $subx-pack:check1: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) write-stream-data(out, line) - 3d/compare-eax-and 0/imm32 + # . if (eax != false) write-stream-data(out, line) + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $subx-pack:pass-through/disp32 $subx-pack:check2: #? # dump word-slice {{{ @@ -256,8 +256,8 @@ $subx-pack:check2: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto check3 - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto check3 + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $subx-pack:check3/disp32 # word-slice = next-word(line) # . . push args @@ -328,8 +328,8 @@ $subx-pack:check3: e8/call rewind-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # if (in-code? != 0) convert-instruction(line, out) - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32 # compare ebx + # if (in-code? != false) convert-instruction(line, out) + 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32/false # compare ebx 74/jump-if-equal $subx-pack:data/disp8 $subx-pack:code: # . convert-instruction(line, out) @@ -911,7 +911,7 @@ test-subx-pack-code-and-data-segments: convert-data: # line : (address stream byte), out : (address buffered-file) # pseudocode: - # var word-slice = {0, 0} + # var word-slice : (ref slice) # while true # word-slice = next-word(line) # if slice-empty?(word-slice) # end of file (maybe including trailing whitespace) @@ -936,7 +936,7 @@ convert-data: # line : (address stream byte), out : (address buffered-file) 50/push-eax 51/push-ecx 52/push-edx - # var word-slice/ecx = {0, 0} + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -1024,17 +1024,17 @@ $convert-data:check0: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $convert-data:break/disp32 $convert-data:check-for-comment: # if (slice-starts-with?(word-slice, "#")) - # . start/edx = word-slice->start + # . var start/edx : (address byte) = word-slice->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL - # . if (eax != '#') goto next check + # . if (c != '#') goto next check 3d/compare-eax-and 0x23/imm32/hash 75/jump-if-not-equal $convert-data:check-for-label/disp8 $convert-data:comment: @@ -1050,12 +1050,12 @@ $convert-data:comment: 0f 85/jump-if-not-equal $convert-data:end/disp32 $convert-data:check-for-label: # if (slice-ends-with?(word-slice, ":")) - # . end/edx = word-slice->end + # . var end/edx : (address byte) = word-slice->end 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx - # . c/eax = *(end-1) + # . var c/eax : byte = *(end-1) 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 1/mod/*+disp8 2/rm32/edx . . . 0/r32/AL -1/disp8 . # copy byte at *ecx to AL - # . if (eax != ':') goto next check + # . if (c != ':') goto next check 3d/compare-eax-and 0x3a/imm32/colon 75/jump-if-not-equal $convert-data:check-for-imm32/disp8 $convert-data:label: @@ -1079,8 +1079,8 @@ $convert-data:check-for-imm32: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) process as a single byte - 3d/compare-eax-and 0/imm32 + # . if (eax == false) process as a single byte + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $convert-data:single-byte/disp8 $convert-data:imm32: # emit(out, word-slice, 4) @@ -1837,7 +1837,7 @@ convert-instruction: # line : (address stream byte), out : (address buffered-fi 50/push-eax 51/push-ecx 52/push-edx - # var word-slice/ecx = {0, 0} + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -1858,27 +1858,27 @@ $convert-instruction:check0: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) pass through - 3d/compare-eax-and 0/imm32 + # . if (eax != false) pass through + 3d/compare-eax-and 0/imm32/false 75/jump-if-not-equal $convert-instruction:pass-through/disp8 $convert-instruction:check1: # if (slice-starts-with?(word-slice, "#")) write-stream-data(out, line) - # . start/edx = word-slice->start + # . var start/edx : (address byte) = word-slice->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL - # . if (eax == '#') pass through + # . if (c == '#') pass through 3d/compare-eax-and 0x23/imm32/hash 74/jump-if-equal $convert-instruction:pass-through/disp8 $convert-instruction:check2: # if (slice-ends-with?(word-slice, ":")) write-stream-data(out, line) - # . end/edx = word-slice->end + # . var end/edx : (address byte) = word-slice->end 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx - # . c/eax = *(end-1) + # . var c/eax : byte = *(end-1) 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 1/mod/*+disp8 2/rm32/edx . . . 0/r32/AL -1/disp8 . # copy byte at *ecx to AL - # . if (eax == ':') pass through + # . if (c == ':') pass through 3d/compare-eax-and 0x3a/imm32/colon 75/jump-if-not-equal $convert-instruction:really-convert/disp8 $convert-instruction:pass-through: @@ -1994,11 +1994,11 @@ emit-opcodes: # line : (address stream byte), out : (address buffered-file) 51/push-ecx 52/push-edx 53/push-ebx - # var op1/ecx = {0, 0} + # var op1/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var op2/edx = {0, 0} + # var op2/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -2026,16 +2026,16 @@ $emit-opcodes:op1: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) return - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 # if (slice-starts-with?(op1, "#")) return - # . start/ebx = op1->start + # . var start/ebx : (address byte) = op1->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL - # . if (eax == '#') return + # . if (c == '#') return 3d/compare-eax-and 0x23/imm32/hash 0f 84/jump-if-equal $emit-opcodes:end/disp32 # op1 = next-token-from-slice(op1->start, op1->end, '/') @@ -2073,8 +2073,8 @@ $emit-opcodes:op1: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) goto op2 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) goto op2 + 3d/compare-eax-and 0/imm32/false 75/jump-if-not-equal $emit-opcodes:op2/disp8 # if (slice-equal?(op1, "f2")) goto op2 # . eax = slice-equal?(op1, "f2") @@ -2085,8 +2085,8 @@ $emit-opcodes:op1: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) goto op2 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) goto op2 + 3d/compare-eax-and 0/imm32/false 75/jump-if-not-equal $emit-opcodes:op2/disp8 # if (slice-equal?(op1, "f3")) goto op2 # . eax = slice-equal?(op1, "f3") @@ -2097,8 +2097,8 @@ $emit-opcodes:op1: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) goto op2 - 3d/compare-eax-and 0/imm32 + # . if (eax != false) goto op2 + 3d/compare-eax-and 0/imm32/false 75/jump-if-not-equal $emit-opcodes:op2/disp8 # otherwise return e9/jump $emit-opcodes:end/disp32 @@ -2119,16 +2119,16 @@ $emit-opcodes:op2: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) return - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 # if (slice-starts-with?(op2, "#")) return - # . start/ebx = op2->start + # . var start/ebx : (address byte) = op2->start 8b/copy 0/mod/indirect 2/rm32/edx . . . 3/r32/ebx . . # copy *edx to ebx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL - # . if (eax == '#') return + # . if (c == '#') return 3d/compare-eax-and 0x23/imm32/hash 0f 84/jump-if-equal $emit-opcodes:end/disp32 # op2 = next-token-from-slice(op2->start, op2->end, '/') @@ -2166,8 +2166,8 @@ $emit-opcodes:op2: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) return - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 # if (!slice-equal?(op2, "0f")) return # . eax = slice-equal?(op2, "0f") @@ -2178,8 +2178,8 @@ $emit-opcodes:op2: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) return - 3d/compare-eax-and 0/imm32 + # . if (eax == false) return + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $emit-opcodes:end/disp32 $emit-opcodes:op3: # next-word(line, op3) # reuse op2/edx @@ -2198,16 +2198,16 @@ $emit-opcodes:op3: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) return - 3d/compare-eax-and 0/imm32 + # . if (eax != false) return + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 # if (slice-starts-with?(op3, "#")) return - # . start/ebx = op2->start + # . var start/ebx : (address byte) = op2->start 8b/copy 0/mod/indirect 2/rm32/edx . . . 3/r32/ebx . . # copy *edx to ebx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL - # . if (eax == '#') return + # . if (c == '#') return 3d/compare-eax-and 0x23/imm32/hash 0f 84/jump-if-equal $emit-opcodes:end/disp32 # op3 = next-token-from-slice(op3->start, op3->end, '/') @@ -2253,7 +2253,7 @@ emit-modrm: # line : (address stream byte), out : (address buffered-file) # pseudocode: # rewind-stream(line) # var has-modrm? = false, mod = 0, rm32 = 0, r32 = 0 - # var word-slice = {0, 0} + # var word-slice : (ref slice) # while true # word-slice = next-word(line) # if (slice-empty?(word-slice)) break @@ -2285,17 +2285,17 @@ emit-modrm: # line : (address stream byte), out : (address buffered-file) 53/push-ebx 56/push-esi 57/push-edi - # var word-slice/ecx = {0, 0} + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var has-modrm?/edx = false + # var has-modrm?/edx : boolean = false 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx - # var mod/ebx = 0 + # var mod/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - # var rm32/esi = 0 + # var rm32/esi : byte = 0 31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi - # var r32/edi = 0 + # var r32/edi : byte = 0 31/xor 3/mod/direct 7/rm32/edi . . . 7/r32/edi . . # clear edi # rewind-stream(line) # . . push args @@ -2395,21 +2395,21 @@ $emit-modrm:check0: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) pass through - 3d/compare-eax-and 0/imm32 + # . if (eax != false) pass through + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-modrm:break/disp32 $emit-modrm:check1: # if (slice-starts-with?(word-slice, "#")) break # . spill edx 52/push-edx - # . start/edx = word-slice->start + # . var start/edx : (address byte) = word-slice->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL # . restore edx 5a/pop-to-edx - # . if (eax == '#') pass through + # . if (c == '#') pass through 3d/compare-eax-and 0x23/imm32/hash 0f 84/jump-if-equal $emit-modrm:break/disp32 $emit-modrm:check-for-mod: @@ -2422,8 +2422,8 @@ $emit-modrm:check-for-mod: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-modrm:check-for-rm32/disp8 $emit-modrm:mod: # mod = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) @@ -2450,8 +2450,8 @@ $emit-modrm:check-for-rm32: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-modrm:check-for-r32/disp8 $emit-modrm:rm32: # rm32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) @@ -2478,8 +2478,8 @@ $emit-modrm:check-for-r32: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-modrm:check-for-subop/disp8 $emit-modrm:r32: # r32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) @@ -2506,8 +2506,8 @@ $emit-modrm:check-for-subop: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) loop - 3d/compare-eax-and 0/imm32 + # . if (eax == false) loop + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $emit-modrm:loop/disp32 $emit-modrm:subop: # r32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) @@ -2526,10 +2526,10 @@ $emit-modrm:subop: e9/jump $emit-modrm:loop/disp32 $emit-modrm:break: # if (!has-modrm?) return - 81 7/subop/compare 3/mod/direct 2/rm32/edx . . . . . 0/imm32 # compare edx + 81 7/subop/compare 3/mod/direct 2/rm32/edx . . . . . 0/imm32/false # compare edx 74/jump-if-equal $emit-modrm:end/disp8 $emit-modrm:calculate: - # modrm/ebx = mod & 0b11 + # var modrm/ebx : byte = mod & 0b11 81 4/subop/and 3/mod/direct 3/rm32/ebx . . . . . 3/imm32/0b11 # bitwise and of ebx # modrm <<= 3 c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 3/imm8 # shift ebx left by 3 bits @@ -2569,7 +2569,7 @@ $emit-modrm:end: emit-sib: # line : (address stream byte), out : (address buffered-file) # pseudocode: # var has-sib? = false, base = 0, index = 0, scale = 0 - # var word-slice = {0, 0} + # var word-slice : (ref slice) # while true # word-slice = next-word(line) # if (slice-empty?(word-slice)) break @@ -2601,17 +2601,17 @@ emit-sib: # line : (address stream byte), out : (address buffered-file) 53/push-ebx 56/push-esi 57/push-edi - # var word-slice/ecx = {0, 0} + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var has-sib?/edx = false + # var has-sib?/edx : boolean = false 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx - # var scale/ebx = 0 + # var scale/ebx : byte = 0 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - # var base/esi = 0 + # var base/esi : byte = 0 31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi - # var index/edi = 0 + # var index/edi : byte = 0 31/xor 3/mod/direct 7/rm32/edi . . . 7/r32/edi . . # clear edi # rewind-stream(line) # . . push args @@ -2704,21 +2704,21 @@ $emit-sib:check0: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) pass through - 3d/compare-eax-and 0/imm32 + # . if (eax != false) pass through + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-sib:break/disp32 $emit-sib:check1: # if (slice-starts-with?(word-slice, "#")) break # . spill edx 52/push-edx - # . start/edx = word-slice->start + # . var start/edx : (address byte) = word-slice->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL # . restore edx 5a/pop-to-edx - # . if (eax == '#') pass through + # . if (c == '#') pass through 3d/compare-eax-and 0x23/imm32/hash 0f 84/jump-if-equal $emit-sib:break/disp32 $emit-sib:check-for-scale: @@ -2731,8 +2731,8 @@ $emit-sib:check-for-scale: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-sib:check-for-base/disp8 $emit-sib:scale: # scale = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) @@ -2759,8 +2759,8 @@ $emit-sib:check-for-base: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-sib:check-for-index/disp8 $emit-sib:base: # base = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) @@ -2787,8 +2787,8 @@ $emit-sib:check-for-index: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) loop - 3d/compare-eax-and 0/imm32 + # . if (eax == false) loop + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $emit-sib:loop/disp32 $emit-sib:index: # index = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) @@ -2807,10 +2807,10 @@ $emit-sib:index: e9/jump $emit-sib:loop/disp32 $emit-sib:break: # if (!has-sib?) return - 81 7/subop/compare 3/mod/direct 2/rm32/edx . . . . . 0/imm32 # compare edx + 81 7/subop/compare 3/mod/direct 2/rm32/edx . . . . . 0/imm32/false # compare edx 74/jump-if-equal $emit-sib:end/disp8 $emit-sib:calculate: - # sib/ebx = scale & 0b11 + # var sib/ebx : byte = scale & 0b11 81 4/subop/and 3/mod/direct 3/rm32/ebx . . . . . 3/imm32/0b11 # bitwise and of ebx # sib <<= 2 c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 2/imm8 # shift ebx left by 2 bits @@ -2850,7 +2850,7 @@ $emit-sib:end: emit-disp: # line : (address stream byte), out : (address buffered-file) # pseudocode: # rewind-stream(line) - # var word-slice = {0, 0} + # var word-slice : (ref slice) # while true # word-slice = next-word(line) # if (slice-empty?(word-slice)) break @@ -2872,7 +2872,7 @@ emit-disp: # line : (address stream byte), out : (address buffered-file) 50/push-eax 51/push-ecx 52/push-edx - # var word-slice/ecx = {0, 0} + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -2967,17 +2967,17 @@ $emit-disp:check0: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) pass through - 3d/compare-eax-and 0/imm32 + # . if (eax != false) pass through + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-disp:break/disp32 $emit-disp:check1: # if (slice-starts-with?(word-slice, "#")) break - # . start/edx = word-slice->start + # . var start/edx : (address byte) = word-slice->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL - # . if (eax == '#') break + # . if (c == '#') break 3d/compare-eax-and 0x23/imm32/hash 0f 84/jump-if-equal $emit-disp:break/disp32 $emit-disp:check-for-disp32: @@ -2990,8 +2990,8 @@ $emit-disp:check-for-disp32: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-disp:check-for-disp16/disp8 $emit-disp:disp32: # emit(out, word-slice, 4) @@ -3015,8 +3015,8 @@ $emit-disp:check-for-disp16: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-disp:check-for-disp8/disp8 $emit-disp:disp16: # emit(out, word-slice, 2) @@ -3040,8 +3040,8 @@ $emit-disp:check-for-disp8: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) loop - 3d/compare-eax-and 0/imm32 + # . if (eax == false) loop + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $emit-disp:loop/disp32 $emit-disp:disp8: # emit(out, word-slice, 1) @@ -3069,7 +3069,7 @@ $emit-disp:break: emit-imm: # line : (address stream byte), out : (address buffered-file) # pseudocode: # rewind-stream(line) - # var word-slice = {0, 0} + # var word-slice : (ref slice) # while true # word-slice = next-word(line) # if (slice-empty?(word-slice)) break @@ -3091,7 +3091,7 @@ emit-imm: # line : (address stream byte), out : (address buffered-file) 50/push-eax 51/push-ecx 52/push-edx - # var word-slice/ecx = {0, 0} + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -3186,17 +3186,17 @@ $emit-imm:check0: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) pass through - 3d/compare-eax-and 0/imm32 + # . if (eax != false) pass through + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-imm:break/disp32 $emit-imm:check1: # if (slice-starts-with?(word-slice, "#")) break - # . start/edx = slice->start + # . var start/edx : (address byte) = slice->start 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - # . c/eax = *start + # . var c/eax : byte = *start 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL - # . if (eax == '#') break + # . if (c == '#') break 3d/compare-eax-and 0x23/imm32/hash 0f 84/jump-if-equal $emit-imm:break/disp32 $emit-imm:check-for-imm32: @@ -3209,8 +3209,8 @@ $emit-imm:check-for-imm32: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-imm:check-for-imm16/disp8 $emit-imm:imm32: # emit(out, word-slice, 4) @@ -3234,8 +3234,8 @@ $emit-imm:check-for-imm16: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-imm:check-for-imm8/disp8 $emit-imm:imm16: # emit(out, word-slice, 2) @@ -3259,8 +3259,8 @@ $emit-imm:check-for-imm8: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) loop - 3d/compare-eax-and 0/imm32 + # . if (eax == false) loop + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $emit-imm:loop/disp32 $emit-imm:imm8: # emit(out, word-slice, 1) @@ -5837,7 +5837,7 @@ test-convert-instruction-handles-imm8-operand: c3/return # shortcut for parse-hex-int(next-token-from-slice(word->start, word->end, '/')) -parse-datum-of-word: # word : (address slice) -> value/eax +parse-datum-of-word: # word : (address slice) -> value/eax : int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -5846,7 +5846,7 @@ parse-datum-of-word: # word : (address slice) -> value/eax 56/push-esi # esi = word 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -5860,7 +5860,7 @@ parse-datum-of-word: # word : (address slice) -> value/eax e8/call next-token-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # value/eax = parse-hex-int(slice) + # return parse-hex-int(slice) # . . push args 51/push-ecx # . . call diff --git a/apps/sigils b/apps/sigils index a792c7e0..a1f33ada 100755 Binary files a/apps/sigils and b/apps/sigils differ diff --git a/apps/sigils.subx b/apps/sigils.subx index e6aba87a..a22aee44 100644 --- a/apps/sigils.subx +++ b/apps/sigils.subx @@ -78,8 +78,8 @@ Entry: # run tests if necessary, convert stdin if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto interactive - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto interactive + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-sigils-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 @@ -147,7 +147,7 @@ subx-sigils: # in : (address buffered-file), out : (address buffered-file) 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var word-slice/edx = {0, 0} + # var word-slice/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -189,8 +189,8 @@ $subx-sigils:check1: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $subx-sigils:next-line/disp32 $subx-sigils:check-for-comment: # if (slice-starts-with?(word-slice, "#")) continue @@ -269,8 +269,8 @@ $subx-sigils:check-for-indirect-mode: e8/call disp32-mode?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax == 0) goto indirect mode - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto indirect mode + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-sigils:indirect-mode/disp8 $subx-sigils:disp32-mode: # emit-indirect-mode(out, word-slice) @@ -1365,7 +1365,7 @@ emit-direct-mode: # out : (address buffered-file), word-slice : (address slice) 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 50/push-eax - # var local-slice/eax : (address slice) = {word-slice->start, word-slice->end} + # var local-slice/eax : (ref slice) = {word-slice->start, word-slice->end} 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) ff 6/subop/push 0/mod/indirect 0/rm32/eax . . . . . . # push *eax @@ -1834,7 +1834,7 @@ test-next-word-or-expression: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -1907,7 +1907,7 @@ test-next-word-or-expression-returns-whole-comment: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -1980,7 +1980,7 @@ test-next-word-or-expression-returns-empty-slice-on-eof: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -2022,7 +2022,7 @@ test-next-word-or-expression-returns-string-literal: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -2085,7 +2085,7 @@ test-next-word-or-expression-returns-string-with-escapes: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -2148,7 +2148,7 @@ test-next-word-or-expression-returns-whole-expression: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var slice/ecx = {0, 0} + # var slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -2250,7 +2250,7 @@ parse-effective-address: # word-slice : (address slice) -> base/eax, index/ecx, # . save registers 56/push-esi 57/push-edi - # var local-slice/esi : (address slice) = {word-slice->start, word-slice->end} + # var local-slice/esi : (ref slice) = {word-slice->start, word-slice->end} 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi @@ -2679,7 +2679,7 @@ next-register: # in : (address slice) -> reg/eax : int 56/push-esi # esi = in 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # var reg-slice/ecx : (address slice) = {in->start, in->start + 3} + # var reg-slice/ecx : (ref slice) = {in->start, in->start + 3} 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax 05/add-to-eax 3/imm32 50/push-eax @@ -3865,7 +3865,7 @@ disp32-mode?: # in : (address slice) -> reg/eax : boolean # . save registers 56/push-esi 57/push-edi - # var local-slice/esi : (address slice) = {in->start, in->end} + # var local-slice/esi : (ref slice) = {in->start, in->end} 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi @@ -3923,7 +3923,7 @@ emit-indirect-disp32: # out : (address buffered-file), word-slice : (address sl 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 56/push-esi - # var local-slice/esi : (address slice) = {in->start, in->end} + # var local-slice/esi : (ref slice) = {in->start, in->end} 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi @@ -4055,8 +4055,8 @@ $next-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 == 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax == false) break + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $next-hex-int:break/disp8 # eax = from-hex-char(*curr) # . . copy arg to eax @@ -4071,7 +4071,8 @@ $next-hex-int:loop: # loop eb/jump $next-hex-int:loop/disp8 $next-hex-int:break: - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32 # compare ebx + # if (negate?) result = -result + 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32/false # compare ebx 74/jump-if-equal $next-hex-int:end/disp8 $next-hex-int:negate: f7 3/subop/negate 3/mod/direct 7/rm32/edi . . . . . . # negate edi @@ -4437,8 +4438,8 @@ $next-positive-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 == 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax == false) break + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $next-positive-hex-int:end/disp8 # eax = from-hex-char(*curr) # . . copy arg to eax diff --git a/apps/survey b/apps/survey index 23eb9e3b..2ec38e5d 100755 Binary files a/apps/survey and b/apps/survey differ diff --git a/apps/survey.subx b/apps/survey.subx index 8563116f..e365ac1b 100644 --- a/apps/survey.subx +++ b/apps/survey.subx @@ -74,8 +74,8 @@ Entry: # run tests if necessary, convert stdin if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto interactive - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto interactive + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-survey-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 @@ -115,9 +115,9 @@ $subx-survey-main:end: subx-survey: # infile : (address buffered-file), out : (address buffered-file) # pseudocode - # var in : (address stream byte) = stream(4096) + # var in : (ref stream byte 4096) # slurp(infile, in) - # var segments : (stream segment-info 10) + # var segments : (stream segment-info) # var labels : (stream label-info Max-labels) # compute-offsets(in, segments, labels) # compute-addresses(segments, labels) @@ -131,13 +131,13 @@ subx-survey: # infile : (address buffered-file), out : (address buffered-file) 51/push-ecx 52/push-edx 56/push-esi - # var segments/ecx = stream(10 * 16) + # var segments/ecx : (ref stream {string, segment-info} 160) # 10 rows * 16 bytes/row 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 68/push 0xa0/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var labels/edx = stream(Max-labels * 16) + # var labels/edx : (ref stream label-info Max-labels*16) # . data 2b/subtract 0/mod/indirect 5/rm32/.disp32 . . 4/r32/esp Max-labels/disp32 # subtract *Max-labels from esp # . length @@ -147,7 +147,7 @@ subx-survey: # infile : (address buffered-file), out : (address buffered-file) # . write 68/push 0/imm32/write 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # var in/esi = stream(Input-size * 1) + # var in/esi : (ref stream byte Input-size) # . data 2b/subtract 0/mod/indirect 5/rm32/.disp32 . . 4/r32/esp Input-size/disp32 # subtract *Input-size from esp # . length @@ -618,7 +618,7 @@ compute-offsets:segment-tmp: # slice == code -compute-offsets: # in : (address stream), segments : (address stream {string, segment-info}), labels : (address stream {string, label-info}) +compute-offsets: # in : (address stream byte), segments : (address stream {string, segment-info}), labels : (address stream {string, label-info}) # skeleton: # for lines in 'in' # for words in line @@ -833,8 +833,8 @@ $compute-offsets:case-empty: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $compute-offsets:line-loop/disp32 $compute-offsets:case-comment: # if slice-starts-with?(word-slice, "#") continue @@ -843,8 +843,8 @@ $compute-offsets:case-comment: e8/call slice-starts-with?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $compute-offsets:line-loop/disp32 $compute-offsets:case-segment-header: # if (!slice-equal?(word-slice/edx, "==")) goto next case @@ -854,8 +854,8 @@ $compute-offsets:case-segment-header: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next case - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next case + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $compute-offsets:case-label/disp32 # if (curr-segment-name == 0) goto construct-next-segment 81 7/subop/compare 3/mod/direct 6/rm32/esi . . . . . 0/imm32 # compare esi @@ -973,8 +973,8 @@ $compute-offsets:update-curr-segment-name: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) abort - 3d/compare-eax-and 0/imm32 + # . if (eax != false) abort + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $compute-offsets:abort/disp32 # seg/ebx = get-or-insert(segments, curr-segment-name, row-size=16) # . . push args @@ -1022,8 +1022,8 @@ $compute-offsets:case-label: e8/call is-label?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax == 0) goto next case - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next case + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $compute-offsets:case-default/disp8 # strip trailing ':' from word-slice ff 1/subop/decrement 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # decrement *(edx+4) @@ -1219,13 +1219,13 @@ test-compute-offsets: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # var segments/ecx = stream(2 * 16) + # var segments/ecx : (ref stream byte 2*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # subtract from esp 68/push 0x20/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var labels/edx = stream(2 * 16) + # var labels/edx : (ref stream byte 2*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # subtract from esp 68/push 0x20/imm32/length 68/push 0/imm32/read @@ -1381,7 +1381,7 @@ test-compute-offsets: compute-addresses: # segments : (address stream {string, segment-info}), labels : (address stream {string, label-info}) # pseudocode: # srow : (address segment-info) = segments->data - # max = segments->data + segments->write + # max = &segments->data[segments->write] # num-segments = segments->write / 16 # starting-offset = 0x34 + (num-segments * 0x20) # while true @@ -1392,7 +1392,7 @@ compute-addresses: # segments : (address stream {string, segment-info}), labels # trace-sssns("segment " s->key " starts at address " s->address) # srow += 16 # row-size # lrow : (address label-info) = labels->data - # max = labels->data + labels->write + # max = &labels->data[labels->write] # while true # if (lrow >= max) break # seg-name : (address string) = lrow->segment-name @@ -1422,7 +1422,7 @@ compute-addresses: # segments : (address stream {string, segment-info}), labels 81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 0x34/imm32 # add to edi # srow/eax = segments->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 0xc/disp8 . # copy esi+12 to eax - # max/ecx = segments->data + segments->write + # max/ecx = &segments->data[segments->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx 01/add 3/mod/direct 1/rm32/ecx . . . 6/r32/esi . . # add esi to ecx $compute-addresses:segment-loop: @@ -1489,7 +1489,7 @@ $compute-addresses:segment-break: 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi # lrow/eax = labels->data 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 0xc/disp8 . # copy esi+12 to eax - # max/ecx = labels->data + labels->write + # max/ecx = &labels->data[labels->write] 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx 01/add 3/mod/direct 1/rm32/ecx . . . 6/r32/esi . . # add esi to ecx $compute-addresses:label-loop: @@ -1621,13 +1621,13 @@ test-compute-addresses: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # setup - # . var segments/ecx = stream(10 * 16) + # . var segments/ecx : (ref stream byte 10*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 68/push 0xa0/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # . var labels/edx = stream(512 * 16) + # . var labels/edx : (ref stream byte 512*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 68/push 0x2000/imm32/length 68/push 0/imm32/read @@ -1790,13 +1790,13 @@ test-compute-addresses-large-segments: 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # setup - # . var segments/ecx = stream(10 * 16) + # . var segments/ecx : (ref stream byte 10*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 68/push 0xa0/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # . var labels/edx = stream(512 * 16) + # . var labels/edx : (ref stream byte 512*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 68/push 0x2000/imm32/length 68/push 0/imm32/read @@ -1871,7 +1871,7 @@ test-compute-addresses-large-segments: 5d/pop-to-ebp c3/return -emit-output: # in : (address stream), out : (address buffered-file), segments : (address stream {string, segment-info}), labels : (address stream {string, label-info}) +emit-output: # in : (address stream byte), out : (address buffered-file), segments : (address stream {string, segment-info}), labels : (address stream {string, label-info}) # pseudocode: # emit-headers(out, segments, labels) # emit-segments(in, out, segments, labels) @@ -1922,7 +1922,7 @@ $emit-output:end: 5d/pop-to-ebp c3/return -emit-segments: # in : (address stream), out : (address buffered-file), segments : (address stream {string, segment-info}), labels : (address stream {string, label-info}) +emit-segments: # in : (address stream byte), out : (address buffered-file), segments : (address stream {string, segment-info}), labels : (address stream {string, label-info}) # pseudocode: # var offset-of-next-instruction = 0 # var line : (stream byte 512) @@ -1993,11 +1993,11 @@ emit-segments: # in : (address stream), out : (address buffered-file), segments 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var word-slice/edx = {0, 0} + # var word-slice/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # var datum/edi = {0, 0} + # var datum/edi : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi @@ -2139,8 +2139,8 @@ $emit-segments:check-for-label: e8/call is-label?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-segments:line-loop/disp32 $emit-segments:check-for-segment-header: # if (slice-equal?(word-slice, "==")) break @@ -2152,8 +2152,8 @@ $emit-segments:check-for-segment-header: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-segments:line-loop/disp32 $emit-segments:2-character: # if (length(word-slice) != 2) goto next check @@ -2275,8 +2275,8 @@ $emit-segments:check-global-variable: e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) goto code label checks - 3d/compare-eax-and 0/imm32 + # . if (eax != false) goto code label checks + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-segments:check-code-label-for-imm8/disp32 $emit-segments:check-global-variable-for-disp8: # if has-metadata?(word-slice, "disp8") abort @@ -2288,8 +2288,8 @@ $emit-segments:check-global-variable-for-disp8: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) abort - 3d/compare-eax-and 0/imm32 + # . if (eax != false) abort + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-segments:global-variable-abort/disp32 $emit-segments:check-global-variable-for-imm8: # if has-metadata?(word-slice, "imm8") abort @@ -2301,8 +2301,8 @@ $emit-segments:check-global-variable-for-imm8: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) abort - 3d/compare-eax-and 0/imm32 + # . if (eax != false) abort + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-segments:global-variable-abort/disp32 $emit-segments:emit-global-variable: # emit-hex(out, info->address, 4) @@ -2326,8 +2326,8 @@ $emit-segments:check-code-label-for-imm8: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) abort - 3d/compare-eax-and 0/imm32 + # . if (eax != false) abort + 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-not-equal $emit-segments:imm8-abort/disp32 $emit-segments:check-code-label-for-imm32: # if (!has-metadata?(word-slice, "imm32")) goto next check @@ -2339,7 +2339,7 @@ $emit-segments:check-code-label-for-imm32: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check + # . if (eax == false) goto next check 3d/compare-eax-and 0/imm32 74/jump-if-equal $emit-segments:check-code-label-for-disp8/disp8 #? # dump info->address {{{ @@ -2397,8 +2397,8 @@ $emit-segments:check-code-label-for-disp8: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-segments:check-code-label-for-disp32/disp8 $emit-segments:emit-code-label-disp8: # emit-hex(out, info->offset - offset-of-next-instruction, 1) @@ -2424,8 +2424,8 @@ $emit-segments:check-code-label-for-disp32: e8/call has-metadata?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) abort - 3d/compare-eax-and 0/imm32 + # . if (eax == false) abort + 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-equal $emit-segments:abort/disp32 $emit-segments:emit-code-label-disp32: # emit-hex(out, info->offset - offset-of-next-instruction, 4) @@ -2577,13 +2577,13 @@ test-emit-segments-global-variable: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . var segments/ecx = stream(10 * 16) + # . var segments/ecx : (ref stream byte 10*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 68/push 0xa0/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # . var labels/edx = stream(512 * 16) + # . var labels/edx : (ref stream byte 512*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 68/push 0x2000/imm32/length 68/push 0/imm32/read @@ -2814,13 +2814,13 @@ test-emit-segments-code-label: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . var segments/ecx = stream(10 * 16) + # . var segments/ecx : (ref stream byte 10*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 68/push 0xa0/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # . var labels/edx = stream(512 * 16) + # . var labels/edx : (ref stream byte 512*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 68/push 0x2000/imm32/length 68/push 0/imm32/read @@ -3016,13 +3016,13 @@ test-emit-segments-code-label-absolute: e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . var segments/ecx = stream(10 * 16) + # . var segments/ecx : (ref stream byte 10*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 68/push 0xa0/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # . var labels/edx = stream(512 * 16) + # . var labels/edx : (ref stream byte 512*16) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 68/push 0x2000/imm32/length 68/push 0/imm32/read @@ -3177,7 +3177,7 @@ emit-headers: # out : (address buffered-file), segments : (address stream {stri # pseudocode: # emit-elf-header(out, segments, labels) # curr-segment = segments->data - # max = segments->data + segments->write + # max = &segments->data[segments->write] # while true # if (curr-segment >= max) break # emit-elf-program-header-entry(out, curr-segment) @@ -3213,7 +3213,7 @@ emit-headers: # out : (address buffered-file), segments : (address stream {stri 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx # curr-segment/eax = segments->data 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 0xc/disp8 . # copy eax+12 to eax - # max/ecx = segments->data + segments->write + # max/ecx = &segments->data[segments->write] 01/add 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # add eax to ecx $emit-headers:loop: # if (curr-segment >= max) break @@ -3431,8 +3431,8 @@ emit-elf-program-header-entry: # out : (address buffered-file), curr-segment : e8/call string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto next check - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $emit-elf-program-header-entry:data/disp8 # *$Elf_p_flags = r-x c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . $Elf_p_flags/disp32 5/imm32 # copy to *$Elf_p_flags @@ -3479,12 +3479,12 @@ stream-add4: # in : (address stream byte), key : address, val1 : address, val2 56/push-esi # esi = in 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/eax = in->data + in->write + # curr/eax = &in->data[in->write] # . eax = in->write 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax # . eax = esi+eax+12 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy esi+eax+12 to eax - # max/edx = in->data + in->length + # max/edx = &in->data[in->length] # . edx = in->length 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 8/disp8 . # copy *(esi+8) to edx # . edx = esi+edx+12 @@ -3830,7 +3830,7 @@ test-trace-slsls: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var b/ebx : (address slice) = {eax, ecx} + # var b/ebx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx @@ -3839,7 +3839,7 @@ test-trace-slsls: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var d/edx : (address slice) = {eax, ecx} + # var d/edx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -3955,7 +3955,7 @@ test-trace-slsns: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var b/ebx : (address slice) = {eax, ecx} + # var b/ebx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx @@ -4071,7 +4071,7 @@ test-trace-slsss: 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 - # var b/ebx : (address slice) = {eax, ecx} + # var b/ebx : (ref slice) = {eax, ecx} 51/push-ecx 50/push-eax 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx @@ -4125,7 +4125,7 @@ test-trace-slsss: 5d/pop-to-ebp c3/return -num-bytes: # line : (address stream) -> eax : int +num-bytes: # line : (address stream byte) -> eax : int # pseudocode: # result = 0 # while true @@ -4150,7 +4150,7 @@ num-bytes: # line : (address stream) -> eax : int 53/push-ebx # var result/eax = 0 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - # var word-slice/ecx = {0, 0} + # var word-slice/ecx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx @@ -4247,8 +4247,8 @@ $num-bytes:check0: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false # . restore result now that ZF is set 58/pop-to-eax 75/jump-if-not-equal $num-bytes:end/disp8 @@ -4284,8 +4284,8 @@ $num-bytes:check-for-segment-header: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false # . restore result now that ZF is set 58/pop-to-eax 75/jump-if-not-equal $num-bytes:end/disp8 diff --git a/apps/tests b/apps/tests index dd75aac1..b292f93b 100755 Binary files a/apps/tests and b/apps/tests differ diff --git a/apps/tests.subx b/apps/tests.subx index f31f4d16..1d00cf30 100644 --- a/apps/tests.subx +++ b/apps/tests.subx @@ -43,8 +43,8 @@ Entry: # run tests if necessary, convert stdin if not e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) goto run-main - 3d/compare-eax-and 0/imm32 + # . if (eax == false) goto run-main + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-tests-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 @@ -101,13 +101,13 @@ subx-gen-run-tests: # in : (address buffered-file), out : (address buffered-fil 52/push-edx 53/push-ebx 57/push-edi - # var line/ecx : (address stream byte) = stream(512) + # var line/ecx : (ref stream byte 512) 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var word-slice/edx = {0, 0} + # var word-slice/edx : (ref slice) 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -178,8 +178,8 @@ $subx-gen-run-tests:check-for-label: e8/call is-label?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax == 0) continue - 3d/compare-eax-and 0/imm32 + # . if (eax == false) continue + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-gen-run-tests:continue/disp8 $subx-gen-run-tests:check-label-prefix: # strip trailing ':' from word-slice @@ -192,8 +192,8 @@ $subx-gen-run-tests:check-label-prefix: e8/call slice-starts-with?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == 0) break - 3d/compare-eax-and 0/imm32 + # . if (eax == false) break + 3d/compare-eax-and 0/imm32/false 74/jump-if-equal $subx-gen-run-tests:continue/disp8 $subx-gen-run-tests:call-test-function: # tests-found? = true @@ -242,7 +242,7 @@ $subx-gen-run-tests:continue: e9/jump $subx-gen-run-tests:loop/disp32 $subx-gen-run-tests:break: # if (!tests-found?) goto end - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32 # compare ebx + 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32/false # compare ebx 74/jump-if-equal $subx-gen-run-tests:end/disp8 # write(new-code-segment, " c3/return\n") # . . push args