https://github.com/akkartik/mu/blob/master/subx/058stream-equal.subx
  1 # some primitives for checking stream contents
  2 
  3 == code
  4 #   instruction                     effective address                                                   register    displacement    immediate
  5 # . op          subop               mod             rm32          base        index         scale       r32
  6 # . 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
  7 
  8 # compare all the data in a stream (ignoring the read pointer)
  9 stream-data-equal?:  # f : (address stream), s : (address string) -> EAX : boolean
 10     # . prolog
 11     55/push-EBP
 12     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
 13     # . save registers
 14     51/push-ECX
 15     52/push-EDX
 16     56/push-ESI
 17     57/push-EDI
 18     # ESI = f
 19     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
 20     # EAX = f->write
 21     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/EAX   .               .                 # copy *ESI to EAX
 22     # maxf/EDX = f->data + f->write
 23     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  0/index/EAX   .           2/r32/EDX   0xc/disp8       .                 # copy ESI+EAX+12 to EDX
 24     # currf/ESI = f->data
 25     81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               0xc/imm32         # add to ESI
 26     # EDI = s
 27     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0xc/disp8       .                 # copy *(EBP+12) to EDI
 28     # if (f->write != s->length) return false
 29 $stream-data-equal?:compare-lengths:
 30     39/compare                      0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # compare *EDI and EAX
 31     75/jump-if-not-equal  $stream-data-equal?:false/disp8
 32     # currs/EDI = s->data
 33     81          0/subop/add         3/mod/direct    7/rm32/EDI    .           .             .           .           .               4/imm32           # add to EDI
 34     # EAX = ECX = 0
 35     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
 36     31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
 37 $stream-data-equal?:loop:
 38     # if (currf >= maxf) return true
 39     39/compare                      3/mod/direct    6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # compare ESI with EDX
 40     73/jump-if-greater-or-equal-unsigned  $stream-data-equal?:true/disp8
 41     # AL = *currs
 42     8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/AL    .               .                 # copy byte at *ESI to AL
 43     # CL = *curr
 44     8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/CL    .               .                 # copy byte at *EDI to CL
 45     # if (EAX != ECX) return false
 46     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX and ECX
 47     75/jump-if-not-equal  $stream-data-equal?:false/disp8
 48     # ++f
 49     46/increment-ESI
 50     # ++curr
 51     47/increment-EDI
 52     eb/jump $stream-data-equal?:loop/disp8
 53 $stream-data-equal?:false:
 54     b8/copy-to-EAX  0/imm32
 55     eb/jump  $stream-data-equal?:end/disp8
 56 $stream-data-equal?:true:
 57     b8/copy-to-EAX  1/imm32
 58 $stream-data-equal?:end:
 59     # . restore registers
 60     5f/pop-to-EDI
 61     5e/pop-to-ESI
 62     5a/pop-to-EDX
 63     59/pop-to-ECX
 64     # . epilog
 65     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
 66     5d/pop-to-EBP
 67     c3/return
 68 
 69 test-stream-data-equal:
 70     # . prolog
 71     55/push-EBP
 72     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
 73     # clear-stream(_test-stream)
 74     # . . push args
 75     68/push  _test-stream/imm32
 76     # . . call
 77     e8/call  clear-stream/disp32
 78     # . . discard args
 79     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
 80     # write(_test-stream, "Abc")
 81     # . . push args
 82     68/push  "Abc"/imm32
 83     68/push  _test-stream/imm32
 84     # . . call
 85     e8/call  write/disp32
 86     # . . discard args
 87     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
 88     # EAX = stream-data-equal?(_test-stream, "Abc")
 89     # . . push args
 90     68/push  "Abc"/imm32
 91     68/push  _test-stream/imm32
 92     # . . call
 93     e8/call  stream-data-equal?/disp32
 94     # . . discard args
 95     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
 96     # check-ints-equal(EAX, 1, msg)
 97     # . . push args
 98     68/push  "F - test-stream-data-equal"/imm32
 99     68/push  1/imm32
100     50/push-EAX
101     # . . call
102     e8/call  check-ints-equal/disp32
103     # . . discard args
104     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
105     # . epilog
106     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
107     5d/pop-to-EBP
108     c3/return
109 
110 test-stream-data-equal-2:
111     # . prolog
112     55/push-EBP
113     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
114     # clear-stream(_test-stream)
115     # . . push args
116     68/push  _test-stream/imm32
117     # . . call
118     e8/call  clear-stream/disp32
119     # . . discard args
120     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
121     # write(_test-stream, "Abc")
122     # . . push args
123     68/push  "Abc"/imm32
124     68/push  _test-stream/imm32
125     # . . call
126     e8/call  write/disp32
127     # . . discard args
128     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
129     # EAX = stream-data-equal?(_test-stream, "Abd")
130     # . . push args
131     68/push  "Abd"/imm32
132     68/push  _test-stream/imm32
133     # . . call
134     e8/call  stream-data-equal?/disp32
135     # . . discard args
136     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
137     # check-ints-equal(EAX, 0, msg)
138     # . . push args
139     68/push  "F - test-stream-data-equal-2"/imm32
140     68/push  0/imm32
141     50/push-EAX
142     # . . call
143     e8/call  check-ints-equal/disp32
144     # . . discard args
145     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
146     # . epilog
147     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
148     5d/pop-to-EBP
149     c3/return
150 
151 test-stream-data-equal-length-check:
152     # . prolog
153     55/push-EBP
154     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
155     # clear-stream(_test-stream)
156     # . . push args
157     68/push  _test-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     # write(_test-stream, "Abc")
163     # . . push args
164     68/push  "Abc"/imm32
165     68/push  _test-stream/imm32
166     # . . call
167     e8/call  write/disp32
168     # . . discard args
169     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
170     # EAX = stream-data-equal?(_test-stream, "Abcd")
171     # . . push args
172     68/push  "Abcd"/imm32
173     68/push  _test-stream/imm32
174     # . . call
175     e8/call  stream-data-equal?/disp32
176     # . . discard args
177     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
178     # check-ints-equal(EAX, 0, msg)
179     # . . push args
180     68/push  "F - test-stream-data-equal-length-check"/imm32
181     68/push  0/imm32
182     50/push-EAX
183     # . . call
184     e8/call  check-ints-equal/disp32
185     # . . discard args
186     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
187     # . epilog
188     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
189     5d/pop-to-EBP
190     c3/return
191 
192 # helper for later tests
193 check-stream-equal:  # f : (address stream), s : (address string), msg : (address string)
194     # . prolog
195     55/push-EBP
196     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
197     # . save registers
198     50/push-EAX
199     # EAX = stream-data-equal?(f, s)
200     # . . push args
201     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
202     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
203     # . . call
204     e8/call  stream-data-equal?/disp32
205     # . . discard args
206     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
207     # check-ints-equal(EAX, 1, msg)
208     # . . push args
209     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
210     68/push  1/imm32
211     50/push-EAX
212     # . . call
213     e8/call  check-ints-equal/disp32
214     # . . discard args
215     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
216 $check-stream-equal:end:
217     # . restore registers
218     58/pop-to-EAX
219     # . epilog
220     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
221     5d/pop-to-EBP
222     c3/return
223 
224 # scan the next line until newline starting from f->read and compare it with
225 # 's' (ignoring the trailing newline)
226 # on success, set f->read to after the next newline
227 # on failure, leave f->read unmodified
228 # this function is usually used only in tests, so we repeatedly write f->read
229 next-stream-line-equal?:  # f : (address stream), s : (address string) -> EAX : boolean
230     # pseudocode:
231     #   currf = f->read  # bound: f->write
232     #   currs = 0  # bound : s->length
233     #   while true
234     #     if currf >= f->write
235     #       return currs >= s->length
236     #     if f[currf] == '\n'
237     #       ++currf
238     #       return currs >= s->length
239     #     if (currs >= s->length) return false  # the current line of f still has data to match
240     #     if (f[currf] != s[currs]) return false
241     #     ++currf
242     #     ++currs
243     #
244     # collapsing the two branches that can return true:
245     #   currf = f->read  # bound: f->write
246     #   currs = 0  # bound : s->length
247     #   while true
248     #     if (currf >= f->write) break
249     #     if (f[currf] == '\n') break
250     #     if (currs >= s->length) return false  # the current line of f still has data to match
251     #     if (f[currf] != s[currs]) return false
252     #     ++currf
253     #     ++currs
254     #   ++currf  # skip '\n'
255     #   return currs >= s->length
256     # Here the final `++currf` is sometimes unnecessary (if we're already at the end of the stream)
257     #
258     # registers:
259     #   f: ESI
260     #   s: EDI
261     #   currf: ECX
262     #   currs: EDX
263     #   f[currf]: EAX
264     #   s[currs]: EBX
265     #
266     # . prolog
267     55/push-EBP
268     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
269     # . save registers
270     51/push-ECX
271     52/push-EDX
272     56/push-ESI
273     57/push-EDI
274     # ESI = f
275     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
276     # currf/ECX = f->read
277     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
278     # EDI = s
279     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0xc/disp8       .                 # copy *(EBP+12) to EDI
280     # currs/EDX = 0
281     31/xor                          3/mod/direct    2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # clear EDX
282     # EAX = EBX = 0
283     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
284     31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
285 $next-stream-line-equal?:loop:
286     # if (currf >= f->write) break
287     3b/compare                      0/mod/indirect  6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # compare ECX with *ESI
288     7d/jump-if-greater-or-equal  $next-stream-line-equal?:break/disp8
289     # AL = *(f->data + f->read)
290     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
291     # if (EAX == '\n') break
292     3d/compare-EAX-and  0xa/imm32/newline
293     74/jump-if-equal  $next-stream-line-equal?:break/disp8
294     # if (currs >= s->length) return false
295     3b/compare                      0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # compare EDX with *EDI
296     7d/jump-if-greater-or-equal  $next-stream-line-equal?:false/disp8
297     # BL = *(s->data + currs)
298     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    7/base/EDI  2/index/EDX   .           3/r32/BL    4/disp8         .                 # copy byte at *(EDI+EDX+4) to BL
299     # if (EAX != EBX) return false
300     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
301     75/jump-if-not-equal  $next-stream-line-equal?:false/disp8
302     # ++currf
303     41/increment-ECX
304     # ++currs
305     42/increment-EDX
306     eb/jump $next-stream-line-equal?:loop/disp8
307 $next-stream-line-equal?:break:
308     # ++currf
309     41/increment-ECX
310     # if (currs >= s->length) return true
311     3b/compare                      0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # compare EDX with *EDI
312     7c/jump-if-lesser  $next-stream-line-equal?:false/disp8
313 $next-stream-line-equal?:true:
314     b8/copy-to-EAX  1/imm32
315     # persist f->read on success
316     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
317     eb/jump  $next-stream-line-equal?:end/disp8
318 $next-stream-line-equal?:false:
319     b8/copy-to-EAX  0/imm32
320 $next-stream-line-equal?:end:
321     # . restore registers
322     5f/pop-to-EDI
323     5e/pop-to-ESI
324     5a/pop-to-EDX
325     59/pop-to-ECX
326     # . epilog
327     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
328     5d/pop-to-EBP
329     c3/return
330 
331 test-next-stream-line-equal-stops-at-newline:
332     # . prolog
333     55/push-EBP
334     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
335     # clear-stream(_test-stream)
336     # . . push args
337     68/push  _test-stream/imm32
338     # . . call
339     e8/call  clear-stream/disp32
340     # . . discard args
341     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
342     # write(_test-stream, "Abc\ndef")
343     # . . push args
344     68/push  "Abc\ndef"/imm32
345     68/push  _test-stream/imm32
346     # . . call
347     e8/call  write/disp32
348     # . . discard args
349     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
350     # EAX = next-stream-line-equal?(_test-stream, "Abc")
351     # . . push args
352     68/push  "Abc"/imm32
353     68/push  _test-stream/imm32
354     # . . call
355     e8/call  next-stream-line-equal?/disp32
356     # . . discard args
357     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
358     # check-ints-equal(EAX, 1, msg)
359     # . . push args
360     68/push  "F - test-next-stream-line-equal-stops-at-newline"/imm32
361     68/push  1/imm32
362     50/push-EAX
363     # . . call
364     e8/call  check-ints-equal/disp32
365     # . . discard args
366     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
367     # . epilog
368     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
369     5d/pop-to-EBP
370     c3/return
371 
372 test-next-stream-line-equal-stops-at-newline-2:
373     # . prolog
374     55/push-EBP
375     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
376     # clear-stream(_test-stream)
377     # . . push args
378     68/push  _test-stream/imm32
379     # . . call
380     e8/call  clear-stream/disp32
381     # . . discard args
382     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
383     # write(_test-stream, "Abc\ndef")
384     # . . push args
385     68/push  "Abc\ndef"/imm32
386     68/push  _test-stream/imm32
387     # . . call
388     e8/call  write/disp32
389     # . . discard args
390     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
391     # EAX = next-stream-line-equal?(_test-stream, "def")
392     # . . push args
393     68/push  "def"/imm32
394     68/push  _test-stream/imm32
395     # . . call
396     e8/call  next-stream-line-equal?/disp32
397     # . . discard args
398     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
399     # check-ints-equal(EAX, 0, msg)
400     # . . push args
401     68/push  "F - test-next-stream-line-equal-stops-at-newline-2"/imm32
402     68/push  0/imm32
403     50/push-EAX
404     # . . call
405     e8/call  check-ints-equal/disp32
406     # . . discard args
407     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
408     # . epilog
409     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
410     5d/pop-to-EBP
411     c3/return
412 
413 test-next-stream-line-equal-skips-newline:
414     # . prolog
415     55/push-EBP
416     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
417     # clear-stream(_test-stream)
418     # . . push args
419     68/push  _test-stream/imm32
420     # . . call
421     e8/call  clear-stream/disp32
422     # . . discard args
423     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
424     # write(_test-stream, "Abc\ndef\n")
425     # . . push args
426     68/push  "Abc\ndef\n"/imm32
427     68/push  _test-stream/imm32
428     # . . call
429     e8/call  write/disp32
430     # . . discard args
431     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
432     # next-stream-line-equal?(_test-stream, "Abc")
433     # . . push args
434     68/push  "Abc"/imm32
435     68/push  _test-stream/imm32
436     # . . call
437     e8/call  next-stream-line-equal?/disp32
438     # . . discard args
439     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
440     # EAX = next-stream-line-equal?(_test-stream, "def")
441     # . . push args
442     68/push  "def"/imm32
443     68/push  _test-stream/imm32
444     # . . call
445     e8/call  next-stream-line-equal?/disp32
446     # . . discard args
447     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
448     # check-ints-equal(EAX, 1, msg)
449     # . . push args
450     68/push  "F - test-next-stream-line-equal-skips-newline"/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     # . epilog
458     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
459     5d/pop-to-EBP
460     c3/return
461 
462 test-next-stream-line-equal-handles-final-line:
463     # . prolog
464     55/push-EBP
465     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
466     # clear-stream(_test-stream)
467     # . . push args
468     68/push  _test-stream/imm32
469     # . . call
470     e8/call  clear-stream/disp32
471     # . . discard args
472     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
473     # write(_test-stream, "Abc\ndef")
474     # . . push args
475     68/push  "Abc\ndef"/imm32
476     68/push  _test-stream/imm32
477     # . . call
478     e8/call  write/disp32
479     # . . discard args
480     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
481     # next-stream-line-equal?(_test-stream, "Abc")
482     # . . push args
483     68/push  "Abc"/imm32
484     68/push  _test-stream/imm32
485     # . . call
486     e8/call  next-stream-line-equal?/disp32
487     # . . discard args
488     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
489     # EAX = next-stream-line-equal?(_test-stream, "def")
490     # . . push args
491     68/push  "def"/imm32
492     68/push  _test-stream/imm32
493     # . . call
494     e8/call  next-stream-line-equal?/disp32
495     # . . discard args
496     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
497     # check-ints-equal(EAX, 1, msg)
498     # . . push args
499     68/push  "F - test-next-stream-line-equal-skips-newline"/imm32
500     68/push  1/imm32
501     50/push-EAX
502     # . . call
503     e8/call  check-ints-equal/disp32
504     # . . discard args
505     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
506     # . epilog
507     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
508     5d/pop-to-EBP
509     c3/return
510 
511 test-next-stream-line-equal-always-fails-after-Eof:
512     # . prolog
513     55/push-EBP
514     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
515     # clear-stream(_test-stream)
516     # . . push args
517     68/push  _test-stream/imm32
518     # . . call
519     e8/call  clear-stream/disp32
520     # . . discard args
521     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
522     # write nothing
523     # EAX = next-stream-line-equal?(_test-stream, "")
524     # . . push args
525     68/push  ""/imm32
526     68/push  _test-stream/imm32
527     # . . call
528     e8/call  next-stream-line-equal?/disp32
529     # . . discard args
530     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
531     # check-ints-equal(EAX, 0, msg)
532     # . . push args
533     68/push  "F - test-next-stream-line-equal-always-fails-after-Eof"/imm32
534     68/push  1/imm32
535     50/push-EAX
536     # . . call
537     e8/call  check-ints-equal/disp32
538     # . . discard args
539     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
540     # EAX = next-stream-line-equal?(_test-stream, "")
541     # . . push args
542     68/push  ""/imm32
543     68/push  _test-stream/imm32
544     # . . call
545     e8/call  next-stream-line-equal?/disp32
546     # . . discard args
547     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
548     # check-ints-equal(EAX, 0, msg)
549     # . . push args
550     68/push  "F - test-next-stream-line-equal-always-fails-after-Eof/2"/imm32
551     68/push  1/imm32
552     50/push-EAX
553     # . . call
554     e8/call  check-ints-equal/disp32
555     # . . discard args
556     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
557     # . epilog
558     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
559     5d/pop-to-EBP
560     c3/return
561 
562 # helper for later tests
563 check-next-stream-line-equal:
564     # . prolog
565     55/push-EBP
566     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
567     # . save registers
568     50/push-EAX
569     # EAX = next-stream-line-equal?(f, s)
570     # . . push args
571     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
572     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
573     # . . call
574     e8/call  next-stream-line-equal?/disp32
575     # . . discard args
576     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
577     # check-ints-equal(EAX, 1, msg)
578     # . . push args
579     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
580     68/push  1/imm32
581     50/push-EAX
582     # . . call
583     e8/call  check-ints-equal/disp32
584     # . . discard args
585     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
586     # . restore registers
587     58/pop-to-EAX
588     # . epilog
589     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
590     5d/pop-to-EBP
591     c3/return
592 
593 # . . vim:nowrap:textwidth=0