# Helper to allocate a stream on the heap. == code # instruction effective address register displacement immediate # . op subop mod rm32 base index scale r32 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes new-stream: # ad: (addr allocation-descriptor), length: int, elemsize: int, out: (addr handle stream _) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 50/push-eax 52/push-edx # var size/edx: int = elemsize*length (clobbering eax) # . eax = elemsize 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax # . eax *= length 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx f7 4/subop/multiply 1/mod/*+disp8 5/rm32/ebp . . 0xc/disp8 . # multiply *(ebp+12) into edx:eax # . if overflow abort 81 7/subop/compare 3/mod/direct 2/rm32/edx . . . . . 0/imm32 # compare edx 75/jump-if-!= $new-stream:abort/disp8 # . edx = elemsize*length 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx # var n/eax: int = size + 12 (for read, write and size) 05/add-to-eax 0xc/imm32 # allocate(ad, n, out) # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20) 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) # . . call e8/call allocate/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # eax = out->payload 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x14/disp8 . # copy *(ebp+20) to eax 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax # skip payload->allocid 05/add-to-eax 4/imm32 # eax->size = size 89/copy 1/mod/*+disp8 0/rm32/eax . . . 2/r32/edx 8/disp8 . # copy edx to *(eax+8) # clear-stream(eax) # . . push args 50/push-eax # . . call e8/call clear-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp $new-stream:end: # . restore registers 5a/pop-to-edx 58/pop-to-eax # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return $new-stream:abort: (abort "new-stream: size too large") # never gets here test-new-stream: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # var ad/ecx: allocation-descriptor containing 16 bytes # . var end/ecx: (addr byte) 89/<- %ecx 4/r32/esp # . var start/edx: (addr byte) = end - 32 81 5/subop/subtract %esp 0x20/imm32 89/<- %edx 4/r32/esp # . ad = {start, end} 51/push-ecx 52/push-edx 89/copy 3/mod/direct 1/r