# 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