6182 - start of support for safe handles

So far it's unclear how to do this in a series of small commits. Still
nibbling around the edges. In this commit we standardize some terminology:

The length of an array or stream is denominated in the high-level elements.
The _size_ is denominated in bytes.

The thing we encode into the type is always the size, not the length.

There's still an open question of what to do about the Mu `length` operator.
I'd like to modify it to provide the length. Currently it provides the
size. If I can't fix that I'll rename it.
This commit is contained in:
Kartik Agaram 2020-04-03 12:35:53 -07:00
parent f730f2f2c7
commit bfcc0f858a
42 changed files with 221 additions and 221 deletions

View File

@ -1,11 +1,11 @@
# Checking null-terminated ascii strings.
#
# By default we create strings as arrays of bytes, and all arrays have a 4-byte
# length prefix.
# size 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'.
# null-terminated 'kernel string' with a size-prefixed 'SubX string'.
#
# To run (from the subx directory):
# $ ./bootstrap translate 05[0-2]*.subx -o /tmp/tmp52
@ -28,11 +28,11 @@ Entry: # run all tests
b8/copy-to-eax 1/imm32/exit
cd/syscall 0x80/imm8
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
# compare a null-terminated ascii string with a more idiomatic size-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: (addr kernel-string), benchmark: (addr array byte) -> eax: boolean
# pseudocode:
# n = benchmark->length
# n = benchmark->size
# s1 = s
# s2 = benchmark->data
# i = 0
@ -63,7 +63,7 @@ kernel-string-equal?: # s: (addr kernel-string), benchmark: (addr array byte) -
57/push-edi
# var s1/edi: (addr byte) = s
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
# var n/edx: int = benchmark->length
# var n/edx: int = benchmark->size
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
# var s2/esi: (addr byte) = benchmark->data

View File

@ -1,4 +1,4 @@
# Comparing 'regular' length-prefixed strings.
# Comparing 'regular' size-prefixed strings.
== code
# instruction effective address register displacement immediate
@ -15,7 +15,7 @@ Entry: # run all tests
string-equal?: # s: (addr array byte), benchmark: (addr array byte) -> eax: boolean
# pseudocode:
# if (s->length != benchmark->length) return false
# if (s->size != benchmark->size) return false
# return string-starts-with?(s, benchmark)
#
# . prologue
@ -29,10 +29,10 @@ string-equal?: # s: (addr array byte), benchmark: (addr array byte) -> eax: boo
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# edi = benchmark
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
# ecx = s->length
# ecx = s->size
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
$string-equal?:lengths:
# if (ecx != benchmark->length) return false
$string-equal?:sizes:
# if (ecx != benchmark->size) return false
39/compare 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # compare *edi and ecx
b8/copy-to-eax 0/imm32/false
75/jump-if-!= $string-equal?:end/disp8
@ -57,10 +57,10 @@ $string-equal?:end:
string-starts-with?: # s: (addr array byte), benchmark: (addr array byte) -> eax: boolean
# pseudocode:
# if (s->length < benchmark->length) return false
# if (s->size < benchmark->size) return false
# currs = s->data
# currb = benchmark->data
# maxb = &benchmark->data[benchmark->length]
# maxb = &benchmark->data[benchmark->size]
# while currb < maxb
# c1 = *currs
# c2 = *currb
@ -87,17 +87,17 @@ string-starts-with?: # s: (addr array byte), benchmark: (addr array byte) -> ea
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# edi = benchmark
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
# var blen/ecx: int = benchmark->length
# var bsize/ecx: int = benchmark->size
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
$string-starts-with?:lengths:
# if (s->length < blen) return false
$string-starts-with?:sizes:
# if (s->size < bsize) return false
39/compare 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # compare *esi with ecx
7c/jump-if-< $string-starts-with?:false/disp8
# var currs/esi: (addr byte) = s->data
81 0/subop/add 3/mod/direct 6/rm32/esi . . . . . 4/imm32 # add to esi
# var currb/edi: (addr byte) = benchmark->data
81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi
# var maxb/ecx: (addr byte) = &benchmark->data[benchmark->length]
# var maxb/ecx: (addr byte) = &benchmark->data[benchmark->size]
01/add 3/mod/direct 1/rm32/ecx . . . 7/r32/edi . . # add edi to ecx
# var c1/eax: byte = 0
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
@ -157,7 +157,7 @@ test-compare-empty-with-empty-string:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
c3/return
test-compare-empty-with-non-empty-string: # also checks length-mismatch code path
test-compare-empty-with-non-empty-string: # also checks size-mismatch code path
# eax = string-equal?("", "Abc")
# . . push args
68/push "Abc"/imm32
@ -197,7 +197,7 @@ test-compare-equal-strings:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
c3/return
test-compare-inequal-strings-equal-lengths:
test-compare-inequal-strings-equal-sizes:
# eax = string-equal?("Abc", "Adc")
# . . push args
68/push "Adc"/imm32
@ -208,7 +208,7 @@ test-compare-inequal-strings-equal-lengths:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# check-ints-equal(eax, 0, msg)
# . . push args
68/push "F - test-compare-inequal-strings-equal-lengths"/imm32
68/push "F - test-compare-inequal-strings-equal-sizes"/imm32
68/push 0/imm32/false
50/push-eax
# . . call

View File

@ -3,10 +3,10 @@
# 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: (array byte) # prefixed by size as usual
#
# some primitives for operating on streams:
# - clear-stream (clears everything but the data length)
# - clear-stream (clears everything but the data size)
# - rewind-stream (resets read pointer)
== code
@ -23,9 +23,9 @@ clear-stream: # f: (addr stream byte)
51/push-ecx
# eax = f
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
# var count/ecx: int = f->length
# var count/ecx: int = f->size
8b/copy 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 8/disp8 . # copy *(eax+8) to ecx
# var max/ecx: (addr byte) = &f->data[f->length]
# var max/ecx: (addr byte) = &f->data[f->size]
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

View File

@ -3,7 +3,7 @@
# A trace stream looks like a regular stream:
# write: int # index at which writes go
# read: int # index that we've read until
# data: (array byte) # prefixed by length as usual
# data: (array byte) # prefixed by size as usual
# Usually the trace stream will be in a separate segment set aside for the purpose.
#
# primitives for operating on traces (arguments in quotes):
@ -33,7 +33,7 @@ _test-trace-stream: # (stream byte)
0/imm32
# current read index
0/imm32
# length
# size
8/imm32
# data
00 00 00 00 00 00 00 00 # 8 bytes
@ -43,7 +43,7 @@ _test-trace-stream: # (stream byte)
# . 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
# Allocate a new segment for the trace stream, initialize its length, and save its address to Trace-stream.
# Allocate a new segment for the trace stream, initialize its size, and save its address to Trace-stream.
# The Trace-stream segment will consist of variable-length lines separated by newlines (0x0a)
initialize-trace-stream: # n: int
# . prologue
@ -67,10 +67,10 @@ initialize-trace-stream: # n: int
#? # 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
# Trace-stream->size = n - 12
# . ecx -= 12
81 5/subop/subtract 3/mod/direct 1/rm32/ecx . . . . . 0xc/imm32 # subtract from ecx
# . Trace-stream->length = ecx
# . Trace-stream->size = ecx
89/copy 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 8/disp8 . # copy ecx to *(eax+8)
$initialize-trace-stream:end:
# . restore registers
@ -100,12 +100,12 @@ trace: # line: (addr array byte)
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# var ecx: int = t->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
# var edx: int = t->length
# var edx: int = t->size
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)
# eax = _append-3(&t->data[t->write], &t->data[t->size], line)
# . . push line
56/push-esi
# . . push &t->data[t->length]
# . . push &t->data[t->size]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/edi 2/index/edx . 3/r32/ebx 0xc/disp8 . # copy edi+edx+12 to ebx
53/push-ebx
# . . push &t->data[t->write]
@ -122,10 +122,10 @@ trace: # line: (addr array byte)
01/add 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # add eax to *edi
# refresh ecx = t->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
# eax = _append-3(&t->data[t->write], &t->data[t->length], line)
# eax = _append-3(&t->data[t->write], &t->data[t->size], line)
# . . push line
68/push Newline/imm32
# . . push &t->data[t->length]
# . . push &t->data[t->size]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/edi 2/index/edx . 3/r32/ebx 0xc/disp8 . # copy edi+edx+12 to ebx
53/push-ebx
# . . push &t->data[t->write]
@ -868,8 +868,8 @@ _append-3: # out: (addr byte), outend: (addr byte), s: (addr array byte) -> num
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
# . save registers
51/push-ecx
# eax = _append-4(out, outend, &s->data[0], &s->data[s->length])
# . . push &s->data[s->length]
# eax = _append-4(out, outend, &s->data[0], &s->data[s->size])
# . . push &s->data[s->size]
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
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
@ -965,7 +965,7 @@ _test-stream-line-ABABA: # (stream byte)
8/imm32
# read
0/imm32
# length
# size
8/imm32
# data
41 42 41 42 41 0a 00 00 # 8 bytes
@ -975,7 +975,7 @@ _test-stream-empty: # (stream byte)
0/imm32
# read
0/imm32
# length
# size
8/imm32
# data
00 00 00 00 00 00 00 00 # 8 bytes
@ -985,7 +985,7 @@ _test-stream-filled: # (stream byte)
8/imm32
# read
0/imm32
# length
# size
8/imm32
# data
41 41 41 41 0a 41 41 41 # 8 bytes

View File

@ -13,7 +13,7 @@
# A stream looks like this:
# read: int # index at which to read next
# write: int # index at which writes go
# data: (array byte) # prefixed by length as usual
# data: (array byte) # prefixed by size as usual
== code
# instruction effective address register displacement immediate
@ -47,12 +47,12 @@ $write:fake:
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
# edx = f->write
8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx
# ebx = f->length
# ebx = f->size
8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 3/r32/ebx 8/disp8 . # copy *(ecx+8) to ebx
# eax = _append-3(&f->data[f->write], &f->data[f->length], s)
# eax = _append-3(&f->data[f->write], &f->data[f->size], s)
# . . push s
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
# . . push &f->data[f->length]
# . . push &f->data[f->size]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 3/index/ebx . 3/r32/ebx 0xc/disp8 . # copy ecx+ebx+12 to ebx
53/push-ebx
# . . push &f->data[f->write]
@ -150,7 +150,7 @@ _test-stream: # (stream byte)
0/imm32
# current read index
0/imm32
# length
# size
0x10/imm32
# data (2 lines x 8 bytes/line)
00 00 00 00 00 00 00 00

View File

@ -25,8 +25,8 @@ stream-data-equal?: # f: (addr stream byte), s: (addr array byte) -> eax: boole
81 0/subop/add 3/mod/direct 6/rm32/esi . . . . . 0xc/imm32 # add to esi
# edi = s
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
$stream-data-equal?:compare-lengths:
# if (f->write != s->length) return false
$stream-data-equal?:compare-sizes:
# if (f->write != s->size) return false
39/compare 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # compare *edi and eax
75/jump-if-!= $stream-data-equal?:false/disp8
# var currs/edi: (addr byte) = s->data
@ -149,7 +149,7 @@ test-stream-data-equal-2:
5d/pop-to-ebp
c3/return
test-stream-data-equal-length-check:
test-stream-data-equal-size-check:
# . prologue
55/push-ebp
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
@ -178,7 +178,7 @@ test-stream-data-equal-length-check:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# check-ints-equal(eax, 0, msg)
# . . push args
68/push "F - test-stream-data-equal-length-check"/imm32
68/push "F - test-stream-data-equal-size-check"/imm32
68/push 0/imm32
50/push-eax
# . . call
@ -230,30 +230,30 @@ $check-stream-equal:end:
next-stream-line-equal?: # f: (addr stream byte), s: (addr array byte) -> eax: boolean
# pseudocode:
# currf = f->read # bound: f->write
# currs = 0 # bound: s->length
# currs = 0 # bound: s->size
# while true
# if currf >= f->write
# return currs >= s->length
# return currs >= s->size
# if f[currf] == '\n'
# ++currf
# return currs >= s->length
# if (currs >= s->length) return false # the current line of f still has data to match
# return currs >= s->size
# if (currs >= s->size) return false # the current line of f still has data to match
# if (f[currf] != s[currs]) return false
# ++currf
# ++currs
#
# collapsing the two branches that can return true:
# currf = f->read # bound: f->write
# currs = 0 # bound: s->length
# currs = 0 # bound: s->size
# while true
# if (currf >= f->write) break
# if (f[currf] == '\n') break
# if (currs >= s->length) return false # the current line of f still has data to match
# if (currs >= s->size) return false # the current line of f still has data to match
# if (f[currf] != s[currs]) return false
# ++currf
# ++currs
# ++currf # skip '\n'
# return currs >= s->length
# return currs >= s->size
# Here the final `++currf` is sometimes unnecessary (if we're already at the end of the stream)
#
# registers:
@ -293,7 +293,7 @@ $next-stream-line-equal?:loop:
# if (c1 == '\n') break
3d/compare-eax-and 0xa/imm32/newline
74/jump-if-= $next-stream-line-equal?:break/disp8
# if (currs >= s->length) return false
# if (currs >= s->size) return false
3b/compare 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # compare edx with *edi
7d/jump-if->= $next-stream-line-equal?:false/disp8
# c2 = s->data[currs]
@ -309,7 +309,7 @@ $next-stream-line-equal?:loop:
$next-stream-line-equal?:break:
# ++currf
41/increment-ecx
# if (currs >= s->length) return true
# if (currs >= s->size) return true
3b/compare 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # compare edx with *edi
7c/jump-if-< $next-stream-line-equal?:false/disp8
$next-stream-line-equal?:true:

View File

@ -38,7 +38,7 @@
# As a reminder, a stream looks like this:
# write: int # index at which to write to next
# read: int # index at which to read next
# data: (array byte) # prefixed by length as usual
# data: (array byte) # prefixed by size as usual
== code
# instruction effective address register displacement immediate
@ -70,7 +70,7 @@ $read:fake:
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# edi = s
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to esi
# eax = _buffer-4(out = &s->data[s->write], outend = &s->data[s->length],
# eax = _buffer-4(out = &s->data[s->write], outend = &s->data[s->size],
# in = &f->data[f->read], inend = &f->data[f->write])
# . . push &f->data[f->write]
8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax
@ -80,7 +80,7 @@ $read:fake:
8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) 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
# . . push &s->data[s->length]
# . . push &s->data[s->size]
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 8/disp8 . # copy *(edi+8) to eax
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/edi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy edi+eax+12 to eax
50/push-eax
@ -116,8 +116,8 @@ _buffer-3: # out: address, outend: address, s: (array byte) -> num_bytes_buffer
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
# . save registers
51/push-ecx
# eax = _buffer-4(out, outend, &s->data[0], &s->data[s->length])
# . . push &s->data[s->length]
# eax = _buffer-4(out, outend, &s->data[0], &s->data[s->size])
# . . push &s->data[s->size]
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
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
@ -208,14 +208,14 @@ _read: # fd: int, s: (addr stream byte) -> num-bytes-read/eax: int
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi
# eax = s->write
8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax
# edx = s->length
# edx = s->size
8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 8/disp8 . # copy *(esi+8) to edx
# syscall(read, fd, &s->data[s->write], s->length - s->write)
# syscall(read, fd, &s->data[s->write], s->size - s->write)
# . . fd: ebx
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 3/r32/ebx 8/disp8 . # copy *(ebp+8) to ebx
# . . data: ecx = &s->data[s->write]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 1/r32/ecx 0xc/disp8 . # copy esi+eax+12 to ecx
# . . size: edx = s->length - s->write
# . . size: edx = s->size - s->write
29/subtract 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # subtract eax from edx
# . . syscall
b8/copy-to-eax 3/imm32/read
@ -237,14 +237,14 @@ $_read:end:
# 1 (what we have above):
# ecx = s
# eax = s->write
# edx = s->length
# edx = s->size
# # syscall
# ecx = lea ecx+eax+12
# edx = sub edx eax
#
# 2:
# ecx = s
# edx = s->length
# edx = s->size
# ecx = &s->data
# # syscall
# ecx = add ecx, s->write
@ -431,7 +431,7 @@ _test-tmp-stream: # (stream byte)
0/imm32
# current read index
0/imm32
# length
# size
8/imm32
# data
00 00 00 00 00 00 00 00 # 8 bytes

View File

@ -20,7 +20,7 @@ $Stdin->buffer:
0/imm32
# current read index
0/imm32
# length
# size
8/imm32
# data
00 00 00 00 00 00 00 00 # 8 bytes
@ -246,7 +246,7 @@ test-read-byte-buffered-refills-buffer:
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# pretend buffer is full
# . _test-buffered-file->read = 6 # >= _test-buffered-file->length
# . _test-buffered-file->read = 6 # >= _test-buffered-file->size
b8/copy-to-eax _test-buffered-file/imm32
c7 0/subop/copy 1/mod/*+disp8 0/rm32/eax . . . . 8/disp8 6/imm32 # copy to *(eax+8)
# read-byte-buffered(_test-buffered-file)
@ -279,7 +279,7 @@ $_test-buffered-file->buffer:
0/imm32
# current read index
0/imm32
# length
# size
6/imm32
# data
00 00 00 00 00 00 # 6 bytes
@ -289,7 +289,7 @@ _test-input-stream: # (stream byte)
0/imm32
# current read index
0/imm32
# length
# size
0x100/imm32 # 256 bytes
# data (16 lines x 16 bytes/line)
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@ -318,7 +318,7 @@ $_test-input-buffered-file->buffer:
0/imm32
# current read index
0/imm32
# length
# size
6/imm32
# data
00 00 00 00 00 00 # 6 bytes

View File

@ -40,7 +40,7 @@ $write-stream:fake:
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
# esi = s
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi
# eax = _append-4(&f->data[f->write], &f->data[f->length], &s->data[s->read], &s->data[s->write])
# eax = _append-4(&f->data[f->write], &f->data[f->size], &s->data[s->read], &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
@ -49,7 +49,7 @@ $write-stream:fake:
8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) 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
# . . push &f->data[f->length]
# . . push &f->data[f->size]
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 8/disp8 . # copy *(edi+8) to eax
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/edi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy edi+eax+12 to eax
50/push-eax
@ -247,7 +247,7 @@ _test-stream2: # (stream byte)
4/imm32
# current read index
1/imm32
# length
# size
8/imm32
# data
41/A 42/B 43/C 44/D 00 00 00 00 # 8 bytes

View File

@ -16,7 +16,7 @@ $Stdout->buffer:
0/imm32
# current read index
0/imm32
# length
# size
8/imm32
# data
00 00 00 00 00 00 00 00 # 8 bytes
@ -41,7 +41,7 @@ write-byte-buffered: # f: (addr buffered-file), n: int
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
# ecx = f->write
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx
# if (f->write >= f->length) flush and clear f's stream
# if (f->write >= f->size) flush and clear f's stream
3b/compare 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 0xc/disp8 . # compare ecx with *(edi+12)
7c/jump-if-< $write-byte-buffered:to-stream/disp8
# . flush(f)
@ -216,7 +216,7 @@ append-byte: # f: (addr stream byte), n: int
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
# ecx = f->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
# if (f->write >= f->length) abort
# if (f->write >= f->size) abort
3b/compare 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(edi+8)
7d/jump-if->= $append-byte:abort/disp8
$append-byte:to-stream:
@ -288,7 +288,7 @@ _test-output-stream: # (stream byte)
0/imm32
# current read index
0/imm32
# length
# size
0x400/imm32 # 1024 bytes
# data (64 lines x 16 bytes/line)
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@ -365,7 +365,7 @@ $_test-output-buffered-file->buffer:
0/imm32
# current read index
0/imm32
# length
# size
6/imm32
# data
00 00 00 00 00 00 # 6 bytes
@ -396,7 +396,7 @@ $_test-error-buffered-file->buffer:
0/imm32
# current read index
0/imm32
# length
# size
6/imm32
# data
00 00 00 00 00 00 # 6 bytes

View File

@ -8,9 +8,9 @@
write-buffered: # f: (addr buffered-file), msg: (addr array byte)
# pseudocode:
# in = msg->data
# inend = &msg->data[msg->length]
# inend = &msg->data[msg->size]
# while (in < inend)
# if f->write >= f->length
# if f->write >= f->size
# flush(f)
# clear-stream(f)
# c = *in
@ -22,7 +22,7 @@ write-buffered: # f: (addr buffered-file), msg: (addr array byte)
# in: esi
# inend: ecx
# f: edi
# f->length: edx
# f->size: edx
# f->write: ebx (cached; need to keep in sync)
# c: eax
#
@ -40,12 +40,12 @@ write-buffered: # f: (addr buffered-file), msg: (addr array byte)
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax
# var in/esi: (addr byte) = msg->data
8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 6/r32/esi 4/disp8 . # copy eax+4 to esi
# var inend/ecx: (addr byte) = &msg->data[msg->length]
# var inend/ecx: (addr byte) = &msg->data[msg->size]
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
8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
# edx = f->length
# edx = f->size
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 0xc/disp8 . # copy *(edi+12) to edx
# ebx = f->write
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 4/disp8 . # copy *(edi+4) to ebx
@ -53,7 +53,7 @@ $write-buffered:loop:
# if (in >= inend) break
39/compare 3/mod/direct 6/rm32/esi . . . 1/r32/ecx . . # compare esi with ecx
73/jump-if-addr>= $write-buffered:loop-end/disp8
# if (f->write >= f->length) flush and clear f's stream
# if (f->write >= f->size) flush and clear f's stream
39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx with edx
7c/jump-if-< $write-buffered:to-stream/disp8
# . persist f->write
@ -215,7 +215,7 @@ $Stderr->buffer:
0/imm32
# current read index
0/imm32
# length
# size
8/imm32
# data
00 00 00 00 00 00 00 00 # 8 bytes

View File

@ -362,10 +362,10 @@ parse-hex-int: # in: (addr array byte) -> result/eax: int
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
# var curr/ecx: (addr byte) = &in->data
8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy eax+4 to ecx
# var max/edx: (addr byte) = &in->data[in->length]
# . edx = in->length
# var max/edx: (addr byte) = &in->data[in->size]
# . edx = in->size
8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx
# . edx = in->data + in->length
# . edx = in->data + in->size
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
# return parse-hex-int-helper(curr, max)
# . . push args

View File

@ -11,7 +11,7 @@ new-stream: # ad: (addr allocation-descriptor), length: int, elemsize: int -> a
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
# . save registers
52/push-edx
# var n/eax: int = elemsize * length + 12 (for read, write and length)
# var n/eax: int = elemsize * length + 12 (for read, write and size)
# . eax = elemsize
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
# . eax *= length
@ -32,7 +32,7 @@ new-stream: # ad: (addr allocation-descriptor), length: int, elemsize: int -> a
e8/call allocate/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# eax->length = elemsize*length
# eax->size = elemsize*length
89/copy 1/mod/*+disp8 0/rm32/eax . . . 2/r32/edx 8/disp8 . # copy edx to *(eax+8)
# clear-stream(eax)
# . . push args
@ -100,9 +100,9 @@ test-new-stream:
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
# check-ints-equal(eax->length, 6, msg)
# check-ints-equal(eax->size, 6, msg)
# . . push args
68/push "F - test-new-stream: sets length correctly"/imm32
68/push "F - test-new-stream: sets size correctly"/imm32
68/push 6/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . . 8/disp8 # push *(eax+8)
# . . call

View File

@ -9,7 +9,7 @@
read-line-buffered: # f: (addr buffered-file), s: (addr stream byte)
# pseudocode:
# while true
# if (s->write >= s->length) abort
# if (s->write >= s->size) abort
# if (f->read >= f->write) populate stream from file
# if (f->write == 0) break
# AL = f->data[f->read]
@ -35,7 +35,7 @@ read-line-buffered: # f: (addr buffered-file), s: (addr stream byte)
# edx = s->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy *edi to edx
$read-line-buffered:loop:
# if (s->write >= s->length) abort
# if (s->write >= s->size) abort
3b/compare 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # compare edx with *(edi+8)
7d/jump-if->= $read-line-buffered:abort/disp8
# if (f->read >= f->write) populate stream from file
@ -219,7 +219,7 @@ test-read-line-buffered-reads-final-line-until-Eof:
read-line: # f: (addr stream byte), s: (addr stream byte)
# pseudocode:
# while true
# if (s->write >= s->length) abort
# if (s->write >= s->size) abort
# if (f->read >= f->write) break
# AL = f->data[f->read]
# s->data[s->write] = AL
@ -244,7 +244,7 @@ read-line: # f: (addr stream byte), s: (addr stream byte)
# edx = s->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy *edi to edx
$read-line:loop:
# if (s->write >= s->length) abort
# if (s->write >= s->size) abort
3b/compare 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # compare edx with *(edi+8)
0f 8d/jump-if->= $read-line:abort/disp32
# if (f->read >= f->write) break

View File

@ -122,7 +122,7 @@ slice-equal?: # s: (addr slice), p: (addr array byte) -> eax: boolean
# if (p == 0) return (s == 0)
# currs = s->start
# maxs = s->end
# if (maxs - currs != p->length) return false
# if (maxs - currs != p->size) return false
# currp = p->data
# while currs < maxs
# if (*currs != *currp) return false
@ -151,7 +151,7 @@ slice-equal?: # s: (addr slice), p: (addr array byte) -> eax: boolean
8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx
# var maxs/esi: (addr byte) = s->end
8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi
# var slen/eax: int = maxs - currs
# var ssize/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
@ -165,7 +165,7 @@ $slice-equal?:null-string:
74/jump-if-= $slice-equal?:true/disp8
eb/jump $slice-equal?:false/disp8
$slice-equal?:nonnull-string:
# if (slen != p->length) return false
# if (ssize != p->size) return false
39/compare 0/mod/indirect 3/rm32/ebx . . . 0/r32/eax . . # compare *ebx and eax
75/jump-if-!= $slice-equal?:false/disp8
# var currp/ebx: (addr byte) = p->data
@ -486,12 +486,12 @@ test-slice-equal-with-null:
slice-starts-with?: # s: (addr slice), head: (addr array byte) -> eax: boolean
# pseudocode
# lenh = head->length
# if (lenh > s->end - s->start) return false
# hsize = head->size
# if (hsize > s->end - s->start) return false
# i = 0
# currs = s->start
# currp = head->data
# while i < lenh
# while i < hsize
# if (*currs != *currh) return false
# ++i
# ++currs
@ -504,7 +504,7 @@ slice-starts-with?: # s: (addr slice), head: (addr array byte) -> eax: boolean
# *currs: eax
# *currh: ebx
# i: ecx
# lenh: edx
# hsize: edx
#
# . prologue
55/push-ebp
@ -522,9 +522,9 @@ slice-starts-with?: # s: (addr slice), head: (addr array byte) -> eax: boolean
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
# var lenh/edx: int = head->length
# var hsize/edx: int = head->size
8b/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy *edi to edx
# if (lenh > lens) return false
# if (hsize > lens) return false
39/compare 3/mod/direct 2/rm32/edx . . . 1/r32/ecx . . # compare edx with ecx
7f/jump-if-> $slice-starts-with?:false/disp8
# var currs/esi: (addr byte) = s->start
@ -538,7 +538,7 @@ slice-starts-with?: # s: (addr slice), head: (addr array byte) -> eax: boolean
# 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
# if (i >= hsize) return true
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
7d/jump-if->= $slice-starts-with?:true/disp8
# c1 = *currs
@ -809,7 +809,7 @@ write-slice: # out: (addr stream byte), s: (addr slice)
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
# edx = out->length
# edx = out->size
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # copy *(edi+8) to edx
# ebx = out->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 3/r32/ebx . . # copy *edi to ebx
@ -817,7 +817,7 @@ $write-slice:loop:
# if (curr >= max) break
39/compare 3/mod/direct 1/rm32/ecx . . . 6/r32/esi . . # compare ecx with esi
73/jump-if-addr>= $write-slice:loop-end/disp8
# if (out->write >= out->length) abort
# if (out->write >= out->size) abort
39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx with edx
7d/jump-if->= $write-slice:abort/disp8
# out->data[out->write] = *in
@ -925,7 +925,7 @@ write-slice-buffered: # out: (addr buffered-file), s: (addr slice)
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
# edx = out->length
# edx = out->size
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 0xc/disp8 . # copy *(edi+12) to edx
# ebx = out->write
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 4/disp8 . # copy *(edi+4) to ebx
@ -933,7 +933,7 @@ $write-slice-buffered:loop:
# if (curr >= max) break
39/compare 3/mod/direct 1/rm32/ecx . . . 6/r32/esi . . # compare ecx with esi
73/jump-if-addr>= $write-slice-buffered:loop-end/disp8
# if (out->write >= out->length) flush and clear out's stream
# if (out->write >= out->size) flush and clear out's stream
39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx with edx
7c/jump-if-< $write-slice-buffered:to-stream/disp8
# . persist out->write
@ -1056,7 +1056,7 @@ slice-to-string: # ad: (addr allocation-descriptor), in: (addr slice) -> out/ea
8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx
# var max/ebx: (addr byte) = in->end
8b/copy 1/mod/*+disp8 6/rm32/esi . . . 3/r32/ebx 4/disp8 . # copy *(esi+4) to ebx
# var size/ecx: int = 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 'size' field)
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
@ -1071,7 +1071,7 @@ slice-to-string: # ad: (addr allocation-descriptor), in: (addr slice) -> out/ea
# if (eax == 0) abort
3d/compare-eax-and 0/imm32
74/jump-if-= $slice-to-string:abort/disp8
# out->length = size-4
# out->size = 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

View File

@ -22,7 +22,7 @@ print-int32-decimal: # out: (addr stream byte), n: int32
# push '-'
# w = out->write
# curr = &out->data[out->write]
# max = &out->data[out->length]
# max = &out->data[out->size]
# while true
# pop into eax
# if (eax == sentinel) break
@ -78,7 +78,7 @@ $print-int32-decimal:write:
8b/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy *edi to edx
# var curr/ecx: (addr 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
# var max/ebx: (addr byte) = &out->data[out->length]
# var max/ebx: (addr byte) = &out->data[out->size]
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:

View File

@ -127,7 +127,7 @@ test-get:
# - setup: create a table with a couple of keys
# var table/ecx: (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 0x10/imm32/size
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
@ -308,7 +308,7 @@ test-get-slice:
# - setup: create a table with a couple of keys
# var table/ecx: (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 0x10/imm32/size
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
@ -409,7 +409,7 @@ get-or-insert: # table: (addr stream {string_key, T}), key: string_key, row-siz
# if string-equal?(key, *curr)
# return curr+4
# curr += row-size
# if table->write >= table->length
# if table->write >= table->size
# abort
# zero-out(max, row-size)
# *max = key
@ -456,7 +456,7 @@ $get-or-insert:mismatch:
$get-or-insert:not-found:
# result/eax = 0
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
# if (table->write >= table->length) abort
# if (table->write >= table->size) abort
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(esi+8)
73/jump-if-addr>= $get-or-insert:abort/disp8
@ -514,7 +514,7 @@ test-get-or-insert:
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
# var table/ecx: (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 0x10/imm32/size
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
@ -658,7 +658,7 @@ get-or-insert-slice: # table: (addr stream {string_key, T}), key: (addr slice),
# if slice-equal?(key, *curr)
# return curr+4
# curr += row-size
# if table->write >= table->length
# if table->write >= table->size
# abort
# zero-out(max, row-size)
# *max = slice-to-string(ad, key)
@ -705,7 +705,7 @@ $get-or-insert-slice:mismatch:
$get-or-insert-slice:not-found:
# result/eax = 0
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
# if (table->write >= table->length) abort
# if (table->write >= table->size) abort
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(esi+8)
7d/jump-if->= $get-or-insert-slice:abort/disp8
@ -769,7 +769,7 @@ test-get-or-insert-slice:
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
# var table/ecx: (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 0x10/imm32/size
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
@ -1054,7 +1054,7 @@ test-get-or-stop:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# var table/ecx: (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 0x10/imm32/size
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
@ -1270,7 +1270,7 @@ test-get-slice-or-stop:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# var table/ecx: (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 0x10/imm32/size
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
@ -1446,7 +1446,7 @@ test-maybe-get:
# - setup: create a table with one row
# var table/ecx: (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 0x10/imm32/size
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
@ -1593,7 +1593,7 @@ test-maybe-get-slice:
# - setup: create a table with one row
# var table/ecx: (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 0x10/imm32/size
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

View File

@ -8,7 +8,7 @@
slurp: # f: (addr buffered-file), s: (addr stream byte)
# pseudocode:
# while true
# if (s->write >= s->length) abort
# if (s->write >= s->size) abort
# if (f->read >= f->write) populate stream from file
# if (f->write == 0) break
# AL = f->data[f->read]
@ -33,7 +33,7 @@ slurp: # f: (addr buffered-file), s: (addr stream byte)
# edx = s->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy *edi to edx
$slurp:loop:
# if (s->write >= s->length) abort
# if (s->write >= s->size) abort
3b/compare 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # compare edx with *(edi+8)
7d/jump-if->= $slurp:abort/disp8
# if (f->read >= f->write) populate stream from file

View File

@ -16,7 +16,7 @@ compute-width: # word: (addr 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
# var ecx: (addr byte) = &word[word->length]
# var ecx: (addr byte) = &word[word->size]
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

View File

@ -19,7 +19,7 @@ emit-hex-array: # out: (addr buffered-file), arr: (addr array byte)
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx
# var curr/ecx: (addr byte) = arr->data
8d/copy-address 1/mod/*+disp8 2/rm32/edx . . . 1/r32/ecx 4/disp8 . # copy edx+4 to ecx
# var max/edx: (addr byte) = &arr->data[arr->length]
# var max/edx: (addr byte) = &arr->data[arr->size]
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
# var c/eax: byte = 0
@ -73,7 +73,7 @@ test-emit-hex-array:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# var arr/ecx (array byte) = [01, 02, 03]
68/push 0x00030201/imm32 # bytes 01 02 03
68/push 3/imm32/length
68/push 3/imm32/size
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# emit-hex-array(_test-output-buffered-file, arr)
# . . push args

View File

@ -17,7 +17,7 @@ write-int: # out: (addr stream byte), n: int
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
# ecx = out->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
# if (out->write >= out->length) abort
# if (out->write >= out->size) abort
3b/compare 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(edi+8)
7d/jump-if->= $write-int:abort/disp8
$write-int:to-stream:

View File

@ -1,6 +1,6 @@
# A stack looks like this:
# top: int
# data: (array byte) # prefixed by length as usual
# data: (array byte) # prefixed by size as usual
== code
# instruction effective address register displacement immediate
@ -16,7 +16,7 @@ clear-stack: # s: (addr stack)
51/push-ecx
# eax = s
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
# var max/ecx: (addr byte) = &s->data[s->length]
# var max/ecx: (addr byte) = &s->data[s->size]
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
@ -48,7 +48,7 @@ test-clear-stack:
# var stack/ecx = stack of size 8 with random data in it
68/push 34/imm32
68/push 35/imm32
68/push 8/imm32/length
68/push 8/imm32/size
68/push 14/imm32/top
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# clear(stack)
@ -69,11 +69,11 @@ test-clear-stack:
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
# length should remain 8
# size should remain 8
58/pop-to-eax
# . check-ints-equal(eax, 8, msg)
# . . push args
68/push "F - test-clear-stack: length"/imm32
68/push "F - test-clear-stack: size"/imm32
68/push 8/imm32
50/push-eax
# . . call
@ -119,7 +119,7 @@ push: # s: (addr stack), n: int
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# ecx = s->top
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
# if (s->top >= s->length) abort
# if (s->top >= s->size) abort
39/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # compare *(esi+4) and ecx
7e/jump-if-<= $push:abort/disp8
# s->data[s->top] = n
@ -167,7 +167,7 @@ test-push:
# var stack/ecx = empty stack of size 8
68/push 0/imm32
68/push 0/imm32
68/push 8/imm32/length
68/push 8/imm32/size
68/push 0/imm32/top
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# push(stack, 0x42)
@ -189,11 +189,11 @@ test-push:
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
# check length
# check size
58/pop-to-eax
# . check-ints-equal(eax, 8, msg)
# . . push args
68/push "F - test-push: length"/imm32
68/push "F - test-push: size"/imm32
68/push 8/imm32
50/push-eax
# . . call
@ -285,7 +285,7 @@ test-pop:
# var stack/ecx = stack of size 8 containing just 0x42
68/push 0/imm32
68/push 0x42/imm32
68/push 8/imm32/length
68/push 8/imm32/size
68/push 4/imm32/top
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# eax = pop(stack)
@ -315,11 +315,11 @@ test-pop:
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
# check length
# check size
58/pop-to-eax
# . check-ints-equal(eax, 8, msg)
# . . push args
68/push "F - test-pop: length"/imm32
68/push "F - test-pop: size"/imm32
68/push 8/imm32
50/push-eax
# . . call
@ -386,7 +386,7 @@ test-top:
# var stack/ecx = stack of size 8 containing just 0x42
68/push 0/imm32
68/push 0x42/imm32
68/push 8/imm32/length
68/push 8/imm32/size
68/push 4/imm32/top
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# eax = top(stack)

View File

@ -4,12 +4,12 @@
array-equal?: # a: (addr array int), b: (addr array int) -> eax: boolean
# pseudocode:
# lena = a->length
# if (lena != b->length) return false
# asize = a->size
# if (asize != b->size) return false
# i = 0
# curra = a->data
# currb = b->data
# while i < lena
# while i < asize
# i1 = *curra
# i2 = *currb
# if (c1 != c2) return false
@ -18,7 +18,7 @@ array-equal?: # a: (addr array int), b: (addr array int) -> eax: boolean
#
# registers:
# i: ecx
# lena: edx
# asize: edx
# curra: esi
# currb: edi
# i1: eax
@ -37,10 +37,10 @@ array-equal?: # a: (addr array int), b: (addr array int) -> eax: boolean
8b/-> *(ebp+8) 6/r32/esi
# edi = b
8b/-> *(ebp+0xc) 7/r32/edi
# var lena/edx: int = a->length
# var asize/edx: int = a->size
8b/-> *esi 2/r32/edx
$array-equal?:lengths:
# if (lena != b->length) return false
$array-equal?:sizes:
# if (asize != b->size) return false
39/compare *edi 2/r32/edx
75/jump-if-!= $array-equal?:false/disp8
# var curra/esi: (addr byte) = a->data
@ -52,7 +52,7 @@ $array-equal?:lengths:
# var vala/eax: int
# var valb/ebx: int
$array-equal?:loop:
# if (i >= lena) return true
# if (i >= asize) return true
39/compare %ecx 2/r32/edx
7d/jump-if->= $array-equal?:true/disp8
# var vala/eax: int = *curra
@ -104,7 +104,7 @@ test-compare-empty-with-empty-array:
5d/pop-to-ebp
c3/return
test-compare-empty-with-non-empty-array: # also checks length-mismatch code path
test-compare-empty-with-non-empty-array: # also checks size-mismatch code path
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
@ -147,7 +147,7 @@ test-compare-equal-arrays:
5d/pop-to-ebp
c3/return
test-compare-inequal-arrays-equal-lengths:
test-compare-inequal-arrays-equal-sizes:
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
@ -165,7 +165,7 @@ test-compare-inequal-arrays-equal-lengths:
89/<- %edx 4/r32/esp
#
(array-equal? %ecx %edx) # => eax
(check-ints-equal %eax 0 "F - test-compare-inequal-arrays-equal-lengths")
(check-ints-equal %eax 0 "F - test-compare-inequal-arrays-equal-sizes")
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
@ -173,7 +173,7 @@ test-compare-inequal-arrays-equal-lengths:
parse-array-of-ints: # ad: (addr allocation-descriptor), s: (addr string) -> result/eax: (handle array int)
# pseudocode
# end = &s->data[s->length]
# end = &s->data[s->size]
# curr = s->data
# size = 0
# while true
@ -209,8 +209,8 @@ parse-array-of-ints: # ad: (addr allocation-descriptor), s: (addr string) -> re
8b/-> *(ebp+0xc) 6/r32/esi
# var curr/ecx: (addr byte) = s->data
8d/copy-address *(esi+4) 1/r32/ecx
# var end/edx: (addr byte) = &s->data[s->length]
# . edx = s->length
# var end/edx: (addr byte) = &s->data[s->size]
# . edx = s->size
8b/-> *esi 2/r32/edx
# . edx += curr
01/add-to %edx 1/r32/ecx

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -108,12 +108,12 @@ compile: # in: (addr buffered-file), out: fd or (addr stream byte), err: fd or
# var num/ecx: (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.
# Add 12 bytes for 'read', 'write' and 'size' fields, for a total of 19 bytes, or 0x13 in hex.
# The stack pointer is no longer aligned, so dump_stack() can be misleading past this point.
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x13/imm32 # subtract from esp
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# initialize the stream
# . num->length = 7
# . num->size = 7
c7 0/subop/copy 1/mod/*+disp8 1/rm32/ecx . . . . 8/disp8 7/imm32 # copy to *(ecx+8)
# . clear-stream(num)
# . . push args
@ -194,7 +194,7 @@ $compile:end:
get-num: # in: (addr buffered-file), out: (addr stream byte), err: fd or (addr stream byte), ed: (addr exit-descriptor)
# pseudocode:
# if (!is-digit?(Look)) expected(ed, err, "integer")
# if out->write >= out->length
# if out->write >= out->size
# write(err, "Error: too many digits in number\n")
# stop(ed, 1)
# out->data[out->write] = LSB(Look)
@ -205,7 +205,7 @@ get-num: # in: (addr buffered-file), out: (addr stream byte), err: fd or (addr
# in: esi
# out: edi
# out->write: ecx (cached copy; need to keep in sync)
# out->length: edx
# out->size: edx
# temporaries: eax, ebx
# We can't allocate Look to a register because it gets written implicitly in
# get-char in each iteration of the loop. (Thereby demonstrating that it's
@ -250,10 +250,10 @@ $get-num:main:
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
# ecx = out->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
# edx = out->length
# edx = out->size
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # copy *(edi+8) to edx
$get-num:loop:
# if (out->write >= out->length) error
# if (out->write >= out->size) error
39/compare 3/mod/direct 2/rm32/edx . . . 1/r32/ecx . . # compare edx with ecx
7d/jump-if-< $get-num:stage2/disp8
# . error(ed, err, msg) # TODO: show full number

Binary file not shown.

View File

@ -108,12 +108,12 @@ compile: # in: (addr buffered-file), out: fd or (addr stream byte), err: fd or
# var num/ecx: (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.
# Add 12 bytes for 'read', 'write' and 'size' fields, for a total of 19 bytes, or 0x13 in hex.
# The stack pointer is no longer aligned, so dump_stack() can be misleading past this point.
81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x13/imm32 # subtract from esp
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# initialize the stream
# . num->length = 7
# . num->size = 7
c7 0/subop/copy 1/mod/*+disp8 1/rm32/ecx . . . . 8/disp8 7/imm32 # copy to *(ecx+8)
# . clear-stream(num)
# . . push args
@ -195,7 +195,7 @@ get-num: # in: (addr buffered-file), out: (addr stream byte), err: fd or (addr
# pseudocode:
# if (!is-digit?(Look)) expected(ed, err, "integer")
# do
# if out->write >= out->length
# if out->write >= out->size
# write(err, "Error: too many digits in number\n")
# stop(ed, 1)
# out->data[out->write] = LSB(Look)
@ -210,7 +210,7 @@ get-num: # in: (addr buffered-file), out: (addr stream byte), err: fd or (addr
# in: esi
# out: edi
# out->write: ecx (cached copy; need to keep in sync)
# out->length: edx
# out->size: edx
# temporaries: eax, ebx
# We can't allocate Look to a register because it gets written implicitly in
# get-char in each iteration of the loop. (Thereby demonstrating that it's
@ -255,10 +255,10 @@ $get-num:main:
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
# ecx = out->write
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
# edx = out->length
# edx = out->size
8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # copy *(edi+8) to edx
$get-num:loop:
# if (out->write >= out->length) error
# if (out->write >= out->size) error
39/compare 3/mod/direct 2/rm32/edx . . . 1/r32/ecx . . # compare edx with ecx
7d/jump-if-< $get-num:loop-stage2/disp8
# . error(ed, err, msg) # TODO: show full number

Binary file not shown.

View File

@ -1,9 +1,9 @@
# Null-terminated vs length-prefixed ascii strings.
# Null-terminated vs size-prefixed ascii strings.
#
# By default we create strings with a 4-byte length prefix rather than a null suffix.
# By default we create strings with a 4-byte size 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'.
# a null-terminated 'kernel string' with a size-prefixed 'SubX string'.
#
# To run:
# $ ./bootstrap translate init.linux apps/ex11.subx -o apps/ex11
@ -25,11 +25,11 @@ Entry: # run all tests
89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx
e8/call syscall_exit/disp32
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
# compare a null-terminated ascii string with a more idiomatic size-prefixed byte array
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
kernel-string-equal?: # s: null-terminated ascii string, benchmark: length-prefixed ascii string -> eax: boolean
kernel-string-equal?: # s: null-terminated ascii string, benchmark: size-prefixed ascii string -> eax: boolean
# pseudocode:
# n = benchmark->length
# n = benchmark->size
# s1 = s
# s2 = benchmark->data
# i = 0
@ -60,7 +60,7 @@ kernel-string-equal?: # s: null-terminated ascii string, benchmark: length-pref
57/push-edi
# s1/edi = s
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
# n/edx = benchmark->length
# n/edx = benchmark->size
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

Binary file not shown.

Binary file not shown.

BIN
apps/hex

Binary file not shown.

BIN
apps/mu

Binary file not shown.

View File

@ -380,7 +380,7 @@ Max-type-id:
Type-id: # (stream (address array byte))
0x1c/imm32/write
0/imm32/read
0x100/imm32/length
0x100/imm32/size
# data
"literal"/imm32 # 0
"int"/imm32 # 1
@ -2478,7 +2478,7 @@ test-convert-index-into-array-with-literal:
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-with-literal/5")
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-with-literal/6")
(check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-with-literal/7")
# 2 * 4 bytes/elem + 4 bytes for length = offset 12
# 2 * 4 bytes/elem + 4 bytes for size = offset 12
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/8")
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/9")
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/10")
@ -3163,7 +3163,7 @@ parse-mu: # in: (addr buffered-file)
57/push-edi
# var line/ecx: (stream byte 512)
81 5/subop/subtract %esp 0x200/imm32
68/push 0x200/imm32/length
68/push 0x200/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/<- %ecx 4/r32/esp
@ -3177,7 +3177,7 @@ parse-mu: # in: (addr buffered-file)
be/copy-to-esi _Program-types/imm32
# var vars/ebx: (stack (addr var) 256)
81 5/subop/subtract %esp 0x400/imm32
68/push 0x400/imm32/length
68/push 0x400/imm32/size
68/push 0/imm32/top
89/<- %ebx 4/r32/esp
{
@ -3486,7 +3486,7 @@ test-function-header-with-arg:
(zero-out %ecx *Function-size)
# var vars/ebx: (stack (addr var) 16)
81 5/subop/subtract %esp 0x10/imm32
68/push 0x10/imm32/length
68/push 0x10/imm32/size
68/push 0/imm32/top
89/<- %ebx 4/r32/esp
# convert
@ -3519,7 +3519,7 @@ test-function-header-with-multiple-args:
(zero-out %ecx *Function-size)
# var vars/ebx: (stack (addr var) 16)
81 5/subop/subtract %esp 0x10/imm32
68/push 0x10/imm32/length
68/push 0x10/imm32/size
68/push 0/imm32/top
89/<- %ebx 4/r32/esp
# convert
@ -3571,7 +3571,7 @@ test-function-with-multiple-args-and-outputs:
(zero-out %ecx *Function-size)
# var vars/ebx: (stack (addr var) 16)
81 5/subop/subtract %esp 0x10/imm32
68/push 0x10/imm32/length
68/push 0x10/imm32/size
68/push 0/imm32/top
89/<- %ebx 4/r32/esp
# convert
@ -4666,7 +4666,7 @@ parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn
57/push-edi
# var line/ecx: (stream byte 512)
81 5/subop/subtract %esp 0x200/imm32
68/push 0x200/imm32/length
68/push 0x200/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/<- %ecx 4/r32/esp
@ -4809,7 +4809,7 @@ new-block-name: # fn: (handle function) -> result/eax: (handle var)
# var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
8b/-> *(ebp+8) 0/r32/eax
8b/-> *eax 0/r32/eax # Function-name
8b/-> *eax 0/r32/eax # String-length
8b/-> *eax 0/r32/eax # String-size
05/add-to-eax 0xd/imm32 # 10 + 2 for '$:'
89/<- %ecx 0/r32/eax
# var name/edx: (stream byte n)
@ -5019,7 +5019,7 @@ test-parse-mu-var-def:
(write _test-input-stream "n: int\n") # caller has consumed the 'var'
# var vars/ecx: (stack (addr var) 4)
81 5/subop/subtract %esp 0x10/imm32
68/push 0x10/imm32/length
68/push 0x10/imm32/size
68/push 0/imm32/top
89/<- %ecx 4/r32/esp
(clear-stack %ecx)
@ -5049,7 +5049,7 @@ test-parse-mu-reg-var-def:
(write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var'
# var vars/ecx: (stack (addr var) 4)
81 5/subop/subtract %esp 0x10/imm32
68/push 0x10/imm32/length
68/push 0x10/imm32/size
68/push 0/imm32/top
89/<- %ecx 4/r32/esp
(clear-stack %ecx)
@ -5428,7 +5428,7 @@ lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -
8b/-> *(ebp+0xc) 6/r32/esi
# ebx = vars->top
8b/-> *esi 3/r32/ebx
# if (vars->top > vars->length) abort
# if (vars->top > vars->size) abort
3b/compare<- *(esi+4) 0/r32/eax
0f 8f/jump-if-> $lookup-var-helper:error1/disp32
# var min/edx: (addr handle var) = vars->data
@ -5548,7 +5548,7 @@ test-parse-mu-stmt:
(write _test-input-stream "increment n\n")
# var vars/ecx: (stack (addr var) 4)
81 5/subop/subtract %esp 0x10/imm32
68/push 0x10/imm32/length
68/push 0x10/imm32/size
68/push 0/imm32/top
89/<- %ecx 4/r32/esp
(clear-stack %ecx)
@ -5584,7 +5584,7 @@ test-parse-mu-stmt-with-comma:
(write _test-input-stream "copy-to n, 3\n")
# var vars/ecx: (stack (addr var) 4)
81 5/subop/subtract %esp 0x10/imm32
68/push 0x10/imm32/length
68/push 0x10/imm32/size
68/push 0/imm32/top
89/<- %ecx 4/r32/esp
(clear-stack %ecx)
@ -6141,7 +6141,7 @@ populate-mu-type: # in: (addr stream byte), t: (handle typeinfo)
8b/-> *(ebp+0xc) 7/r32/edi
# var line/ecx: (stream byte 512)
81 5/subop/subtract %esp 0x200/imm32
68/push 0x200/imm32/length
68/push 0x200/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/<- %ecx 4/r32/esp
@ -6685,7 +6685,7 @@ size-of-array: # a: (handle tree type-id) -> result/eax: int
# return array-size * size-of(elem-type)
(size-of-type-id %edx) # => eax
f7 4/subop/multiply-into-eax %ecx
05/add-to-eax 4/imm32 # for array length
05/add-to-eax 4/imm32 # for array size
$size-of-array:end:
# . restore registers
5a/pop-to-edx
@ -6822,7 +6822,7 @@ emit-subx-function: # out: (addr buffered-file), f: (handle function)
8b/-> *(ebp+0xc) 1/r32/ecx
# var vars/edx: (stack (addr var) 256)
81 5/subop/subtract %esp 0x400/imm32
68/push 0x400/imm32/length
68/push 0x400/imm32/size
68/push 0/imm32/top
89/<- %edx 4/r32/esp
#
@ -7223,7 +7223,7 @@ Reverse-branch: # (table string string)
# a table is a stream
0xa0/imm32/write
0/imm32/read
0xa0/imm32/length
0xa0/imm32/size
# data
"break-if-="/imm32 "0f 85/jump-if-!="/imm32
"loop-if-="/imm32 "0f 85/jump-if-!="/imm32
@ -7689,7 +7689,7 @@ emit-subx-var-def: # out: (addr buffered-file), stmt: (handle stmt)
(is-mu-array? *(ecx+4)) # Var-type => eax
3d/compare-eax-and 0/imm32/false
0f 84/jump-if-= break/disp32
# var array-size-without-length/edx: int = n-4
# var array-size-without-size/edx: int = n-4
81 5/subop/subtract %edx 4/imm32
(emit-indent *(ebp+8) *Curr-block-depth)
(write-buffered *(ebp+8) "(push-n-zero-bytes ")
@ -7732,7 +7732,7 @@ emit-subx-stmt: # out: (addr buffered-file), stmt: (handle stmt), primitives: (
# - some special-case primitives that don't actually use the 'primitives' data structure
# ecx = stmt
8b/-> *(ebp+0xc) 1/r32/ecx
# array length
# array size
{
# if (!string-equal?(stmt->operation, "length")) break
(string-equal? *(ecx+4) "length") # Stmt1-operation => eax

BIN
apps/pack

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -133,14 +133,14 @@ subx-survey: # infile: (addr buffered-file), out: (addr buffered-file)
56/push-esi
# var segments/ecx: (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 0xa0/imm32/size
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 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
# . size
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Max-labels/disp32 # push *Max-labels
# . read
68/push 0/imm32/read
@ -150,7 +150,7 @@ subx-survey: # infile: (addr buffered-file), out: (addr buffered-file)
# var in/esi: (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
# . size
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Input-size/disp32 # push *Input-size
# . read
68/push 0/imm32/read
@ -690,7 +690,7 @@ compute-offsets: # in: (addr stream byte), segments: (addr stream {string, segm
c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . compute-offsets:segment-offset/disp32 0/imm32 # copy to *compute-offsets:word-slice
# var line/ecx: (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 0x200/imm32/size
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
@ -1222,13 +1222,13 @@ test-compute-offsets:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# var segments/ecx: (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 0x20/imm32/size
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 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 0x20/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx
@ -1624,13 +1624,13 @@ test-compute-addresses:
# setup
# . var segments/ecx: (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 0xa0/imm32/size
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 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 0x2000/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx
@ -1793,13 +1793,13 @@ test-compute-addresses-large-segments:
# setup
# . var segments/ecx: (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 0xa0/imm32/size
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 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 0x2000/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx
@ -1989,7 +1989,7 @@ emit-segments: # in: (addr stream byte), out: (addr buffered-file), labels: (ad
57/push-edi
# var line/ecx: (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 0x200/imm32/size
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
@ -2156,8 +2156,8 @@ $emit-segments:check-for-segment-header:
3d/compare-eax-and 0/imm32/false
0f 85/jump-if-!= $emit-segments:line-loop/disp32
$emit-segments:2-character:
# if (length(word-slice) != 2) goto next check
# . eax = length(word-slice)
# if (size(word-slice) != 2) goto next check
# . eax = size(word-slice)
8b/copy 1/mod/*+disp8 2/rm32/edx . . . 0/r32/eax 4/disp8 . # copy *(edx+4) to eax
2b/subtract 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # subtract *edx from eax
# . if (eax != 2) goto next check
@ -2579,7 +2579,7 @@ test-emit-segments-global-variable:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# . var labels/edx: (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 0x2000/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx
@ -2789,7 +2789,7 @@ test-emit-segments-code-label:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# . var labels/edx: (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 0x2000/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx
@ -2974,7 +2974,7 @@ test-emit-segments-code-label-absolute:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# . var labels/edx: (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 0x2000/imm32/size
68/push 0/imm32/read
68/push 0/imm32/write
89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx
@ -3423,8 +3423,8 @@ stream-add4: # in: (addr stream byte), key: addr, val1: addr, val2: addr, val3:
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]
# . edx = in->length
# max/edx = &in->data[in->size]
# . edx = in->size
8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 8/disp8 . # copy *(esi+8) to edx
# . edx = esi+edx+12
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 2/index/edx . 2/r32/edx 0xc/disp8 . # copy esi+edx+12 to edx
@ -4609,7 +4609,7 @@ test-num-bytes-handles-imm32:
# some fields (the ones with labels capitalized) filled in.
# http://www.sco.com/developers/gabi/latest/ch4.eheader.html
Elf_header:
# - length
# - size
0x34/imm32
# - data
$e_ident:
@ -4647,7 +4647,7 @@ $e_shstrndx:
# Some fields need filling in each time.
# https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-83432/index.html
Elf_program_header_entry:
# - length
# - size
0x20/imm32
# - data
$p_type:

Binary file not shown.