1 # Read a series of segments from stdin and concatenate segments with the same 2 # name on stdout. 3 # 4 # Segments are emitted in order of first encounter. 5 # 6 # Drop lines that are all comments. They could get misleading after assortment 7 # because we don't know if they refer to the line above or the line below. 8 # 9 # To run (from the subx/ directory): 10 # $ ./subx translate *.subx apps/assort.subx -o apps/assort 11 # $ cat x 12 # == code 13 # abc 14 # == code 15 # def 16 # $ cat x |./subx run apps/assort 17 # == code 18 # abc 19 # def 20 21 == code 22 # instruction effective address register displacement immediate 23 # . op subop mod rm32 base index scale r32 24 # . 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 25 26 Entry: # run tests if necessary, convert stdin if not 27 28 # for debugging: run a single test 29 #? e8/call test-convert/disp32 30 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX 31 #? eb/jump $main:end/disp8 32 33 # . prolog 34 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 35 # - if argc > 1 and argv[1] == "test", then return run_tests() 36 # . argc > 1 37 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 38 7e/jump-if-lesser-or-equal $run-main/disp8 39 # . argv[1] == "test" 40 # . . push args 41 68/push "test"/imm32 42 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 43 # . . call 44 e8/call kernel-string-equal?/disp32 45 # . . discard args 46 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 47 # . check result 48 3d/compare-EAX-and 1/imm32 49 75/jump-if-not-equal $run-main/disp8 50 # . run-tests() 51 e8/call run-tests/disp32 52 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX 53 eb/jump $main:end/disp8 54 $run-main: 55 # - otherwise convert stdin 56 # var ed/EAX : exit-descriptor 57 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 58 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX 59 # configure ed to really exit() 60 # . ed->target = 0 61 c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX 62 # return convert(Stdin, 1/stdout, 2/stderr, ed) 63 # . . push args 64 50/push-EAX/ed 65 68/push Stderr/imm32 66 68/push Stdout/imm32 67 68/push Stdin/imm32 68 # . . call 69 e8/call convert/disp32 70 # . . discard args 71 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 72 # . syscall(exit, 0) 73 bb/copy-to-EBX 0/imm32 74 $main:end: 75 b8/copy-to-EAX 1/imm32/exit 76 cd/syscall 0x80/imm8 77 78 # data structure: 79 # row: pair of (address array byte) and (address stream byte) 80 # table: (address stream row) 81 82 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> 83 # pseudocode: 84 # var table : (address stream) = new-stream(10 rows, 8 bytes each) 85 # read-segments(in, table) 86 # write-segments(out, table) 87 # 88 # . prolog 89 55/push-EBP 90 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 91 # . save registers 92 51/push-ECX 93 # var table/ECX : (address stream byte) = stream(10 * 8) 94 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x50/imm32 # subtract from ESP 95 68/push 0x50/imm32/length 96 68/push 0/imm32/read 97 68/push 0/imm32/write 98 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 99 # clear-stream(table) 100 # . . push args 101 51/push-ECX 102 # . . call 103 e8/call clear-stream/disp32 104 # . . discard args 105 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 106 $convert:read: 107 # read-segments(in, table) 108 # . . push args 109 51/push-ECX 110 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 111 # . . call 112 e8/call read-segments/disp32 113 # . . discard args 114 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 115 $convert:write: 116 # write-segments(out, table) 117 # . . push args 118 51/push-ECX 119 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 120 # . . call 121 e8/call write-segments/disp32 122 # . . discard args 123 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 124 $convert:end: 125 # . reclaim locals 126 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x5c/imm32 # add to ESP 127 # . restore registers 128 59/pop-to-ECX 129 # . epilog 130 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 131 5d/pop-to-EBP 132 c3/return 133 134 #? test-convert: 135 #? # . prolog 136 #? 55/push-EBP 137 #? 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 138 #? # setup 139 #? # . clear-stream(_test-input-stream) 140 #? # . . push args 141 #? 68/push _test-input-stream/imm32 142 #? # . . call 143 #? e8/call clear-stream/disp32 144 #? # . . discard args 145 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 146 #? # . clear-stream(_test-input-buffered-file+4) 147 #? # . . push args 148 #? b8/copy-to-EAX _test-input-buffered-file/imm32 149 #? 05/add-to-EAX 4/imm32 150 #? 50/push-EAX 151 #? # . . call 152 #? e8/call clear-stream/disp32 153 #? # . . discard args 154 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 155 #? # . clear-stream(_test-output-stream) 156 #? # . . push args 157 #? 68/push _test-output-stream/imm32 158 #? # . . call 159 #? e8/call clear-stream/disp32 160 #? # . . discard args 161 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 162 #? # . clear-stream(_test-output-buffered-file+4) 163 #? # . . push args 164 #? b8/copy-to-EAX _test-output-buffered-file/imm32 165 #? 05/add-to-EAX 4/imm32 166 #? 50/push-EAX 167 #? # . . call 168 #? e8/call clear-stream/disp32 169 #? # . . discard args 170 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 171 #? # initialize input (meta comments in parens) 172 #? # # comment 1 173 #? # # comment 2 indented 174 #? # == code (new segment) 175 #? # # comment 3 inside a segment 176 #? # 1 177 #? # (empty line) 178 #? # 2 3 # comment 4 inline with other contents 179 #? # == data (new segment) 180 #? # 4 5/imm32 181 #? # == code (existing segment but non-contiguous with previous iteration) 182 #? # 6 7 183 #? # 8 9 (multiple lines) 184 #? # == code (existing segment contiguous with previous iteration) 185 #? # 10 11 186 #? # . write(_test-input-stream, "# comment 1") 187 #? # . . push args 188 #? 68/push "# comment 1"/imm32 189 #? 68/push _test-input-stream/imm32 190 #? # . . call 191 #? e8/call write/disp32 192 #? # . . discard args 193 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 194 #? # . write(_test-input-stream, "\n") 195 #? # . . push args 196 #? 68/push Newline/imm32 197 #? 68/push _test-input-stream/imm32 198 #? # . . call 199 #? e8/call write/disp32 200 #? # . . discard args 201 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 202 #? # . write(_test-input-stream, " # comment 2 indented") 203 #? # . . push args 204 #? 68/push " # comment 2 indented"/imm32 205 #? 68/push _test-input-stream/imm32 206 #? # . . call 207 #? e8/call write/disp32 208 #? # . . discard args 209 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 210 #? # . write(_test-input-stream, "\n") 211 #? # . . push args 212 #? 68/push Newline/imm32 213 #? 68/push _test-input-stream/imm32 214 #? # . . call 215 #? e8/call write/disp32 216 #? # . . discard args 217 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 218 #? # . write(_test-input-stream, "== code") 219 #? # . . push args 220 #? 68/push "== code"/imm32 221 #? 68/push _test-input-stream/imm32 222 #? # . . call 223 #? e8/call write/disp32 224 #? # . . discard args 225 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 226 #? # . write(_test-input-stream, "\n") 227 #? # . . push args 228 #? 68/push Newline/imm32 229 #? 68/push _test-input-stream/imm32 230 #? # . . call 231 #? e8/call write/disp32 232 #? # . . discard args 233 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 234 #? # . write(_test-input-stream, "# comment 3 inside a segment") 235 #? # . . push args 236 #? 68/push "# comment 3 inside a segment"/imm32 237 #? 68/push _test-input-stream/imm32 238 #? # . . call 239 #? e8/call write/disp32 240 #? # . . discard args 241 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 242 #? # . write(_test-input-stream, "\n") 243 #? # . . push args 244 #? 68/push Newline/imm32 245 #? 68/push _test-input-stream/imm32 246 #? # . . call 247 #? e8/call write/disp32 248 #? # . . discard args 249 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 250 #? # . write(_test-input-stream, "1") 251 #? # . . push args 252 #? 68/push "1"/imm32 253 #? 68/push _test-input-stream/imm32 254 #? # . . call 255 #? e8/call write/disp32 256 #? # . . discard args 257 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 258 #? # . write(_test-input-stream, "\n") 259 #? # . . push args 260 #? 68/push Newline/imm32 261 #? 68/push _test-input-stream/imm32 262 #? # . . call 263 #? e8/call write/disp32 264 #? # . . discard args 265 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 266 #? # . write(_test-input-stream, "\n") # empty line 267 #? # . . push args 268 #? 68/push Newline/imm32 269 #? 68/push _test-input-stream/imm32 270 #? # . . call 271 #? e8/call write/disp32 272 #? # . . discard args 273 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 274 #? # . write(_test-input-stream, "2 3 # comment 4 inline with other comments") 275 #? # . . push args 276 #? 68/push "2 3 # comment 4 inline with other comments"/imm32 277 #? 68/push _test-input-stream/imm32 278 #? # . . call 279 #? e8/call write/disp32 280 #? # . . discard args 281 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 282 #? # . write(_test-input-stream, "\n") 283 #? # . . push args 284 #? 68/push Newline/imm32 285 #? 68/push _test-input-stream/imm32 286 #? # . . call 287 #? e8/call write/disp32 288 #? # . . discard args 289 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 290 #? # . write(_test-input-stream, "== data") 291 #? # . . push args 292 #? 68/push "== data"/imm32 293 #? 68/push _test-input-stream/imm32 294 #? # . . call 295 #? e8/call write/disp32 296 #? # . . discard args 297 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 298 #? # . write(_test-input-stream, "\n") 299 #? # . . push args 300 #? 68/push Newline/imm32 301 #? 68/push _test-input-stream/imm32 302 #? # . . call 303 #? e8/call write/disp32 304 #? # . . discard args 305 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 306 #? # . write(_test-input-stream, "4 5/imm32") 307 #? # . . push args 308 #? 68/push "4 5/imm32"/imm32 309 #? 68/push _test-input-stream/imm32 310 #? # . . call 311 #? e8/call write/disp32 312 #? # . . discard args 313 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 314 #? # . write(_test-input-stream, "\n") 315 #? # . . push args 316 #? 68/push Newline/imm32 317 #? 68/push _test-input-stream/imm32 318 #? # . . call 319 #? e8/call write/disp32 320 #? # . . discard args 321 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 322 #? # . write(_test-input-stream, "== code") 323 #? # . . push args 324 #? 68/push "== code"/imm32 325 #? 68/push _test-input-stream/imm32 326 #? # . . call 327 #? e8/call write/disp32 328 #? # . . discard args 329 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 330 #? # . write(_test-input-stream, "\n") 331 #? # . . push args 332 #? 68/push Newline/imm32 333 #? 68/push _test-input-stream/imm32 334 #? # . . call 335 #? e8/call write/disp32 336 #? # . . discard args 337 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 338 #? # . write(_test-input-stream, "6 7") 339 #? # . . push args 340 #? 68/push "6 7"/imm32 341 #? 68/push _test-input-stream/imm32 342 #? # . . call 343 #? e8/call write/disp32 344 #? # . . discard args 345 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 346 #? # . write(_test-input-stream, "\n") 347 #? # . . push args 348 #? 68/push Newline/imm32 349 #? 68/push _test-input-stream/imm32 350 #? # . . call 351 #? e8/call write/disp32 352 #? # . . discard args 353 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 354 #? # . write(_test-input-stream, "8 9") 355 #? # . . push args 356 #? 68/push "6 7"/imm32 357 #? 68/push _test-input-stream/imm32 358 #? # . . call 359 #? e8/call write/disp32 360 #? # . . discard args 361 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 362 #? # . write(_test-input-stream, "\n") 363 #? # . . push args 364 #? 68/push Newline/imm32 365 #? 68/push _test-input-stream/imm32 366 #? # . . call 367 #? e8/call write/disp32 368 #? # . . discard args 369 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 370 #? # . write(_test-input-stream, "== code") 371 #? # . . push args 372 #? 68/push "== code"/imm32 373 #? 68/push _test-input-stream/imm32 374 #? # . . call 375 #? e8/call write/disp32 376 #? # . . discard args 377 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 378 #? # . write(_test-input-stream, "\n") 379 #? # . . push args 380 #? 68/push Newline/imm32 381 #? 68/push _test-input-stream/imm32 382 #? # . . call 383 #? e8/call write/disp32 384 #? # . . discard args 385 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 386 #? # . write(_test-input-stream, "10 11") 387 #? # . . push args 388 #? 68/push "10 11"/imm32 389 #? 68/push _test-input-stream/imm32 390 #? # . . call 391 #? e8/call write/disp32 392 #? # . . discard args 393 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 394 #? # . write(_test-input-stream, "\n") 395 #? # . . push args 396 #? 68/push Newline/imm32 397 #? 68/push _test-input-stream/imm32 398 #? # . . call 399 #? e8/call write/disp32 400 #? # . . discard args 401 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 402 #? # convert(_test-input-buffered-file, _test-output-buffered-file) 403 #? # . . push args 404 #? 68/push _test-output-buffered-file/imm32 405 #? 68/push _test-input-buffered-file/imm32 406 #? # . . call 407 #? e8/call convert/disp32 408 #? # . . discard args 409 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 410 #? # check output 411 #? # == code 412 #? # 1 413 #? # 2 3 # comment 4 inline with other contents 414 #? # 6 7 415 #? # 8 9 416 #? # 10 11 417 #? # == data 418 #? # 4 5/imm32 419 +-- 34 lines: #? #? # debug print ------------------------------------------------------------------------------------------------------------------------ 453 #? # . flush(_test-output-buffered-file) 454 #? # . . push args 455 #? 68/push _test-output-buffered-file/imm32 456 #? # . . call 457 #? e8/call flush/disp32 458 #? # . . discard args 459 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 460 #? # . check-next-stream-line-equal(_test-output-stream, "== code", msg) 461 #? # . . push args 462 #? 68/push "F - test-convert-code-and-data-segments/0"/imm32 463 #? 68/push "== code"/imm32 464 #? 68/push _test-output-stream/imm32 465 #? # . . call 466 #? e8/call check-next-stream-line-equal/disp32 467 #? # . . discard args 468 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 469 #? # . check-next-stream-line-equal(_test-output-stream, "1", msg) 470 #? # . . push args 471 #? 68/push "F - test-convert-code-and-data-segments/1"/imm32 472 #? 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 473 #? 68/push _test-output-stream/imm32 474 #? # . . call 475 #? e8/call check-next-stream-line-equal/disp32 476 #? # . . discard args 477 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 478 #? # . check-next-stream-line-equal(_test-output-stream, "2 3 # comment 4 inline with other contents", msg) 479 #? # . . push args 480 #? 68/push "F - test-convert-code-and-data-segments/2"/imm32 481 #? 68/push "2 3 # comment 4 inline with other contents"/imm32 482 #? 68/push _test-output-stream/imm32 483 #? # . . call 484 #? e8/call check-next-stream-line-equal/disp32 485 #? # . . discard args 486 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 487 #? # . check-next-stream-line-equal(_test-output-stream, "6 7", msg) 488 #? # . . push args 489 #? 68/push "F - test-convert-code-and-data-segments/3"/imm32 490 #? 68/push "6 7"/imm32 491 #? 68/push _test-output-stream/imm32 492 #? # . . call 493 #? e8/call check-next-stream-line-equal/disp32 494 #? # . . discard args 495 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 496 #? # . check-next-stream-line-equal(_test-output-stream, "8 9", msg) 497 #? # . . push args 498 #? 68/push "F - test-convert-code-and-data-segments/4"/imm32 499 #? 68/push "8 9"/imm32 500 #? 68/push _test-output-stream/imm32 501 #? # . . call 502 #? e8/call check-next-stream-line-equal/disp32 503 #? # . . discard args 504 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 505 #? # . check-next-stream-line-equal(_test-output-stream, "10 11", msg) 506 #? # . . push args 507 #? 68/push "F - test-convert-code-and-data-segments/5"/imm32 508 #? 68/push "10 11"/imm32 509 #? 68/push _test-output-stream/imm32 510 #? # . . call 511 #? e8/call check-next-stream-line-equal/disp32 512 #? # . . discard args 513 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 514 #? # . check-next-stream-line-equal(_test-output-stream, "== data", msg) 515 #? # . . push args 516 #? 68/push "F - test-convert-code-and-data-segments/6"/imm32 517 #? 68/push "== data"/imm32 518 #? 68/push _test-output-stream/imm32 519 #? # . . call 520 #? e8/call check-next-stream-line-equal/disp32 521 #? # . . discard args 522 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 523 #? # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32", msg) 524 #? # . . push args 525 #? 68/push "F - test-convert-code-and-data-segments/4"/imm32 526 #? 68/push "4 5/imm32"/imm32 527 #? 68/push _test-output-stream/imm32 528 #? # . . call 529 #? e8/call check-next-stream-line-equal/disp32 530 #? # . . discard args 531 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 532 #? # . epilog 533 #? 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 534 #? 5d/pop-to-EBP 535 #? c3/return 536 537 read-segments: # in : (address buffered-file), table : (address stream row) 538 # pseudocode: 539 # var curr-segment = null 540 # var line = new-stream(512, 1) 541 # while true 542 # clear-stream(line) 543 # read-line(in, line) 544 # if (line->write == 0) break # end of file 545 # var word-slice = next-word(line) 546 # if slice-empty?(word-slice) # whitespace 547 # continue 548 # if slice-starts-with?(word-slice, "#") # comment 549 # continue 550 # if (slice-equal?(word-slice, "==")) 551 # var segment-name = next-word(line) 552 # curr-segment = get-or-insert-segment(table, segment-name, N) 553 # else 554 # write-stream-data(curr-segment, line) 555 # 556 # . prolog 557 55/push-EBP 558 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 559 # . save registers 560 51/push-ECX 561 # var line/ECX : (address stream byte) = stream(512) 562 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP 563 68/push 0x200/imm32/length 564 68/push 0/imm32/read 565 68/push 0/imm32/write 566 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 567 # var word-slice/EDX = {0, 0} 568 68/push 0/imm32/end 569 68/push 0/imm32/curr 570 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX 571 # var curr-segment/EBX = null 572 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX 573 $read-segments:loop: 574 # clear-stream(line) 575 # . . push args 576 51/push-ECX 577 # . . call 578 e8/call clear-stream/disp32 579 # . . discard args 580 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 581 # read-line(in, line) 582 # . . push args 583 51/push-ECX 584 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 585 # . . call 586 e8/call read-line/disp32 587 # . . discard args 588 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 589 $read-segments:check0: 590 # if (line->write == 0) break 591 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX 592 0f 84/jump-if-equal $read-segments:break/disp32 593 +-- 34 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- 627 # next-word(line, word-slice) 628 # . . push args 629 52/push-EDX 630 51/push-ECX 631 # . . call 632 e8/call next-word/disp32 633 # . . discard args 634 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 635 $read-segments:check1: 636 # if (slice-empty?(word-slice)) continue 637 # . EAX = slice-empty?(word-slice) 638 # . . push args 639 52/push-EDX 640 # . . call 641 e8/call slice-empty?/disp32 642 # . . discard args 643 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 644 # . if (EAX != 0) continue 645 3d/compare-EAX-and 0/imm32 646 0f 85/jump-if-not-equal $read-segments:loop/disp32 647 $read-segments:check-for-comment: 648 # if (slice-starts-with?(word-slice, "#")) 649 # . start/EDX = word-slice->start 650 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX 651 # . c/EAX = *start 652 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 653 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL 654 # . if (EAX == '#') continue 655 3d/compare-EAX-and 0x23/imm32/hash 656 74/jump-if-equal $read-segments:loop/disp8 657 $read-segments:check-for-segment-header: 658 +-- 50 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- 708 # if (slice-equal?(word-slice, "==")) 709 # segment-name = next-word(line) 710 # curr-segment = get-or-insert(table, segment-name) 711 # . EAX = slice-equal?(word-slice, "==") 712 # . . push args 713 68/push "=="/imm32 714 52/push-EDX 715 # . . call 716 e8/call slice-equal?/disp32 717 # . . discard args 718 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 719 # . if (EAX == 0) goto check3 720 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX 721 0f 84/jump-if-equal $read-segments:regular-line/disp32 722 # . next-word(line, segment-name) 723 # . . push args 724 52/push-EDX 725 51/push-ECX 726 # . . call 727 e8/call next-word/disp32 728 # . . discard args 729 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 730 +-- 50 lines: #? # dump segment name --------------------------------------------------------------------------------------------------------------------- 780 # . EAX = get-or-insert-segment(table, segment-name, N) 781 # . . push args 782 68/push 0x1000/imm32/segment-size/4KB 783 52/push-EDX 784 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 785 # . . call 786 e8/call get-or-insert-segment/disp32 787 # . . discard args 788 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 789 # . curr-segment = EAX 790 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX 791 # . continue 792 e9/jump $read-segments:loop/disp32 793 $read-segments:regular-line: 794 # write-stream-data(curr-segment, line) 795 # . . push args 796 51/push-ECX 797 53/push-EBX 798 # . . call 799 e8/call write-stream-data/disp32 800 # . . discard args 801 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 802 # loop 803 e9/jump $read-segments:loop/disp32 804 $read-segments:break: 805 $read-segments:end: 806 # . reclaim locals 807 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP 808 # . restore registers 809 59/pop-to-ECX 810 # . epilog 811 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 812 5d/pop-to-EBP 813 c3/return 814 815 write-segments: # out : (address buffered-file), table : (address stream row) 816 # pseudocode: 817 # name, stream = table[0] 818 # var i = 0 819 # while i < table.length 820 # name = table[i].name 821 # if (name == null) break 822 # write-buffered(out, "== ") 823 # write-buffered(out, name) 824 # write-buffered(out, "\n") 825 # stream = table[i].stream 826 # write-stream-data(out, stream) 827 # ++i 828 # flush(out) 829 # 830 # . prolog 831 55/push-EBP 832 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 833 # . save registers 834 $write-segments:end: 835 # . reclaim locals 836 # . restore registers 837 # . epilog 838 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 839 5d/pop-to-EBP 840 c3/return 841 842 ## helpers 843 844 # TODO: pass in an allocation descriptor 845 get-or-insert-segment: # table : (address stream row), s : (address slice), n : int -> EAX : (address stream) 846 # pseudocode: 847 # curr = table->data 848 # max = &table->data[table->write] 849 # while curr < max 850 # if slice-equal?(s, *curr) 851 # return *(curr+4) 852 # curr += 8 853 # if table->write < table->length 854 # *max = slice-to-string(Heap, s) 855 # result = new-stream(Heap, n, 1) 856 # *(max+4) = result 857 # table->write += 8 858 # return result 859 # return 0 860 # 861 # . prolog 862 55/push-EBP 863 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 864 # . save registers 865 51/push-ECX 866 52/push-EDX 867 56/push-ESI 868 # ESI = table 869 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI 870 # curr/ECX = table->data 871 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 0xc/disp8 . # copy ESI+12 to ECX 872 # max/EDX = table->data + table->write 873 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX 874 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX . . # copy ECX+EDX to EDX 875 $get-or-insert-segment:search-loop: 876 # if (curr >= max) break 877 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX and EDX 878 7d/jump-if-greater-or-equal $get-or-insert-segment:not-found/disp8 879 # if (slice-equal?(s, *curr)) return *(curr+4) 880 # . EAX = slice-equal?(s, *curr) 881 # . . push args 882 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX 883 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 884 # . . call 885 e8/call slice-equal?/disp32 886 # . . discard args 887 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 888 # . if (EAX != 0) return EAX = *(curr+4) 889 3d/compare-EAX-and 0/imm32 890 74/jump-if-equal $get-or-insert-segment:mismatch/disp8 891 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX 892 eb/jump $get-or-insert-segment:end/disp8 893 $get-or-insert-segment:mismatch: 894 # curr += 8 895 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 8/imm32 # add to ECX 896 # loop 897 eb/jump $get-or-insert-segment:search-loop/disp8 898 $get-or-insert-segment:not-found: 899 # result/EAX = 0 900 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 901 # if (table->write >= table->length) abort 902 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX 903 3b/compare 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 8/disp8 . # compare ECX with *(ESI+8) 904 7d/jump-if-greater-or-equal $get-or-insert-segment:abort/disp8 905 # *max = slice-to-string(Heap, s) 906 # . EAX = slice-to-string(Heap, s) 907 # . . push args 908 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 909 68/push Heap/imm32 910 # . . call 911 e8/call slice-to-string/disp32 912 # . . discard args 913 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 914 # . *max = EAX <= writes to 0x0a003873 915 89/copy 0/mod/indirect 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to *EDX 916 # result/EAX = new-stream(Heap, n, 1) 917 # . . push args 918 68/push 1/imm32 919 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) 920 68/push Heap/imm32 921 # . . call 922 e8/call new-stream/disp32 923 # . . discard args 924 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 925 # *(max+4) = result 926 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) 927 # table->write += 8 928 81 0/subop/add 0/mod/indirect 6/rm32/ESI . . . . . 8/imm32 # add to *ESI 929 $get-or-insert-segment:end: 930 # . restore registers 931 5e/pop-to-ESI 932 5a/pop-to-EDX 933 59/pop-to-ECX 934 # . epilog 935 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 936 5d/pop-to-EBP 937 c3/return 938 939 $get-or-insert-segment:abort: 940 # . _write(2/stderr, error) 941 # . . push args 942 68/push "get-or-insert-segment: too many segments"/imm32 943 68/push 2/imm32/stderr 944 # . . call 945 e8/call _write/disp32 946 # . . discard args 947 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 948 # . syscall(exit, 1) 949 bb/copy-to-EBX 1/imm32 950 b8/copy-to-EAX 1/imm32/exit 951 cd/syscall 0x80/imm8 952 # never gets here 953 954 test-get-or-insert-segment: 955 # . prolog 956 55/push-EBP 957 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 958 # var table/ECX : (address stream byte) = stream(2 * 8) 959 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # subtract from ESP 960 68/push 0x10/imm32/length 961 68/push 0/imm32/read 962 68/push 0/imm32/write 963 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 964 # EDX : (address slice) = "code" 965 68/push _test-code-segment-end/imm32/end 966 68/push _test-code-segment/imm32/start 967 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX 968 $test-get-or-insert-segment:first-call: 969 # - start with an empty table, insert one segment, verify that it was inserted 970 # segment/EAX = get-or-insert-segment(table, "code" slice, 10) 971 # . . push args 972 68/push 0xa/imm32/segment-length 973 52/push-EDX 974 51/push-ECX 975 # . . call 976 e8/call get-or-insert-segment/disp32 977 # . . discard args 978 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 979 # save segment 980 50/push-EAX 981 # if (segment != 0) goto next check 982 3d/compare-EAX-and 0/imm32 983 75/jump-if-not-equal $test-get-or-insert-segment:check1/disp8 984 # fail test 985 # . _write(2/stderr, msg) 986 # . . push args 987 68/push "F - test-get-or-insert-segment/0"/imm32 988 68/push 2/imm32/stderr 989 # . . call 990 e8/call _write/disp32 991 # . . discard args 992 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 993 # . _write(2/stderr, Newline) 994 # . . push args 995 68/push Newline/imm32 996 68/push 2/imm32/stderr 997 # . . call 998 e8/call _write/disp32 999 # . . discard args 1000 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 1001 # . increment Num-test-failures 1002 ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures 1003 e9/jump $test-get-or-insert-segment:end/disp32 1004 $test-get-or-insert-segment:check1: 1005 # check-ints-equal(segment->length, 10, msg) 1006 # . . push args 1007 68/push "F - test-get-or-insert-segment/1"/imm32 1008 68/push 0xa/imm32/segment-length 1009 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) 1010 # . . call 1011 e8/call check-ints-equal/disp32 1012 # . . discard args 1013 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1014 $test-get-or-insert-segment:check2: 1015 # check-ints-equal(table->write, rowsize = 8, msg) 1016 # . . push args 1017 68/push "F - test-get-or-insert-segment/2"/imm32 1018 68/push 8/imm32/row-size 1019 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX 1020 # . . call 1021 e8/call check-ints-equal/disp32 1022 # . . discard args 1023 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1024 # EAX = string-equal?(*table->data, "code") 1025 # . . push args 1026 68/push "code"/imm32 1027 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 0xc/disp8 . # push *(ECX+12) 1028 # . . call 1029 e8/call string-equal?/disp32 1030 # . . discard args 1031 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 1032 # check-ints-equal(EAX, 1, msg) 1033 # . . push args 1034 68/push "F - test-get-or-insert-segment/3"/imm32 1035 68/push 1/imm32 1036 50/push-EAX 1037 # . . call 1038 e8/call check-ints-equal/disp32 1039 # . . discard args 1040 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1041 $test-get-or-insert-segment:check3: 1042 # stream/EAX = *(table->data+4) 1043 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 0x10/disp8 . # copy *(ECX+16) to EAX 1044 # check-ints-equal(stream->length, 10, msg) 1045 # . . push args 1046 68/push "F - test-get-or-insert-segment/4"/imm32 1047 68/push 0xa/imm32/segment-size 1048 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) 1049 # . . call 1050 e8/call check-ints-equal/disp32 1051 # . . discard args 1052 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1053 $test-get-or-insert-segment:second-call: 1054 # - insert the same segment name again, verify that it was reused 1055 # segment2/EAX = get-or-insert-segment(table, "code" slice, 8) 1056 # . . push args 1057 68/push 8/imm32/segment-length 1058 52/push-EDX 1059 51/push-ECX 1060 # . . call 1061 e8/call get-or-insert-segment/disp32 1062 # . . discard args 1063 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1064 # restore old segment1 1065 5a/pop-to-EDX 1066 # check-ints-equal(segment2/EAX, segment1/EDX, msg) 1067 # . . push args 1068 68/push "F - test-get-or-insert-segment/5"/imm32 1069 52/push-EDX 1070 50/push-EAX 1071 # . . call 1072 e8/call check-ints-equal/disp32 1073 # . . discard args 1074 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1075 # no change to table size 1076 # . check-ints-equal(table->write, rowsize = 8, msg) 1077 # . . push args 1078 68/push "F - test-get-or-insert-segment/6"/imm32 1079 68/push 8/imm32/row-size 1080 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX 1081 # . . call 1082 e8/call check-ints-equal/disp32 1083 # . . discard args 1084 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1085 $test-get-or-insert-segment:third-call: 1086 # - insert a new segment name, verify that it was inserted 1087 # EDX : (address slice) = "data" 1088 c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . _test-data-segment/imm32 # copy to *EDX 1089 c7 0/subop/copy 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 _test-data-segment-end/imm32 # copy to *(EDX+4) 1090 # segment2/EAX = get-or-insert-segment(table, "data" slice, 8) 1091 # . . push args 1092 68/push 8/imm32/segment-length 1093 52/push-EDX 1094 51/push-ECX 1095 # . . call 1096 e8/call get-or-insert-segment/disp32 1097 # . . discard args 1098 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1099 # table gets a new row 1100 # . check-ints-equal(table->write, 2 rows = 16, msg) 1101 # . . push args 1102 68/push "F - test-get-or-insert-segment/7"/imm32 1103 68/push 0x10/imm32/two-rows 1104 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX 1105 # . . call 1106 e8/call check-ints-equal/disp32 1107 # . . discard args 1108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1109 $test-get-or-insert-segment:end: 1110 # . epilog 1111 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 1112 5d/pop-to-EBP 1113 c3/return 1114 1115 # write an entire stream's contents to a buffered-file 1116 # ways to do this: 1117 # - construct a 'maximal slice' and pass it to write-slice 1118 # - flush the buffered-file and pass the stream directly to its fd (disabling buffering) 1119 # we'll go with the first way for now 1120 write-stream-data: # f : (address buffered-file), s : (address stream) -> <void> 1121 # . prolog 1122 55/push-EBP 1123 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 1124 # . save registers 1125 50/push-EAX 1126 51/push-ECX 1127 56/push-ESI 1128 # ESI = s 1129 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI 1130 # var slice/ECX = {s->data, s->data + s->write} 1131 # . push s->data + s->write 1132 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX 1133 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 1134 50/push-EAX 1135 # . push s->data 1136 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 0xc/disp8 . # copy ESI+12 to EAX 1137 50/push-EAX 1138 # . ECX = ESP 1139 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 1140 # write-slice(f, slice) 1141 # . . push args 1142 51/push-ECX 1143 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 1144 # . . call 1145 e8/call write-slice/disp32 1146 # . . discard args 1147 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 1148 $write-stream-data:end: 1149 # . restore locals 1150 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 1151 # . restore registers 1152 5e/pop-to-ESI 1153 59/pop-to-ECX 1154 58/pop-to-EAX 1155 # . epilog 1156 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 1157 5d/pop-to-EBP 1158 c3/return 1159 1160 test-write-stream-data: 1161 # . prolog 1162 55/push-EBP 1163 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 1164 # setup 1165 # . clear-stream(_test-stream) 1166 # . . push args 1167 68/push _test-stream/imm32 1168 # . . call 1169 e8/call clear-stream/disp32 1170 # . . discard args 1171 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 1172 # . clear-stream(_test-buffered-file+4) 1173 # . . push args 1174 b8/copy-to-EAX _test-buffered-file/imm32 1175 05/add-to-EAX 4/imm32 1176 50/push-EAX 1177 # . . call 1178 e8/call clear-stream/disp32 1179 # . . discard args 1180 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 1181 # . clear-stream(_test-tmp-stream) 1182 # . . push args 1183 68/push _test-tmp-stream/imm32 1184 # . . call 1185 e8/call clear-stream/disp32 1186 # . . discard args 1187 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 1188 # initialize input 1189 # . write(_test-tmp-stream, "abcd") 1190 # . . push args 1191 68/push "abcd"/imm32 1192 68/push _test-tmp-stream/imm32 1193 # . . call 1194 e8/call write/disp32 1195 # . . discard args 1196 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 1197 # write-stream-data(_test-buffered-file, _test-tmp-stream) 1198 # . . push args 1199 68/push _test-tmp-stream/imm32 1200 68/push _test-buffered-file/imm32 1201 # . . call 1202 e8/call write-stream-data/disp32 1203 # . . discard args 1204 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 1205 # check that the write happened as expected 1206 # . flush(_test-buffered-file) 1207 # . . push args 1208 68/push _test-buffered-file/imm32 1209 # . . call 1210 e8/call flush/disp32 1211 # . . discard args 1212 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 1213 # . check-stream-equal(_test-stream, "abcd", msg) 1214 # . . push args 1215 68/push "F - test-write-stream-data"/imm32 1216 68/push "abcd"/imm32 1217 68/push _test-stream/imm32 1218 # . . call 1219 e8/call check-stream-equal/disp32 1220 # . . discard args 1221 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 1222 # . epilog 1223 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 1224 5d/pop-to-EBP 1225 c3/return 1226 1227 == data 1228 1229 _test-input-stream: 1230 # current write index 1231 0/imm32 1232 # current read index 1233 0/imm32 1234 # length 1235 0x100/imm32 # 256 bytes 1236 # data (16 lines x 16 bytes/line) 1237 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1238 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1239 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1241 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1242 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1243 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1244 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1245 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1246 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1247 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1248 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1249 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1251 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1252 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1253 1254 # a test buffered file for _test-input-stream 1255 _test-input-buffered-file: 1256 # file descriptor or (address stream) 1257 _test-input-stream/imm32 1258 # current write index 1259 0/imm32 1260 # current read index 1261 0/imm32 1262 # length 1263 6/imm32 1264 # data 1265 00 00 00 00 00 00 # 6 bytes 1266 1267 _test-output-stream: 1268 # current write index 1269 0/imm32 1270 # current read index 1271 0/imm32 1272 # length 1273 0x100/imm32 # 256 bytes 1274 # data (16 lines x 16 bytes/line) 1275 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1276 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1277 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1278 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1279 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1281 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1282 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1283 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1284 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1285 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1286 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1287 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1288 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1289 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1291 1292 # a test buffered file for _test-output-stream 1293 _test-output-buffered-file: 1294 # file descriptor or (address stream) 1295 _test-output-stream/imm32 1296 # current write index 1297 0/imm32 1298 # current read index 1299 0/imm32 1300 # length 1301 6/imm32 1302 # data 1303 00 00 00 00 00 00 # 6 bytes 1304 1305 _test-code-segment: 1306 63/c 6f/o 64/d 65/e 1307 _test-code-segment-end: 1308 1309 _test-data-segment: 1310 64/d 61/a 74/t 61/a 1311 _test-data-segment-end: 1312 1313 # . . vim:nowrap:textwidth=0