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:
parent
f730f2f2c7
commit
bfcc0f858a
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
22
060read.subx
22
060read.subx
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
BIN
apps/assort
BIN
apps/assort
Binary file not shown.
BIN
apps/braces
BIN
apps/braces
Binary file not shown.
BIN
apps/calls
BIN
apps/calls
Binary file not shown.
BIN
apps/crenshaw2-1
BIN
apps/crenshaw2-1
Binary file not shown.
|
@ -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.
|
@ -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
|
||||
|
|
BIN
apps/dquotes
BIN
apps/dquotes
Binary file not shown.
|
@ -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
|
||||
|
|
BIN
apps/factorial
BIN
apps/factorial
Binary file not shown.
BIN
apps/handle
BIN
apps/handle
Binary file not shown.
40
apps/mu.subx
40
apps/mu.subx
|
@ -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/sigils
BIN
apps/sigils
Binary file not shown.
BIN
apps/survey
BIN
apps/survey
Binary file not shown.
|
@ -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:
|
||||
|
|
BIN
apps/tests
BIN
apps/tests
Binary file not shown.
Loading…
Reference in New Issue