From 6e1eeeebfb453fa7c871869c19375ce60fbd7413 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 27 Jul 2019 16:01:55 -0700 Subject: 5485 - promote SubX to top-level --- html/subx/056trace.subx.html | 1076 ------------------------------------------ 1 file changed, 1076 deletions(-) delete mode 100644 html/subx/056trace.subx.html (limited to 'html/subx/056trace.subx.html') diff --git a/html/subx/056trace.subx.html b/html/subx/056trace.subx.html deleted file mode 100644 index 61ead557..00000000 --- a/html/subx/056trace.subx.html +++ /dev/null @@ -1,1076 +0,0 @@ - - - - -Mu - subx/056trace.subx - - - - - - - - - - -https://github.com/akkartik/mu/blob/master/subx/056trace.subx -
-   1 # primitives for emitting traces to a 'trace' stream, and for tests to make assertions on its contents
-   2 #
-   3 # A trace stream looks like a regular stream:
-   4 #   write : int  # index at which writes go
-   5 #   read : int  # index that we've read until
-   6 #   data : (array byte)  # prefixed by length as usual
-   7 # Usually the trace stream will be in a separate segment set aside for the purpose.
-   8 #
-   9 # primitives for operating on traces (arguments in quotes):
-  10 #   - initialize-trace-stream: populates Trace-stream with a new segment of the given 'size'
-  11 #   - trace: adds a 'line' to Trace-stream
-  12 #   - check-trace-contains: scans from Trace-stream's start for a matching 'line', prints a 'message' to stderr on failure
-  13 #   - check-trace-scans-to: scans from Trace-stream's read pointer for a matching 'line', prints a 'message' to stderr on failure
-  14 
-  15 == data
-  16 
-  17 # We'll save the address of the trace segment here.
-  18 Trace-stream:
-  19     0/imm32
-  20 
-  21 Trace-segment:
-  22     0/imm32/curr
-  23     0/imm32/limit
-  24 
-  25 # Fake trace-stream for tests.
-  26 # Also illustrates the layout of the real trace-stream (segment).
-  27 _test-trace-stream:
-  28     # current write index
-  29     0/imm32
-  30     # current read index
-  31     0/imm32
-  32     # length
-  33     8/imm32
-  34     # data
-  35     00 00 00 00 00 00 00 00  # 8 bytes
-  36 
-  37 == code
-  38 #   instruction                     effective address                                                   register    displacement    immediate
-  39 # . op          subop               mod             rm32          base        index         scale       r32
-  40 # . 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
-  41 
-  42 # Allocate a new segment for the trace stream, initialize its length, and save its address to Trace-stream.
-  43 # The Trace-stream segment will consist of variable-length lines separated by newlines (0x0a)
-  44 initialize-trace-stream:  # n : int -> <void>
-  45     # . prolog
-  46     55/push-EBP
-  47     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-  48     # . save registers
-  49     50/push-EAX
-  50     51/push-ECX
-  51     # ECX = n
-  52     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
-  53     # Trace-segment = new-segment(n)
-  54     # . . push args
-  55     68/push  Trace-segment/imm32
-  56     51/push-ECX
-  57     # . . call
-  58     e8/call  new-segment/disp32
-  59     # . . discard args
-  60     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-  61     # copy Trace-segment->curr to *Trace-stream
-  62     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-segment/disp32              # copy *Trace-segment to EAX
-  63     # watch point to catch Trace-stream leaks
-  64 #? $watch-1:
-  65     89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy EAX to *Trace-stream
-  66     # Trace-stream->length = n - 12
-  67     # . ECX -= 12
-  68     81          5/subop/subtract    3/mod/direct    1/rm32/ECX    .           .             .           .           .               0xc/imm32         # subtract from ECX
-  69     # . Trace-stream->length = ECX
-  70     89/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           1/r32/ECX   8/disp8         .                 # copy ECX to *(EAX+8)
-  71 $initialize-trace-stream:end:
-  72     # . restore registers
-  73     59/pop-to-ECX
-  74     58/pop-to-EAX
-  75     # . epilog
-  76     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-  77     5d/pop-to-EBP
-  78     c3/return
-  79 
-  80 # Append a string to the given trace stream.
-  81 # Silently give up if it's already full. Or truncate the string if there isn't enough room.
-  82 trace:  # line : (address string)
-  83     # . prolog
-  84     55/push-EBP
-  85     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-  86     # . save registers
-  87     50/push-EAX
-  88     51/push-ECX
-  89     52/push-EDX
-  90     53/push-EBX
-  91     56/push-ESI
-  92     57/push-EDI
-  93     # EDI = *Trace-stream
-  94     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           7/r32/EDI   Trace-stream/disp32               # copy *Trace-stream to EDI
-  95     # ESI = line
-  96     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
-  97     # ECX = t->write
-  98     8b/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # copy *EDI to ECX
-  99     # EDX = t->length
- 100     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           2/r32/EDX   8/disp8         .                 # copy *(EDI+8) to EDX
- 101     # EAX = _append-3(&t->data[t->write], &t->data[t->length], line)
- 102     # . . push line
- 103     56/push-ESI
- 104     # . . push &t->data[t->length]
- 105     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/EDI  2/index/EDX   .           3/r32/EBX   0xc/disp8       .                 # copy EDI+EDX+12 to EBX
- 106     53/push-EBX
- 107     # . . push &t->data[t->write]
- 108     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/EDI  1/index/ECX   .           3/r32/EBX   0xc/disp8       .                 # copy EDI+ECX+12 to EBX
- 109     53/push-EBX
- 110     # . . call
- 111     e8/call  _append-3/disp32
- 112     # . . discard args
- 113     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 114     # if (EAX == 0) return
- 115     3d/compare-EAX-and  0/imm32
- 116     74/jump-if-equal  $trace:end/disp8
- 117     # t->write += EAX
- 118     01/add                          0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # add EAX to *EDI
- 119     # refresh ECX = t->write
- 120     8b/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # copy *EDI to ECX
- 121     # EAX = _append-3(&t->data[t->write], &t->data[t->length], line)
- 122     # . . push line
- 123     68/push  Newline/imm32
- 124     # . . push &t->data[t->length]
- 125     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/EDI  2/index/EDX   .           3/r32/EBX   0xc/disp8       .                 # copy EDI+EDX+12 to EBX
- 126     53/push-EBX
- 127     # . . push &t->data[t->write]
- 128     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/EDI  1/index/ECX   .           3/r32/EBX   0xc/disp8       .                 # copy EDI+ECX+12 to EBX
- 129     53/push-EBX
- 130     # . . call
- 131     e8/call  _append-3/disp32
- 132     # . . discard args
- 133     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 134     # t->write += EAX
- 135     01/add                          0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # add EAX to *EDI
- 136 $trace:end:
- 137     # . restore registers
- 138     5f/pop-to-EDI
- 139     5e/pop-to-ESI
- 140     5b/pop-to-EBX
- 141     5a/pop-to-EDX
- 142     59/pop-to-ECX
- 143     58/pop-to-EAX
- 144     # . epilog
- 145     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 146     5d/pop-to-EBP
- 147     c3/return
- 148 
- 149 test-trace-single:
- 150     # push *Trace-stream
- 151     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
- 152     # *Trace-stream = _test-trace-stream
- 153     b8/copy-to-EAX  _test-trace-stream/imm32
- 154     89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy EAX to *Trace-stream
- 155     # clear-trace-stream()
- 156     e8/call  clear-trace-stream/disp32
- 157     # trace("Ab")
- 158     # . . push args
- 159     68/push  "Ab"/imm32
- 160     # . . call
- 161     e8/call  trace/disp32
- 162     # . . discard args
- 163     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 164     # check-ints-equal(*_test-trace-stream->data, 41/A 62/b 0a/newline 00, msg)
- 165     # . . push args
- 166     68/push  "F - test-trace-single"/imm32
- 167     68/push  0x0a6241/imm32/Ab-newline
- 168     # . . push *_test-trace-stream->data
- 169     b8/copy-to-EAX  _test-trace-stream/imm32
- 170     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           0xc/disp8       .                 # push *(EAX+12)
- 171     # . . call
- 172     e8/call  check-ints-equal/disp32
- 173     # . . discard args
- 174     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 175     # pop into *Trace-stream
- 176     8f          0/subop/pop         0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # pop into *Trace-stream
- 177     # end
- 178     c3/return
- 179 
- 180 test-trace-appends:
- 181     # push *Trace-stream
- 182     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
- 183     # *Trace-stream = _test-trace-stream
- 184     b8/copy-to-EAX  _test-trace-stream/imm32
- 185     89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy EAX to *Trace-stream
- 186     # clear-trace-stream()
- 187     e8/call  clear-trace-stream/disp32
- 188     # trace("C")
- 189     # . . push args
- 190     68/push  "C"/imm32
- 191     # . . call
- 192     e8/call  trace/disp32
- 193     # . . discard args
- 194     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 195     # trace("D")
- 196     # . . push args
- 197     68/push  "D"/imm32
- 198     # . . call
- 199     e8/call  trace/disp32
- 200     # . . discard args
- 201     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 202     # check-ints-equal(*_test-trace-stream->data, 43/C 0a/newline 44/D 0a/newline, msg)
- 203     # . . push args
- 204     68/push  "F - test-trace-appends"/imm32
- 205     68/push  0x0a440a43/imm32/C-newline-D-newline
- 206     # . . push *_test-trace-stream->data
- 207     b8/copy-to-EAX  _test-trace-stream/imm32
- 208     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           0xc/disp8       .                 # push *(EAX+12)
- 209     # . . call
- 210     e8/call  check-ints-equal/disp32
- 211     # . . discard args
- 212     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 213     # pop into *Trace-stream
- 214     8f          0/subop/pop         0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # pop into *Trace-stream
- 215     # end
- 216     c3/return
- 217 
- 218 test-trace-empty-line:
- 219     # push *Trace-stream
- 220     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
- 221     # *Trace-stream = _test-trace-stream
- 222     b8/copy-to-EAX  _test-trace-stream/imm32
- 223     89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy EAX to *Trace-stream
- 224     # clear-trace-stream()
- 225     e8/call  clear-trace-stream/disp32
- 226     # trace("")
- 227     # . . push args
- 228     68/push  ""/imm32
- 229     # . . call
- 230     e8/call  trace/disp32
- 231     # . . discard args
- 232     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 233     # check-ints-equal(*_test-trace-stream->data, 0, msg)
- 234     # . . push args
- 235     68/push  "F - test-trace-empty-line"/imm32
- 236     68/push  0/imm32
- 237     # . . push *_test-trace-stream->data
- 238     b8/copy-to-EAX  _test-trace-stream/imm32
- 239     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           0xc/disp8       .                 # push *(EAX+12)
- 240     # . . call
- 241     e8/call  check-ints-equal/disp32
- 242     # . . discard args
- 243     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 244     # pop into *Trace-stream
- 245     8f          0/subop/pop         0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # pop into *Trace-stream
- 246     # end
- 247     c3/return
- 248 
- 249 check-trace-contains:  # line : (address string), msg : (address string)
- 250     # . prolog
- 251     55/push-EBP
- 252     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 253     # rewind-stream(*Trace-stream)
- 254     # . . push args
- 255     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
- 256     # . . call
- 257     e8/call  rewind-stream/disp32
- 258     # . . discard args
- 259     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 260     # check-trace-scans-to(line, msg)
- 261     # . . push args
- 262     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
- 263     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
- 264     # . . call
- 265     e8/call  check-trace-scans-to/disp32
- 266     # . . discard args
- 267     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 268 $check-trace-contains:end:
- 269     # . epilog
- 270     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 271     5d/pop-to-EBP
- 272     c3/return
- 273 
- 274 check-trace-scans-to:  # line : (address string), msg : (address string)
- 275     # . prolog
- 276     55/push-EBP
- 277     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 278     # . save registers
- 279     50/push-EAX
- 280     # EAX = trace-scan(line)
- 281     # . . push args
- 282     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
- 283     # . . call
- 284     e8/call  trace-scan/disp32
- 285     # . . discard args
- 286     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 287     # check-ints-equal(EAX, 1, msg)
- 288     # . . push args
- 289     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
- 290     68/push  1/imm32
- 291     50/push-EAX
- 292     # . . call
- 293     e8/call check-ints-equal/disp32
- 294     # . . discard args
- 295     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 296 $check-trace-scans-to:end:
- 297     # . restore registers
- 298     58/pop-to-EAX
- 299     # . epilog
- 300     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 301     5d/pop-to-EBP
- 302     c3/return
- 303 
- 304 # Start scanning from Trace-stream->read for 'line'. If found, update Trace-stream->read and return true.
- 305 trace-scan:  # line : (address string) -> result/EAX : boolean
- 306     # pseudocode:
- 307     #   push Trace-stream->read
- 308     #   while true:
- 309     #     if Trace-stream->read >= Trace-stream->write
- 310     #       break
- 311     #     if next-line-matches?(Trace-stream, line)
- 312     #       skip-next-line(Trace-stream)
- 313     #       dump saved copy of Trace-stream->read
- 314     #       return true
- 315     #     skip-next-line(Trace-stream)
- 316     #   pop saved copy of Trace-stream->read
- 317     #   return false
- 318     #
- 319     # . prolog
- 320     55/push-EBP
- 321     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 322     # . save registers
- 323     51/push-ECX
- 324     56/push-ESI
- 325     # ESI = *Trace-stream
- 326     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           6/r32/ESI   Trace-stream/disp32               # copy *Trace-stream to ESI
- 327     # ECX = Trace-stream->write
- 328     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           1/r32/ECX                   .                 # copy *ESI to ECX
- 329     # push Trace-stream->read
- 330     ff          6/subop/push        1/mod/*+disp8   6/rm32/ESI    .           .             .           .           4/disp8         .                 # push *(ESI+4)
- 331 $trace-scan:loop:
- 332     # if (Trace-stream->read >= Trace-stream->write) return false
- 333     39/compare                      1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # compare ECX with *(ESI+4)
- 334     7d/jump-if-greater-or-equal  $trace-scan:false/disp8
- 335     # EAX = next-line-matches?(Trace-stream, line)
- 336     # . . push args
- 337     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
- 338     56/push-ESI
- 339     # . . call
- 340     e8/call  next-line-matches?/disp32
- 341     # . . discard args
- 342     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 343     # if (EAX == 0) continue
- 344     3d/compare-EAX-and  0/imm32
- 345     74/jump-if-equal  $trace-scan:continue/disp8
- 346 $trace-scan:true:
- 347     # skip-next-line(Trace-stream)
- 348     # . . push args
- 349     56/push-ESI
- 350     # . . call
- 351     e8/call  skip-next-line/disp32
- 352     # . . discard args
- 353     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 354     # dump saved copy of Trace-stream->read
- 355     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 356     # return true
- 357     b8/copy-to-EAX  1/imm32/true
- 358     eb/jump  $trace-scan:end/disp8
- 359 $trace-scan:continue:
- 360     # skip-next-line(Trace-stream)
- 361     # . . push args
- 362     56/push-ESI
- 363     # . . call
- 364     e8/call  skip-next-line/disp32
- 365     # . . discard args
- 366     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 367     eb/jump  $trace-scan:loop/disp8
- 368 $trace-scan:false:
- 369     # restore saved copy of Trace-stream->read
- 370     8f          0/subop/pop         1/mod/*+disp8   6/rm32/ESI    .           .             .           .           4/disp8         .                 # pop to *(ESI+4)
- 371     # return false
- 372     b8/copy-to-EAX  0/imm32/false
- 373 $trace-scan:end:
- 374     # . restore registers
- 375     59/pop-to-ECX
- 376     # . epilog
- 377     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 378     5d/pop-to-EBP
- 379     c3/return
- 380 
- 381 test-trace-scan-first:
- 382     # push *Trace-stream
- 383     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
- 384     # setup
- 385     # . *Trace-stream = _test-trace-stream
- 386     b8/copy-to-EAX  _test-trace-stream/imm32
- 387     89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy EAX to *Trace-stream
- 388     # . clear-trace-stream()
- 389     e8/call  clear-trace-stream/disp32
- 390     # . trace("Ab")
- 391     # . . push args
- 392     68/push  "Ab"/imm32
- 393     # . . call
- 394     e8/call  trace/disp32
- 395     # . . discard args
- 396     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 397     # EAX = trace-scan("Ab")
- 398     # . . push args
- 399     68/push  "Ab"/imm32
- 400     # . . call
- 401     e8/call  trace-scan/disp32
- 402     # . . discard args
- 403     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 404     # check-ints-equal(EAX, 1, msg)
- 405     # . . push args
- 406     68/push  "F - test-trace-scan-first"/imm32
- 407     68/push  1/imm32
- 408     50/push-EAX
- 409     # . . call
- 410     e8/call check-ints-equal/disp32
- 411     # . . discard args
- 412     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 413     # pop into *Trace-stream
- 414     8f          0/subop/pop         0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # pop into *Trace-stream
- 415     # . end
- 416     c3/return
- 417 
- 418 test-trace-scan-skips-lines-until-found:
- 419     # push *Trace-stream
- 420     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
- 421     # setup
- 422     # . *Trace-stream = _test-trace-stream
- 423     b8/copy-to-EAX  _test-trace-stream/imm32
- 424     89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy EAX to *Trace-stream
- 425     # . clear-trace-stream()
- 426     e8/call  clear-trace-stream/disp32
- 427     # . trace("Ab")
- 428     # . . push args
- 429     68/push  "Ab"/imm32
- 430     # . . call
- 431     e8/call  trace/disp32
- 432     # . . discard args
- 433     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 434     # . trace("cd")
- 435     # . . push args
- 436     68/push  "cd"/imm32
- 437     # . . call
- 438     e8/call  trace/disp32
- 439     # . . discard args
- 440     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 441     # EAX = trace-scan("cd")
- 442     # . . push args
- 443     68/push  "cd"/imm32
- 444     # . . call
- 445     e8/call  trace-scan/disp32
- 446     # . . discard args
- 447     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 448     # check-ints-equal(EAX, 1, msg)
- 449     # . . push args
- 450     68/push  "F - test-trace-scan-skips-lines-until-found"/imm32
- 451     68/push  1/imm32
- 452     50/push-EAX
- 453     # . . call
- 454     e8/call check-ints-equal/disp32
- 455     # . . discard args
- 456     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 457     # pop into *Trace-stream
- 458     8f          0/subop/pop         0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # pop into *Trace-stream
- 459     # . end
- 460     c3/return
- 461 
- 462 test-trace-second-scan-starts-where-first-left-off:
- 463     # push *Trace-stream
- 464     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
- 465     # setup
- 466     # . *Trace-stream = _test-trace-stream
- 467     b8/copy-to-EAX  _test-trace-stream/imm32
- 468     89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy EAX to *Trace-stream
- 469     # . clear-trace-stream()
- 470     e8/call  clear-trace-stream/disp32
- 471     # . trace("Ab")
- 472     # . . push args
- 473     68/push  "Ab"/imm32
- 474     # . . call
- 475     e8/call  trace/disp32
- 476     # . . discard args
- 477     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 478     # . EAX = trace-scan("Ab")
- 479     # . . push args
- 480     68/push  "Ab"/imm32
- 481     # . . call
- 482     e8/call  trace-scan/disp32
- 483     # . . discard args
- 484     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 485     # second scan fails
- 486     # . EAX = trace-scan("Ab")
- 487     # . . push args
- 488     68/push  "Ab"/imm32
- 489     # . . call
- 490     e8/call  trace-scan/disp32
- 491     # . . discard args
- 492     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 493     # check-ints-equal(EAX, 0, msg)
- 494     # . . push args
- 495     68/push  "F - test-trace-second-scan-starts-where-first-left-off"/imm32
- 496     68/push  0/imm32
- 497     50/push-EAX
- 498     # . . call
- 499     e8/call check-ints-equal/disp32
- 500     # . . discard args
- 501     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 502     # pop into *Trace-stream
- 503     8f          0/subop/pop         0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # pop into *Trace-stream
- 504     # . end
- 505     c3/return
- 506 
- 507 test-trace-scan-failure-leaves-read-index-untouched:
- 508     # push *Trace-stream
- 509     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
- 510     # setup
- 511     # . *Trace-stream = _test-trace-stream
- 512     b8/copy-to-EAX  _test-trace-stream/imm32
- 513     89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy EAX to *Trace-stream
- 514     # . clear-trace-stream()
- 515     e8/call  clear-trace-stream/disp32
- 516     # . trace("Ab")
- 517     # . . push args
- 518     68/push  "Ab"/imm32
- 519     # . . call
- 520     e8/call  trace/disp32
- 521     # . . discard args
- 522     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 523     # . check-ints-equal(_test-trace-stream->read, 0, msg)
- 524     # . . push args
- 525     68/push  "F - test-trace-second-scan-starts-where-first-left-off/precondition-failure"/imm32
- 526     68/push  0/imm32
- 527     b8/copy-to-EAX  _test-trace-stream/imm32
- 528     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
- 529     # . . call
- 530     e8/call check-ints-equal/disp32
- 531     # . . discard args
- 532     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 533     # perform a failing scan
- 534     # . EAX = trace-scan("Ax")
- 535     # . . push args
- 536     68/push  "Ax"/imm32
- 537     # . . call
- 538     e8/call  trace-scan/disp32
- 539     # . . discard args
- 540     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 541     # no change in read index
- 542     # . check-ints-equal(_test-trace-stream->read, 0, msg)
- 543     # . . push args
- 544     68/push  "F - test-trace-second-scan-starts-where-first-left-off"/imm32
- 545     68/push  0/imm32
- 546     b8/copy-to-EAX  _test-trace-stream/imm32
- 547     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
- 548     # . . call
- 549     e8/call check-ints-equal/disp32
- 550     # . . discard args
- 551     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 552     # pop into *Trace-stream
- 553     8f          0/subop/pop         0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # pop into *Trace-stream
- 554     # . end
- 555     c3/return
- 556 
- 557 next-line-matches?:  # t : (address stream), line : (address string) -> result/EAX : boolean
- 558     # pseudocode:
- 559     #   while true:
- 560     #     if (currl >= maxl) break
- 561     #     if (currt >= maxt) return false
- 562     #     if (*currt != *currl) return false
- 563     #     ++currt
- 564     #     ++currl
- 565     #   return *currt == '\n'
- 566     #
- 567     # . prolog
- 568     55/push-EBP
- 569     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 570     # . save registers
- 571     51/push-ECX
- 572     52/push-EDX
- 573     53/push-EBX
- 574     56/push-ESI
- 575     57/push-EDI
- 576     # EDX = line
- 577     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
- 578     # currl/ESI = line->data
- 579     # . ESI = line/EDX->data
- 580     8d/copy-address                 1/mod/*+disp8   2/rm32/EDX    .           .             .           6/r32/ESI   4/disp8         .                 # copy EDX+4 to ESI
- 581     # maxl/ECX = line->data + line->size
- 582     # . EAX = line/EDX->size
- 583     8b/copy                         0/mod/indirect  2/rm32/EDX    .           .                         0/r32/EAX   .               .                 # copy *EDX to EAX
- 584     # . maxl/ECX = line->data/ESI + line->size/EAX
- 585     8d/copy-address                 0/mod/indirect  4/rm32/sib    6/base/ESI  0/index/EAX   .           1/r32/ECX   .               .                 # copy EDX+EAX to ECX
- 586     # EDI = t
- 587     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
- 588     # EBX = t->data
- 589     8d/copy-address                 1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   0xc/disp8       .                 # copy EDI+12 to EBX
- 590     # maxt/EDX = t->data + t->write
- 591     # . EAX = t->write
- 592     8b/copy                         0/mod/indirect  7/rm32/EDI    .           .                         0/r32/EAX   .               .                 # copy *EDI to EAX
- 593     # . maxt/EDX = t->data/EBX + t->write/EAX
- 594     8d/copy-address                 0/mod/indirect  4/rm32/sib    3/base/EBX  0/index/EAX   .           2/r32/EDX   .               .                 # copy EBX+EAX to EDX
- 595     # currt/EDI = t->data + t->read
- 596     # . EAX = t/EDI->read
- 597     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .                         0/r32/EAX   4/disp8         .                 # copy *(EDI+4) to EAX
- 598     # . currt/EDI = t->data/EBX + t->read/EAX
- 599     8d/copy-address                 0/mod/indirect  4/rm32/sib    3/base/EBX  0/index/EAX   .           7/r32/EDI   .               .                 # copy EBX+EAX to EDI
- 600 $next-line-matches?:loop:
- 601     # if (currl/ESI >= maxl/ECX) break
- 602     39/compare                      3/mod/direct    6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # compare ESI and ECX
- 603     73/jump-if-greater-or-equal-unsigned  $next-line-matches?:break/disp8
- 604     # if (currt/EDI >= maxt/EDX) return false
- 605     # . EAX = false
- 606     b8/copy-to-EAX  0/imm32/false
- 607     39/compare                      3/mod/direct    7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # compare EDI and EDX
- 608     73/jump-if-greater-or-equal-unsigned  $next-line-matches?:end/disp8
- 609     # if (*currt/EDI != *currl/ESI) return false
- 610     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
- 611     31/xor                          3/mod/direct    3/rm32/EAX    .           .             .           3/r32/EAX   .               .                 # clear EBX
- 612     # . EAX = (char) *currt/EDI
- 613     8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .                         0/r32/EAX   .               .                 # copy *EDI to EAX
- 614     # . EBX = (char) *currl/ESI
- 615     8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .                         3/r32/EBX   .               .                 # copy *ESI to EBX
- 616     # . EAX >= EBX
- 617     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
- 618     # . EAX = false
- 619     b8/copy-to-EAX  0/imm32/false
- 620     75/jump-if-not-equal  $next-line-matches?:end/disp8
- 621     # ++currt/EDI
- 622     47/increment-EDI
- 623     # ++currl/ESI
- 624     46/increment-ESI
- 625     eb/jump  $next-line-matches?:loop/disp8
- 626 $next-line-matches?:break:
- 627     # return *currt == '\n'
- 628     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
- 629     # . EAX = (char) *currt
- 630     8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .                         0/r32/EAX   .               .                 # copy *EDI to EAX
- 631     3d/compare-EAX-and  0xa/imm32/newline
- 632     # . EAX = false
- 633     b8/copy-to-EAX  1/imm32/true
- 634     74/jump-if-equal  $next-line-matches?:end/disp8
- 635     b8/copy-to-EAX  0/imm32/true
- 636 $next-line-matches?:end:
- 637     # . restore registers
- 638     5f/pop-to-EDI
- 639     5e/pop-to-ESI
- 640     5b/pop-to-EBX
- 641     5a/pop-to-EDX
- 642     59/pop-to-ECX
- 643     # . epilog
- 644     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 645     5d/pop-to-EBP
- 646     c3/return
- 647 
- 648 test-next-line-matches?-no-match-1:
- 649     # next line of "ABABA" does not match "blah blah"
- 650     # . EAX = next-line-matches?(_test-stream-line-ABABA, "blah blah")
- 651     # . . push args
- 652     68/push  "blah blah"/imm32
- 653     68/push  _test-stream-line-ABABA/imm32
- 654     # . . call
- 655     e8/call  next-line-matches?/disp32
- 656     # . . discard args
- 657     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 658     # . check-ints-equal(EAX, 0, msg)
- 659     # . . push args
- 660     68/push  "F - test-next-line-matches?-no-match-1"/imm32
- 661     68/push  0/imm32
- 662     50/push-EAX
- 663     # . . call
- 664     e8/call  check-ints-equal/disp32
- 665     # . . discard args
- 666     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 667     c3/return
- 668 
- 669 test-next-line-matches?-no-match-2:
- 670     # next line of "ABABA" does not match ""
- 671     # . EAX = next-line-matches?(_test-stream-line-ABABA, "")
- 672     # . . push args
- 673     68/push  ""/imm32
- 674     68/push  _test-stream-line-ABABA/imm32
- 675     # . . call
- 676     e8/call  next-line-matches?/disp32
- 677     # . . discard args
- 678     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 679     # . check-ints-equal(EAX, 0, msg)
- 680     # . . push args
- 681     68/push  "F - test-next-line-matches?-no-match-2"/imm32
- 682     68/push  0/imm32
- 683     50/push-EAX
- 684     # . . call
- 685     e8/call  check-ints-equal/disp32
- 686     # . . discard args
- 687     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 688     c3/return
- 689 
- 690 test-next-line-matches?-no-match-3:
- 691     # next line of "ABABA" does not match  "AA"
- 692     # . EAX = next-line-matches?(_test-stream-line-ABABA, "AA")
- 693     # . . push args
- 694     68/push  "AA"/imm32
- 695     68/push  _test-stream-line-ABABA/imm32
- 696     # . . call
- 697     e8/call  next-line-matches?/disp32
- 698     # . . discard args
- 699     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 700     # . check-ints-equal(EAX, 0, msg)
- 701     # . . push args
- 702     68/push  "F - test-next-line-matches?-no-match-3"/imm32
- 703     68/push  0/imm32
- 704     50/push-EAX
- 705     # . . call
- 706     e8/call  check-ints-equal/disp32
- 707     # . . discard args
- 708     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 709     c3/return
- 710 
- 711 test-next-line-matches?-match:
- 712     # next line of "ABABA" matches "ABABA"
- 713     # . EAX = next-line-matches?(_test-stream-line-ABABA, "ABABA")
- 714     # . . push args
- 715     68/push  "ABABA"/imm32
- 716     68/push  _test-stream-line-ABABA/imm32
- 717     # . . call
- 718     e8/call  next-line-matches?/disp32
- 719     # . . discard args
- 720     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 721     # . check-ints-equal(EAX, 1, msg)
- 722     # . . push args
- 723     68/push  "F - test-next-line-matches?-match"/imm32
- 724     68/push  1/imm32
- 725     50/push-EAX
- 726     # . . call
- 727     e8/call  check-ints-equal/disp32
- 728     # . . discard args
- 729     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 730     c3/return
- 731 
- 732 # move t->read to _after_ next newline
- 733 skip-next-line:  # t : (address stream)
- 734     # pseudocode:
- 735     #   max = t->data + t->write
- 736     #   i = t->read
- 737     #   curr = t->data + t->read
- 738     #   while true
- 739     #     if (curr >= max) break
- 740     #     ++i
- 741     #     if (*curr == '\n') break
- 742     #     ++curr
- 743     #   t->read = i
- 744     #
- 745     # . prolog
- 746     55/push-EBP
- 747     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 748     # . save registers
- 749     50/push-EAX
- 750     51/push-ECX
- 751     52/push-EDX
- 752     53/push-EBX
- 753     # ECX = t
- 754     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
- 755     # EDX = t/ECX->data
- 756     8d/copy-address                 1/mod/*+disp8   1/rm32/ECX    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy ECX+12 to EDX
- 757     # EAX = t/ECX->write
- 758     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
- 759     # max/EBX = t->data/EDX + t->write/EAX
- 760     8d/copy-address                 0/mod/indirect  4/rm32/sib    2/base/EDX  0/index/EAX   .           3/r32/EBX   .               .                 # copy EDX+EAX to EBX
- 761     # EAX = t/ECX->read
- 762     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EDX
- 763     # curr/ECX = t->data/EDX + t->read/EAX
- 764     8d/copy-address                 0/mod/indirect  4/rm32/sib    2/base/EDX  0/index/EAX   .           1/r32/ECX   .               .                 # copy EDX+EAX to ECX
- 765     # i/EDX = EAX
- 766     8b/copy                         3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # copy EAX to EDX
- 767 $skip-next-line:loop:
- 768     # if (curr/ECX >= max/EBX) break
- 769     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           3/r32/EBX   .               .                 # compare ECX and EBX
- 770     73/jump-if-greater-or-equal-unsigned  $skip-next-line:end/disp8
- 771     # ++i/EDX
- 772     42/increment-EDX
- 773     # if (*curr/ECX == '\n') break
- 774     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
- 775     8a/copy-byte                    0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
- 776     3d/compare-EAX-and  0a/imm32/newline
- 777     74/jump-if-equal  $skip-next-line:end/disp8
- 778     # ++curr/ECX
- 779     41/increment-ECX
- 780     # loop
- 781     eb/jump  $skip-next-line:loop/disp8
- 782 $skip-next-line:end:
- 783     # ECX = t
- 784     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
- 785     # t/ECX->read = i/EDX
- 786     89/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           2/r32/EDX   4/disp8         .                 # copy EDX to *(ECX+4)
- 787     # . restore registers
- 788     5b/pop-to-EBX
- 789     5a/pop-to-EDX
- 790     59/pop-to-ECX
- 791     58/pop-to-EAX
- 792     # . epilog
- 793     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 794     5d/pop-to-EBP
- 795     c3/return
- 796 
- 797 test-skip-next-line-empty:
- 798     # skipping next line in empty stream leaves read pointer at 0
- 799     # . skip-next-line(_test-stream-empty)
- 800     # . . push args
- 801     68/push  _test-stream-empty/imm32
- 802     # . . call
- 803     e8/call  skip-next-line/disp32
- 804     # . . discard args
- 805     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 806     # . check-ints-equal(_test-stream-empty->read, 0, msg)
- 807     # . . push args
- 808     68/push  "F - test-skip-next-line-empty"/imm32
- 809     68/push  0/imm32
- 810     b8/copy-to-EAX  _test-stream-empty/imm32
- 811     8b/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(EAX+4) to EAX
- 812     50/push-EAX
- 813     # . . call
- 814     e8/call  check-ints-equal/disp32
- 815     # . . discard args
- 816     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 817     c3/return
- 818 
- 819 test-skip-next-line-filled:
- 820     # skipping next line increments read pointer by length of line + 1 (for newline)
- 821     # . skip-next-line(_test-stream-filled)
- 822     # . . push args
- 823     68/push  _test-stream-filled/imm32
- 824     # . . call
- 825     e8/call  skip-next-line/disp32
- 826     # . . discard args
- 827     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 828     # . check-ints-equal(_test-stream-filled->read, 5, msg)
- 829     # . . push args
- 830     68/push  "F - test-skip-next-line-filled"/imm32
- 831     68/push  5/imm32
- 832     b8/copy-to-EAX  _test-stream-filled/imm32
- 833     8b/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(EAX+4) to EAX
- 834     50/push-EAX
- 835     # . . call
- 836     e8/call  check-ints-equal/disp32
- 837     # . . discard args
- 838     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 839     c3/return
- 840 
- 841 clear-trace-stream:
- 842     # . prolog
- 843     55/push-EBP
- 844     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 845     # . save registers
- 846     50/push-EAX
- 847     51/push-ECX
- 848     # EAX = *Trace-stream
- 849     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Trace-stream/disp32               # copy *Trace-stream to EAX
- 850     # ECX = t->length
- 851     8b/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EAX+8) to ECX
- 852     # ECX = &t->data[t->length]
- 853     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   0xc/disp8       .                 # copy EAX+ECX+12 to ECX
- 854     # t->write = 0
- 855     c7          0/subop/copy        0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
- 856     # t->read = 0
- 857     c7          0/subop/copy        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         0/imm32           # copy to *(EAX+4)
- 858     # EAX = t->data
- 859     81          0/subop/add         3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xc/imm32         # add to EAX
- 860 $clear-trace-stream:loop:
- 861     # if (EAX >= ECX) break
- 862     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX with ECX
- 863     73/jump-if-greater-or-equal-unsigned  $clear-trace-stream:end/disp8
- 864     # *EAX = 0
- 865     c7          0/subop/copy        0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
- 866     # EAX += 4
- 867     81          0/subop/add         3/mod/direct    0/rm32/EAX    .           .             .           .           .               4/imm32           # add to EAX
- 868     eb/jump  $clear-trace-stream:loop/disp8
- 869 $clear-trace-stream:end:
- 870     # . restore registers
- 871     59/pop-to-ECX
- 872     58/pop-to-EAX
- 873     # . epilog
- 874     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 875     5d/pop-to-EBP
- 876     c3/return
- 877 
- 878 # - helpers
- 879 
- 880 # 3-argument variant of _append
- 881 _append-3:  # out : address, outend : address, s : (array byte) -> num_bytes_appended/EAX
- 882     # . prolog
- 883     55/push-EBP
- 884     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 885     # . save registers
- 886     51/push-ECX
- 887     # EAX = _append-4(out, outend, &s->data[0], &s->data[s->length])
- 888     # . . push &s->data[s->length]
- 889     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         0/r32/EAX   0x10/disp8      .                 # copy *(EBP+16) to EAX
- 890     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
- 891     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   4/disp8         .                 # copy EAX+ECX+4 to ECX
- 892     51/push-ECX
- 893     # . . push &s->data[0]
- 894     8d/copy-address                 1/mod/*+disp8   0/rm32/EAX    .           .             .           1/r32/ECX   4/disp8         .                 # copy EAX+4 to ECX
- 895     51/push-ECX
- 896     # . . push outend
- 897     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
- 898     # . . push out
- 899     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
- 900     # . . call
- 901     e8/call  _append-4/disp32
- 902     # . . discard args
- 903     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
- 904 $_append-3:end:
- 905     # . restore registers
- 906     59/pop-to-ECX
- 907     # . epilog
- 908     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 909     5d/pop-to-EBP
- 910     c3/return
- 911 
- 912 # 4-argument variant of _append
- 913 _append-4:  # out : address, outend : address, in : address, inend : address -> num_bytes_appended/EAX
- 914     # . prolog
- 915     55/push-EBP
- 916     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 917     # . save registers
- 918     51/push-ECX
- 919     52/push-EDX
- 920     53/push-EBX
- 921     56/push-ESI
- 922     57/push-EDI
- 923     # EAX/num_bytes_appended = 0
- 924     b8/copy-to-EAX  0/imm32
- 925     # EDI = out
- 926     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
- 927     # EDX = outend
- 928     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
- 929     # ESI = in
- 930     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   0x10/disp8      .                 # copy *(EBP+16) to ESI
- 931     # ECX = inend
- 932     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   0x14/disp8      .                 # copy *(EBP+20) to ECX
- 933 $_append-4:loop:
- 934     # if (in >= inend) break
- 935     39/compare                      3/mod/direct    6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # compare ESI with ECX
- 936     73/jump-if-greater-or-equal-unsigned  $_append-4:end/disp8
- 937     # if (out >= outend) abort  # just to catch test failures fast
- 938     39/compare                      3/mod/direct    7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # compare EDI with EDX
- 939     73/jump-if-greater-or-equal-unsigned  $_append-4:abort/disp8
- 940     # *out = *in
- 941     8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/BL    .               .                 # copy byte at *ESI to BL
- 942     88/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           3/r32/BL    .               .                 # copy byte at BL to *EDI
- 943     # ++num_bytes_appended
- 944     40/increment-EAX
- 945     # ++in
- 946     46/increment-ESI
- 947     # ++out
- 948     47/increment-EDI
- 949     eb/jump  $_append-4:loop/disp8
- 950 $_append-4:end:
- 951     # . restore registers
- 952     5f/pop-to-EDI
- 953     5e/pop-to-ESI
- 954     5b/pop-to-EBX
- 955     5a/pop-to-EDX
- 956     59/pop-to-ECX
- 957     # . epilog
- 958     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 959     5d/pop-to-EBP
- 960     c3/return
- 961 
- 962 $_append-4:abort:
- 963     # . _write(2/stderr, error)
- 964     # . . push args
- 965     68/push  "stream overflow\n"/imm32
- 966     68/push  2/imm32/stderr
- 967     # . . call
- 968     e8/call  _write/disp32
- 969     # . . discard args
- 970     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 971     # . syscall(exit, 1)
- 972     bb/copy-to-EBX  1/imm32
- 973     b8/copy-to-EAX  1/imm32/exit
- 974     cd/syscall  0x80/imm8
- 975     # never gets here
- 976 
- 977 == data
- 978 
- 979 _test-stream-line-ABABA:
- 980     # write
- 981     8/imm32
- 982     # read
- 983     0/imm32
- 984     # length
- 985     8/imm32
- 986     # data
- 987     41 42 41 42 41 0a 00 00  # 8 bytes
- 988 
- 989 _test-stream-empty:
- 990     # write
- 991     0/imm32
- 992     # read
- 993     0/imm32
- 994     # length
- 995     8/imm32
- 996     # data
- 997     00 00 00 00 00 00 00 00  # 8 bytes
- 998 
- 999 _test-stream-filled:
-1000     # write
-1001     8/imm32
-1002     # read
-1003     0/imm32
-1004     # length
-1005     8/imm32
-1006     # data
-1007     41 41 41 41 0a 41 41 41  # 8 bytes
-1008 
-1009 # . . vim:nowrap:textwidth=0
-
- - - -- cgit 1.4.1-2-gfad0