You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
7.8 KiB
315 lines
7.8 KiB
# Some unsafe methods not intended to be used directly in SubX, only through |
|
# Mu after proper type-checking. |
|
|
|
== code |
|
|
|
stream-empty?: # s: (addr stream _) -> result/eax: boolean |
|
# . prologue |
|
55/push-ebp |
|
89/<- %ebp 4/r32/esp |
|
# . save registers |
|
51/push-ecx |
|
56/push-esi |
|
# result = false |
|
b8/copy-to-eax 0/imm32/false |
|
# esi = s |
|
8b/-> *(ebp+8) 6/r32/esi |
|
# return s->read >= s->write |
|
8b/-> *esi 1/r32/ecx |
|
39/compare-with *(esi+4) 1/r32/ecx |
|
0f 9d/set-if->= %al |
|
$stream-empty?:end: |
|
# . restore registers |
|
5e/pop-to-esi |
|
59/pop-to-ecx |
|
# . epilogue |
|
89/<- %esp 5/r32/ebp |
|
5d/pop-to-ebp |
|
c3/return |
|
|
|
stream-full?: # s: (addr stream _) -> result/eax: boolean |
|
# . prologue |
|
55/push-ebp |
|
89/<- %ebp 4/r32/esp |
|
# . save registers |
|
51/push-ecx |
|
56/push-esi |
|
# result = false |
|
b8/copy-to-eax 0/imm32/false |
|
# esi = s |
|
8b/-> *(ebp+8) 6/r32/esi |
|
# return s->write >= s->size |
|
8b/-> *(esi+8) 1/r32/ecx |
|
39/compare-with *esi 1/r32/ecx |
|
0f 9d/set-if->= %al |
|
$stream-full?:end: |
|
# . restore registers |
|
5e/pop-to-esi |
|
59/pop-to-ecx |
|
# . epilogue |
|
89/<- %esp 5/r32/ebp |
|
5d/pop-to-ebp |
|
c3/return |
|
|
|
write-to-stream: # s: (addr stream _), in: (addr byte), n: int |
|
# . prologue |
|
55/push-ebp |
|
89/<- %ebp 4/r32/esp |
|
# . save registers |
|
50/push-eax |
|
51/push-ecx |
|
52/push-edx |
|
53/push-ebx |
|
57/push-edi |
|
# edi = s |
|
8b/-> *(ebp+8) 7/r32/edi |
|
# var swrite/edx: int = s->write |
|
8b/-> *edi 2/r32/edx |
|
# if (swrite + n > s->size) abort |
|
8b/-> *(ebp+0x10) 1/r32/ecx |
|
01/add-to %ecx 2/r32/edx |
|
3b/compare 1/r32/ecx *(edi+8) |
|
0f 8f/jump-if-> $write-to-stream:abort/disp32 |
|
# var out/edx: (addr byte) = s->data + s->write |
|
8d/copy-address *(edi+edx+0xc) 2/r32/edx |
|
# var outend/ebx: (addr byte) = out + n |
|
8b/-> *(ebp+0x10) 3/r32/ebx |
|
8d/copy-address *(edx+ebx) 3/r32/ebx |
|
# eax = in |
|
8b/-> *(ebp+0xc) 0/r32/eax |
|
# var inend/ecx: (addr byte) = in + n |
|
8b/-> *(ebp+0x10) 1/r32/ecx |
|
8d/copy-address *(eax+ecx) 1/r32/ecx |
|
# |
|
(_append-4 %edx %ebx %eax %ecx) # => eax |
|
# s->write += n |
|
8b/-> *(ebp+0x10) 1/r32/ecx |
|
01/add-to *edi 1/r32/ecx |
|
$write-to-stream:end: |
|
# . restore registers |
|
5f/pop-to-edi |
|
5b/pop-to-ebx |
|
5a/pop-to-edx |
|
59/pop-to-ecx |
|
58/pop-to-eax |
|
# . epilogue |
|
89/<- %esp 5/r32/ebp |
|
5d/pop-to-ebp |
|
c3/return |
|
|
|
$write-to-stream:abort: |
|
(abort "write-to-stream: stream full") |
|
# never gets here |
|
|
|
read-from-stream: # s: (addr stream _), out: (addr byte), n: int |
|
# . prologue |
|
55/push-ebp |
|
89/<- %ebp 4/r32/esp |
|
# . save registers |
|
50/push-eax |
|
51/push-ecx |
|
52/push-edx |
|
53/push-ebx |
|
56/push-esi |
|
# esi = s |
|
8b/-> *(ebp+8) 6/r32/esi |
|
# var sread/edx: int = s->read |
|
8b/-> *(esi+4) 2/r32/edx |
|
# if (sread + n > s->write) abort |
|
8b/-> *(ebp+0x10) 1/r32/ecx |
|
01/add-to %ecx 2/r32/edx |
|
3b/compare 1/r32/ecx *esi |
|
0f 8f/jump-if-> $read-from-stream:abort/disp32 |
|
# var in/edx: (addr byte) = s->data + s->read |
|
8d/copy-address *(esi+edx+0xc) 2/r32/edx |
|
# var inend/ebx: (addr byte) = in + n |
|
8b/-> *(ebp+0x10) 3/r32/ebx |
|
8d/copy-address *(edx+ebx) 3/r32/ebx |
|
# eax = out |
|
8b/-> *(ebp+0xc) 0/r32/eax |
|
# var outend/ecx: (addr byte) = out + n |
|
8b/-> *(ebp+0x10) 1/r32/ecx |
|
8d/copy-address *(eax+ecx) 1/r32/ecx |
|
# |
|
(_append-4 %eax %ecx %edx %ebx) # => eax |
|
# s->read += n |
|
8b/-> *(ebp+0x10) 1/r32/ecx |
|
01/add-to *(esi+4) 1/r32/ecx |
|
$read-from-stream:end: |
|
# . restore registers |
|
5e/pop-to-esi |
|
5b/pop-to-ebx |
|
5a/pop-to-edx |
|
59/pop-to-ecx |
|
58/pop-to-eax |
|
# . epilogue |
|
89/<- %esp 5/r32/ebp |
|
5d/pop-to-ebp |
|
c3/return |
|
|
|
$read-from-stream:abort: |
|
(abort "read-from-stream: stream empty") |
|
# never gets here |
|
|
|
stream-first: # s: (addr stream byte) -> result/eax: byte |
|
# . prologue |
|
55/push-ebp |
|
89/<- %ebp 4/r32/esp |
|
# . save registers |
|
51/push-ecx |
|
56/push-esi |
|
# result = false |
|
b8/copy-to-eax 0/imm32 |
|
# esi = s |
|
8b/-> *(ebp+8) 6/r32/esi |
|
# var idx/ecx: int = s->read |
|
8b/-> *(esi+4) 1/r32/ecx |
|
# if idx >= s->write return 0 |
|
3b/compare-with 1/r32/ecx *esi |
|
7d/jump-if->= $stream-first:end/disp8 |
|
# result = s->data[idx] |
|
8a/byte-> *(esi+ecx+0xc) 0/r32/AL |
|
$stream-first:end: |
|
# . restore registers |
|
5e/pop-to-esi |
|
59/pop-to-ecx |
|
# . epilogue |
|
89/<- %esp 5/r32/ebp |
|
5d/pop-to-ebp |
|
c3/return |
|
|
|
stream-final: # s: (addr stream byte) -> result/eax: byte |
|
# . prologue |
|
55/push-ebp |
|
89/<- %ebp 4/r32/esp |
|
# . save registers |
|
51/push-ecx |
|
56/push-esi |
|
# result = false |
|
b8/copy-to-eax 0/imm32 |
|
# esi = s |
|
8b/-> *(ebp+8) 6/r32/esi |
|
# var max/ecx: int = s->write |
|
8b/-> *esi 1/r32/ecx |
|
# if s->read >= max return 0 |
|
39/compare-with *(esi+4) 1/r32/ecx |
|
7d/jump-if->= $stream-final:end/disp8 |
|
# var idx/ecx: int = max - 1 |
|
49/decrement-ecx |
|
# result = s->data[idx] |
|
8a/byte-> *(esi+ecx+0xc) 0/r32/AL |
|
$stream-final:end: |
|
# . restore registers |
|
5e/pop-to-esi |
|
59/pop-to-ecx |
|
# . epilogue |
|
89/<- %esp 5/r32/ebp |
|
5d/pop-to-ebp |
|
c3/return |
|
|
|
# compare all the data in two streams (ignoring the read pointer) |
|
streams-data-equal?: # a: (addr stream byte), b: (addr array byte) -> result/eax: boolean |
|
# pseudocode: |
|
# awrite = a->write |
|
# if (awrite != b->write) return false |
|
# i = 0 |
|
# curra = a->data |
|
# currb = b->data |
|
# while i < awrite |
|
# i1 = *curra |
|
# i2 = *currb |
|
# if (c1 != c2) return false |
|
# i+=4, curra+=4, currb+=4 |
|
# return true |
|
# |
|
# registers: |
|
# i: ecx |
|
# awrite: edx |
|
# curra: esi |
|
# currb: edi |
|
# i1: eax |
|
# i2: ebx |
|
# |
|
# . prologue |
|
55/push-ebp |
|
89/<- %ebp 4/r32/esp |
|
# . save registers |
|
51/push-ecx |
|
52/push-edx |
|
53/push-ebx |
|
56/push-esi |
|
57/push-edi |
|
# esi = a |
|
8b/-> *(ebp+8) 6/r32/esi |
|
# edi = b |
|
8b/-> *(ebp+0xc) 7/r32/edi |
|
# var awrite/edx: int = a->write |
|
8b/-> *esi 2/r32/edx |
|
$streams-data-equal?:sizes: |
|
# if (awrite != b->write) return false |
|
39/compare *edi 2/r32/edx |
|
75/jump-if-!= $streams-data-equal?:false/disp8 |
|
# var curra/esi: (addr byte) = a->data |
|
81 0/subop/add %esi 0xc/imm32 |
|
# var currb/edi: (addr byte) = b->data |
|
81 0/subop/add %edi 0xc/imm32 |
|
# var i/ecx: int = 0 |
|
31/xor-with %ecx 1/r32/ecx |
|
# var vala/eax: int |
|
31/xor-with %eax 0/r32/eax |
|
# var valb/ebx: int |
|
31/xor-with %ebx 3/r32/ebx |
|
$streams-data-equal?:loop: |
|
{ |
|
# if (i >= awrite) return true |
|
39/compare %ecx 2/r32/edx |
|
7d/jump-if->= $streams-data-equal?:true/disp8 |
|
# var vala/eax: int = *curra |
|
8a/byte-> *esi 0/r32/eax |
|
# var valb/ebx: int = *currb |
|
8a/byte-> *edi 3/r32/ebx |
|
# if (vala != valb) return false |
|
39/compare %eax 3/r32/ebx |
|
75/jump-if-!= $streams-data-equal?:false/disp8 |
|
# i++ |
|
41/increment-ecx |
|
# curra++ |
|
46/increment-esi |
|
# currb++ |
|
47/increment-edi |
|
eb/jump loop/disp8 |
|
} |
|
$streams-data-equal?:true: |
|
b8/copy-to-eax 1/imm32 |
|
eb/jump $streams-data-equal?:end/disp8 |
|
$streams-data-equal?:false: |
|
b8/copy-to-eax 0/imm32 |
|
$streams-data-equal?:end: |
|
# . restore registers |
|
5f/pop-to-edi |
|
5e/pop-to-esi |
|
5b/pop-to-ebx |
|
5a/pop-to-edx |
|
59/pop-to-ecx |
|
# . epilogue |
|
89/<- %esp 5/r32/ebp |
|
5d/pop-to-ebp |
|
c3/return |
|
|
|
# helper for tests |
|
check-streams-data-equal: # s: (addr stream _), expected: (addr array _), msg: (addr array byte) |
|
# . prologue |
|
55/push-ebp |
|
89/<- %ebp 4/r32/esp |
|
# . save registers |
|
50/push-eax |
|
# |
|
(streams-data-equal? *(ebp+8) *(ebp+0xc)) # => eax |
|
(check-ints-equal %eax 1 *(ebp+0x10)) |
|
$check-streams-data-equal:end: |
|
# . restore registers |
|
58/pop-to-eax |
|
# . epilogue |
|
89/<- %esp 5/r32/ebp |
|
5d/pop-to-ebp |
|
c3/return
|
|
|