From 8aeb85f04ee68b960a6d326aca1a17dec2f6d019 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 9 Dec 2019 01:26:58 -0800 Subject: 5806 --- html/060read.subx.html | 497 ++++++++++++++++++++++++------------------------- 1 file changed, 248 insertions(+), 249 deletions(-) (limited to 'html/060read.subx.html') diff --git a/html/060read.subx.html b/html/060read.subx.html index 886514a2..235389fa 100644 --- a/html/060read.subx.html +++ b/html/060read.subx.html @@ -106,7 +106,7 @@ if ('onhashchange' in window) { 45 # . op subop mod rm32 base index scale r32 46 # . 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 47 - 48 read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/eax + 48 read: # f : fd or (address stream byte), s : (address stream byte) -> num-bytes-read/eax : int 49 # . prologue 50 55/push-ebp 51 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -117,7 +117,7 @@ if ('onhashchange' in window) { 56 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 57 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 58 # . . call - 59 e8/call _read/disp32 + 59 e8/call _read/disp32 60 # . . discard args 61 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 62 # return @@ -252,253 +252,252 @@ if ('onhashchange' in window) { 191 5d/pop-to-ebp 192 c3/return 193 -194 -195 # idea: a clear-if-empty method on streams that clears only if f->read == f->write -196 # Unclear how I'd use it, though. Callers seem to need the check anyway. -197 # Maybe a better helper would be 'empty-stream?' -198 -199 _read: # fd : int, s : (address stream) -> num-bytes-read/eax -200 # . prologue -201 55/push-ebp -202 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -203 # . save registers -204 51/push-ecx -205 52/push-edx -206 53/push-ebx -207 56/push-esi -208 # esi = s -209 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi -210 # eax = s->write -211 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax -212 # edx = s->length -213 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 8/disp8 . # copy *(esi+8) to edx -214 # syscall(read, fd, &s->data[s->write], s->length - s->write) -215 # . . fd : ebx -216 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 3/r32/ebx 8/disp8 . # copy *(ebp+8) to ebx -217 # . . data : ecx = &s->data[s->write] -218 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 -219 # . . size : edx = s->length - s->write -220 29/subtract 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # subtract eax from edx -221 # . . syscall -222 b8/copy-to-eax 3/imm32/read -223 cd/syscall 0x80/imm8 -224 # add the result eax to s->write -225 01/add 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # add eax to *esi -226 $_read:end: -227 # . restore registers -228 5e/pop-to-esi -229 5b/pop-to-ebx -230 5a/pop-to-edx -231 59/pop-to-ecx -232 # . epilogue -233 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -234 5d/pop-to-ebp -235 c3/return -236 -237 # Two options: -238 # 1 (what we have above): -239 # ecx = s -240 # eax = s->write -241 # edx = s->length -242 # # syscall -243 # ecx = lea ecx+eax+12 -244 # edx = sub edx eax -245 # -246 # 2: -247 # ecx = s -248 # edx = s->length -249 # ecx = &s->data -250 # # syscall -251 # ecx = add ecx, s->write -252 # edx = sub edx, s->write -253 # -254 # Not much to choose between the two? Option 2 performs a duplicate load to -255 # use one less register, but doesn't increase the amount of spilling (ecx -256 # and edx must be used, and eax must be clobbered anyway). -257 -258 # - tests -259 -260 test-read-single: -261 # - write a single character into _test-stream, then read from it -262 # clear-stream(_test-stream) -263 # . . push args -264 68/push _test-stream/imm32 -265 # . . call -266 e8/call clear-stream/disp32 -267 # . . discard args -268 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -269 # clear-stream(_test-tmp-stream) -270 # . . push args -271 68/push _test-tmp-stream/imm32 -272 # . . call -273 e8/call clear-stream/disp32 -274 # . . discard args -275 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -276 # write(_test-stream, "Ab") -277 # . . push args -278 68/push "Ab"/imm32 -279 68/push _test-stream/imm32 -280 # . . call -281 e8/call write/disp32 -282 # . . discard args -283 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -284 # eax = read(_test-stream, _test-tmp-stream) -285 # . . push args -286 68/push _test-tmp-stream/imm32 -287 68/push _test-stream/imm32 -288 # . . call -289 e8/call read/disp32 -290 # . . discard args -291 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -292 # check-ints-equal(eax, 2, msg) -293 # . . push args -294 68/push "F - test-read-single: return value"/imm32 -295 68/push 2/imm32 -296 50/push-eax -297 # . . call -298 e8/call check-ints-equal/disp32 -299 # . . discard args -300 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -301 # check-stream-equal(_test-tmp-stream, "Ab", msg) -302 # . . push args -303 68/push "F - test-read-single"/imm32 -304 68/push "Ab"/imm32 -305 68/push _test-tmp-stream/imm32 -306 # . . call -307 e8/call check-stream-equal/disp32 -308 # . . discard args -309 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -310 # end -311 c3/return -312 -313 test-read-is-stateful: -314 # - make two consecutive reads, check that their results are appended -315 # clear-stream(_test-stream) -316 # . . push args -317 68/push _test-stream/imm32 -318 # . . call -319 e8/call clear-stream/disp32 -320 # . . discard args -321 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -322 # clear-stream(_test-tmp-stream) -323 # . . push args -324 68/push _test-tmp-stream/imm32 -325 # . . call -326 e8/call clear-stream/disp32 -327 # . . discard args -328 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -329 # write(_test-stream, "C") -330 # . . push args -331 68/push "C"/imm32 -332 68/push _test-stream/imm32 -333 # . . call -334 e8/call write/disp32 -335 # . . discard args -336 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -337 # read(_test-stream, _test-tmp-stream) -338 # . . push args -339 68/push _test-tmp-stream/imm32 -340 68/push _test-stream/imm32 -341 # . . call -342 e8/call read/disp32 -343 # . . discard args -344 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -345 # write(_test-stream, "D") -346 # . . push args -347 68/push "D"/imm32 -348 68/push _test-stream/imm32 -349 # . . call -350 e8/call write/disp32 -351 # . . discard args -352 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -353 # read(_test-stream, _test-tmp-stream) -354 # . . push args -355 68/push _test-tmp-stream/imm32 -356 68/push _test-stream/imm32 -357 # . . call -358 e8/call read/disp32 -359 # . . discard args -360 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -361 # check-stream-equal(_test-tmp-stream, "CD", msg) -362 # . . push args -363 68/push "F - test-read-is-stateful"/imm32 -364 68/push "CD"/imm32 -365 68/push _test-tmp-stream/imm32 -366 # . . call -367 e8/call check-stream-equal/disp32 -368 # . . discard args -369 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -370 # end -371 c3/return -372 -373 test-read-returns-0-on-end-of-file: -374 # - read after hitting end-of-file, check that result is 0 -375 # setup -376 # . clear-stream(_test-stream) -377 # . . push args -378 68/push _test-stream/imm32 -379 # . . call -380 e8/call clear-stream/disp32 -381 # . . discard args -382 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -383 # . clear-stream(_test-tmp-stream) -384 # . . push args -385 68/push _test-tmp-stream/imm32 -386 # . . call -387 e8/call clear-stream/disp32 -388 # . . discard args -389 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -390 # . write(_test-stream, "Ab") -391 # . . push args -392 68/push "Ab"/imm32 -393 68/push _test-stream/imm32 -394 # . . call -395 e8/call write/disp32 -396 # . . discard args -397 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -398 # first read gets to end-of-file -399 # . read(_test-stream, _test-tmp-stream) -400 # . . push args -401 68/push _test-tmp-stream/imm32 -402 68/push _test-stream/imm32 -403 # . . call -404 e8/call read/disp32 -405 # . . discard args -406 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -407 # second read -408 # . read(_test-stream, _test-tmp-stream) -409 # . . push args -410 68/push _test-tmp-stream/imm32 -411 68/push _test-stream/imm32 -412 # . . call -413 e8/call read/disp32 -414 # . . discard args -415 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -416 # check-ints-equal(eax, 0, msg) -417 # . . push args -418 68/push "F - test-read-returns-0-on-end-of-file"/imm32 -419 68/push 0/imm32 -420 50/push-eax -421 # . . call -422 e8/call check-ints-equal/disp32 -423 # . . discard args -424 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -425 # end -426 c3/return -427 -428 == data -429 -430 _test-tmp-stream: -431 # current write index -432 0/imm32 -433 # current read index -434 0/imm32 -435 # length -436 8/imm32 -437 # data -438 00 00 00 00 00 00 00 00 # 8 bytes -439 -440 # . . vim:nowrap:textwidth=0 +194 # idea: a clear-if-empty method on streams that clears only if f->read == f->write +195 # Unclear how I'd use it, though. Callers seem to need the check anyway. +196 # Maybe a better helper would be 'empty-stream?' +197 +198 _read: # fd : int, s : (address stream byte) -> num-bytes-read/eax : int +199 # . prologue +200 55/push-ebp +201 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +202 # . save registers +203 51/push-ecx +204 52/push-edx +205 53/push-ebx +206 56/push-esi +207 # esi = s +208 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi +209 # eax = s->write +210 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax +211 # edx = s->length +212 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 8/disp8 . # copy *(esi+8) to edx +213 # syscall(read, fd, &s->data[s->write], s->length - s->write) +214 # . . fd : ebx +215 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 3/r32/ebx 8/disp8 . # copy *(ebp+8) to ebx +216 # . . data : ecx = &s->data[s->write] +217 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 +218 # . . size : edx = s->length - s->write +219 29/subtract 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # subtract eax from edx +220 # . . syscall +221 b8/copy-to-eax 3/imm32/read +222 cd/syscall 0x80/imm8 +223 # add the result eax to s->write +224 01/add 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # add eax to *esi +225 $_read:end: +226 # . restore registers +227 5e/pop-to-esi +228 5b/pop-to-ebx +229 5a/pop-to-edx +230 59/pop-to-ecx +231 # . epilogue +232 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +233 5d/pop-to-ebp +234 c3/return +235 +236 # Two options: +237 # 1 (what we have above): +238 # ecx = s +239 # eax = s->write +240 # edx = s->length +241 # # syscall +242 # ecx = lea ecx+eax+12 +243 # edx = sub edx eax +244 # +245 # 2: +246 # ecx = s +247 # edx = s->length +248 # ecx = &s->data +249 # # syscall +250 # ecx = add ecx, s->write +251 # edx = sub edx, s->write +252 # +253 # Not much to choose between the two? Option 2 performs a duplicate load to +254 # use one less register, but doesn't increase the amount of spilling (ecx +255 # and edx must be used, and eax must be clobbered anyway). +256 +257 # - tests +258 +259 test-read-single: +260 # - write a single character into _test-stream, then read from it +261 # clear-stream(_test-stream) +262 # . . push args +263 68/push _test-stream/imm32 +264 # . . call +265 e8/call clear-stream/disp32 +266 # . . discard args +267 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +268 # clear-stream(_test-tmp-stream) +269 # . . push args +270 68/push _test-tmp-stream/imm32 +271 # . . call +272 e8/call clear-stream/disp32 +273 # . . discard args +274 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +275 # write(_test-stream, "Ab") +276 # . . push args +277 68/push "Ab"/imm32 +278 68/push _test-stream/imm32 +279 # . . call +280 e8/call write/disp32 +281 # . . discard args +282 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +283 # eax = read(_test-stream, _test-tmp-stream) +284 # . . push args +285 68/push _test-tmp-stream/imm32 +286 68/push _test-stream/imm32 +287 # . . call +288 e8/call read/disp32 +289 # . . discard args +290 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +291 # check-ints-equal(eax, 2, msg) +292 # . . push args +293 68/push "F - test-read-single: return value"/imm32 +294 68/push 2/imm32 +295 50/push-eax +296 # . . call +297 e8/call check-ints-equal/disp32 +298 # . . discard args +299 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +300 # check-stream-equal(_test-tmp-stream, "Ab", msg) +301 # . . push args +302 68/push "F - test-read-single"/imm32 +303 68/push "Ab"/imm32 +304 68/push _test-tmp-stream/imm32 +305 # . . call +306 e8/call check-stream-equal/disp32 +307 # . . discard args +308 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +309 # end +310 c3/return +311 +312 test-read-is-stateful: +313 # - make two consecutive reads, check that their results are appended +314 # clear-stream(_test-stream) +315 # . . push args +316 68/push _test-stream/imm32 +317 # . . call +318 e8/call clear-stream/disp32 +319 # . . discard args +320 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +321 # clear-stream(_test-tmp-stream) +322 # . . push args +323 68/push _test-tmp-stream/imm32 +324 # . . call +325 e8/call clear-stream/disp32 +326 # . . discard args +327 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +328 # write(_test-stream, "C") +329 # . . push args +330 68/push "C"/imm32 +331 68/push _test-stream/imm32 +332 # . . call +333 e8/call write/disp32 +334 # . . discard args +335 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +336 # read(_test-stream, _test-tmp-stream) +337 # . . push args +338 68/push _test-tmp-stream/imm32 +339 68/push _test-stream/imm32 +340 # . . call +341 e8/call read/disp32 +342 # . . discard args +343 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +344 # write(_test-stream, "D") +345 # . . push args +346 68/push "D"/imm32 +347 68/push _test-stream/imm32 +348 # . . call +349 e8/call write/disp32 +350 # . . discard args +351 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +352 # read(_test-stream, _test-tmp-stream) +353 # . . push args +354 68/push _test-tmp-stream/imm32 +355 68/push _test-stream/imm32 +356 # . . call +357 e8/call read/disp32 +358 # . . discard args +359 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +360 # check-stream-equal(_test-tmp-stream, "CD", msg) +361 # . . push args +362 68/push "F - test-read-is-stateful"/imm32 +363 68/push "CD"/imm32 +364 68/push _test-tmp-stream/imm32 +365 # . . call +366 e8/call check-stream-equal/disp32 +367 # . . discard args +368 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +369 # end +370 c3/return +371 +372 test-read-returns-0-on-end-of-file: +373 # - read after hitting end-of-file, check that result is 0 +374 # setup +375 # . clear-stream(_test-stream) +376 # . . push args +377 68/push _test-stream/imm32 +378 # . . call +379 e8/call clear-stream/disp32 +380 # . . discard args +381 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +382 # . clear-stream(_test-tmp-stream) +383 # . . push args +384 68/push _test-tmp-stream/imm32 +385 # . . call +386 e8/call clear-stream/disp32 +387 # . . discard args +388 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +389 # . write(_test-stream, "Ab") +390 # . . push args +391 68/push "Ab"/imm32 +392 68/push _test-stream/imm32 +393 # . . call +394 e8/call write/disp32 +395 # . . discard args +396 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +397 # first read gets to end-of-file +398 # . read(_test-stream, _test-tmp-stream) +399 # . . push args +400 68/push _test-tmp-stream/imm32 +401 68/push _test-stream/imm32 +402 # . . call +403 e8/call read/disp32 +404 # . . discard args +405 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +406 # second read +407 # . read(_test-stream, _test-tmp-stream) +408 # . . push args +409 68/push _test-tmp-stream/imm32 +410 68/push _test-stream/imm32 +411 # . . call +412 e8/call read/disp32 +413 # . . discard args +414 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +415 # check-ints-equal(eax, 0, msg) +416 # . . push args +417 68/push "F - test-read-returns-0-on-end-of-file"/imm32 +418 68/push 0/imm32 +419 50/push-eax +420 # . . call +421 e8/call check-ints-equal/disp32 +422 # . . discard args +423 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +424 # end +425 c3/return +426 +427 == data +428 +429 _test-tmp-stream: # (ref stream byte) +430 # current write index +431 0/imm32 +432 # current read index +433 0/imm32 +434 # length +435 8/imm32 +436 # data +437 00 00 00 00 00 00 00 00 # 8 bytes +438 +439 # . . vim:nowrap:textwidth=0 -- cgit 1.4.1-2-gfad0