From 6e181e7fd998a0d542cb531c929c905a243ea2f6 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 5 Feb 2019 23:30:12 -0800 Subject: 4953 --- html/subx/071read-line.subx.html | 373 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 html/subx/071read-line.subx.html (limited to 'html/subx/071read-line.subx.html') diff --git a/html/subx/071read-line.subx.html b/html/subx/071read-line.subx.html new file mode 100644 index 00000000..cae91e35 --- /dev/null +++ b/html/subx/071read-line.subx.html @@ -0,0 +1,373 @@ + + + + +Mu - subx/071read-line.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/071read-line.subx +
+  1 == code
+  2 #   instruction                     effective address                                                   register    displacement    immediate
+  3 # . op          subop               mod             rm32          base        index         scale       r32
+  4 # . 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
+  5 
+  6 # main:
+  7     e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
+  8     # syscall(exit, Num-test-failures)
+  9     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+ 10     b8/copy-to-EAX  1/imm32/exit
+ 11     cd/syscall  0x80/imm8
+ 12 
+ 13 # read bytes from 'f' until (and including) a newline and store them into 's'
+ 14 # return true if no data found, false otherwise
+ 15 # just abort if 's' is too small
+ 16 read-line:  # f : (address buffered-file), s : (address stream byte) -> eof?/EAX
+ 17     # pseudocode:
+ 18     #   loop:
+ 19     #     if (s->write >= s->length) abort
+ 20     #     if (f->read >= f->write) populate stream from file
+ 21     #     if (f->write == 0) break
+ 22     #     AL = f->data[f->read]
+ 23     #     s->data[s->write] = AL
+ 24     #     ++f->read
+ 25     #     ++s->write
+ 26     #     if AL == '\n' break
+ 27     # . prolog
+ 28     55/push-EBP
+ 29     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 30     # . save registers
+ 31     51/push-ECX
+ 32     52/push-EDX
+ 33     56/push-ESI
+ 34     57/push-EDI
+ 35     # ESI = f
+ 36     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+ 37     # ECX = f->read
+ 38     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(ESI+8) to ECX
+ 39     # EDI = s
+ 40     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0xc/disp8       .                 # copy *(EBP+12) to EDI
+ 41     # EDX = s->write
+ 42     8b/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # copy *EDI to EDX
+ 43 $read-line:loop:
+ 44     # if (s->write >= s->length) abort
+ 45     3b/compare                      1/mod/*+disp8   7/rm32/EDI    .           .             .           2/r32/EDX   8/disp8         .                 # compare EDX with *(EDI+8)
+ 46     7d/jump-if-greater-or-equal  $read-line:abort/disp8
+ 47     # if (f->read >= f->write) populate stream from file
+ 48     3b/compare                      1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # compare ECX with *(ESI+4)
+ 49     7c/jump-if-lesser  $read-line:from-stream/disp8
+ 50     # . clear-stream(stream = f+4)
+ 51     # . . push args
+ 52     8d/copy-address                 1/mod/*+disp8   6/rm32/ESI    .           .             .           0/r32/EAX   4/disp8         .                 # copy ESI+4 to EAX
+ 53     50/push-EAX
+ 54     # . . call
+ 55     e8/call  clear-stream/disp32
+ 56     # . . discard args
+ 57     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 58     # . f->read must now be 0; update its cache at ECX
+ 59     31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
+ 60     # . EAX = read(f->fd, stream = f+4)
+ 61     # . . push args
+ 62     50/push-EAX
+ 63     ff          6/subop/push        0/mod/indirect  6/rm32/ESI    .           .             .           .           .               .                 # push *ESI
+ 64     # . . call
+ 65     e8/call  read/disp32
+ 66     # . . discard args
+ 67     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 68     # if f->write == 0 return true
+ 69     # . if EAX == 0 return true
+ 70     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # compare EAX
+ 71     75/jump-if-not-equal  $read-line:from-stream/disp8
+ 72     b8/copy-to-EAX  0xffffffff/imm32
+ 73     eb/jump  $read-line:end/disp8
+ 74 $read-line:from-stream:
+ 75     # AL = f->data[f->read]
+ 76     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+ 77     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0x10/disp8      .                 # copy byte at *(ESI+ECX+16) to AL
+ 78     # s->data[s->write] = AL
+ 79     88/copy-byte                    1/mod/*+disp8   4/rm32/sib    7/base/EDI  2/index/EDX   .           0/r32/AL    0xc/disp8       .                 # copy AL to *(EDI+EDX+12)
+ 80     # ++f->read
+ 81     41/increment-ECX
+ 82     # ++s->write
+ 83     42/increment-EDX
+ 84     # if AL == '\n' return false
+ 85     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xa/imm32         # compare EAX
+ 86     75/jump-if-not-equal  $read-line:loop/disp8
+ 87     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+ 88 $read-line:end:
+ 89     # save f->read
+ 90     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   8/disp8         .                 # copy ECX to *(ESI+8)
+ 91     # save s->write
+ 92     89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # copy EDX to *EDI
+ 93     # . restore registers
+ 94     5f/pop-to-EDI
+ 95     5e/pop-to-ESI
+ 96     5a/pop-to-EDX
+ 97     59/pop-to-ECX
+ 98     # . epilog
+ 99     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+100     5d/pop-to-EBP
+101     c3/return
+102 
+103 $read-line:abort:
+104     # . _write(2/stderr, error)
+105     # . . push args
+106     68/push  "read-line: line too long"/imm32
+107     68/push  2/imm32/stderr
+108     # . . call
+109     e8/call  _write/disp32
+110     # . . discard args
+111     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+112     # . syscall(exit, 1)
+113     bb/copy-to-EBX  1/imm32
+114     b8/copy-to-EAX  1/imm32/exit
+115     cd/syscall  0x80/imm8
+116     # never gets here
+117 
+118 test-read-line:
+119     # - check that read-line stops at a newline
+120     # setup
+121     # . clear-stream(_test-stream)
+122     # . . push args
+123     68/push  _test-stream/imm32
+124     # . . call
+125     e8/call  clear-stream/disp32
+126     # . . discard args
+127     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+128     # . clear-stream(_test-buffered-file+4)
+129     # . . push args
+130     b8/copy-to-EAX  _test-buffered-file/imm32
+131     05/add-to-EAX  4/imm32
+132     50/push-EAX
+133     # . . call
+134     e8/call  clear-stream/disp32
+135     # . . discard args
+136     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+137     # . clear-stream(_test-stream-buffer)
+138     # . . push args
+139     68/push  _test-stream-buffer/imm32
+140     # . . call
+141     e8/call  clear-stream/disp32
+142     # . . discard args
+143     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+144     # write(_test-stream, "ab\ncd")
+145     # . write(_test-stream, "ab")
+146     # . . push args
+147     68/push  "ab"/imm32
+148     68/push  _test-stream/imm32
+149     # . . call
+150     e8/call  write/disp32
+151     # . . discard args
+152     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+153     # . write(_test-stream, "\n")
+154     # . . push args
+155     68/push Newline/imm32
+156     68/push  _test-stream/imm32
+157     # . . call
+158     e8/call  write/disp32
+159     # . . discard args
+160     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+161     # . write(_test-stream, "cd")
+162     # . . push args
+163     68/push  "cd"/imm32
+164     68/push  _test-stream/imm32
+165     # . . call
+166     e8/call  write/disp32
+167     # . . discard args
+168     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+169     # read a line from _test-stream (buffered by _test-buffered-file) into _test-stream-buffer
+170     # . EAX = read-line(_test-buffered-file, _test-stream-buffer)
+171     # . . push args
+172     68/push  _test-stream-buffer/imm32
+173     68/push  _test-buffered-file/imm32
+174     # . . call
+175     e8/call  read-line/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/not-at-eof, msg)
+179     # . . push args
+180     68/push  "F - test-read-line: return value"/imm32
+181     68/push  0/imm32/not-at-eof
+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     # check-next-stream-line-equal(_test-stream-buffer, "ab", msg)
+188     # . . push args
+189     68/push  "F - test-read-line"/imm32
+190     68/push  "ab"/imm32
+191     68/push  _test-stream-buffer/imm32
+192     # . . call
+193     e8/call  check-next-stream-line-equal/disp32
+194     # . . discard args
+195     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+196     # end
+197     c3/return
+198 
+199 test-read-line-returns-true-on-eof:
+200     # setup
+201     # . clear-stream(_test-stream)
+202     # . . push args
+203     68/push  _test-stream/imm32
+204     # . . call
+205     e8/call  clear-stream/disp32
+206     # . . discard args
+207     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+208     # . clear-stream(_test-buffered-file+4)
+209     # . . push args
+210     b8/copy-to-EAX  _test-buffered-file/imm32
+211     05/add-to-EAX  4/imm32
+212     50/push-EAX
+213     # . . call
+214     e8/call  clear-stream/disp32
+215     # . . discard args
+216     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+217     # . clear-stream(_test-stream-buffer)
+218     # . . push args
+219     68/push  _test-stream-buffer/imm32
+220     # . . call
+221     e8/call  clear-stream/disp32
+222     # . . discard args
+223     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+224     # write nothing
+225     # EAX = read-line(_test-buffered-file, _test-stream-buffer)
+226     # . . push args
+227     68/push  _test-stream-buffer/imm32
+228     68/push  _test-buffered-file/imm32
+229     # . . call
+230     e8/call  read-line/disp32
+231     # . . discard args
+232     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+233     # check-ints-equal(EAX, eof, msg)
+234     # . . push args
+235     68/push  "F - test-read-line-returns-true-on-eof"/imm32
+236     68/push  0xffffffff/imm32/not-at-eof
+237     50/push-EAX
+238     # . . call
+239     e8/call  check-ints-equal/disp32
+240     # . . discard args
+241     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+242     # end
+243     c3/return
+244 
+245 test-read-line-reads-final-line-until-eof:
+246     # setup
+247     # . clear-stream(_test-stream)
+248     # . . push args
+249     68/push  _test-stream/imm32
+250     # . . call
+251     e8/call  clear-stream/disp32
+252     # . . discard args
+253     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+254     # . clear-stream(_test-buffered-file+4)
+255     # . . push args
+256     b8/copy-to-EAX  _test-buffered-file/imm32
+257     05/add-to-EAX  4/imm32
+258     50/push-EAX
+259     # . . call
+260     e8/call  clear-stream/disp32
+261     # . . discard args
+262     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+263     # . clear-stream(_test-stream-buffer)
+264     # . . push args
+265     68/push  _test-stream-buffer/imm32
+266     # . . call
+267     e8/call  clear-stream/disp32
+268     # . . discard args
+269     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+270     # write(_test-stream, "cd")
+271     # . . push args
+272     68/push  "cd"/imm32
+273     68/push  _test-stream/imm32
+274     # . . call
+275     e8/call  write/disp32
+276     # . . discard args
+277     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+278     # read a line from _test-stream (buffered by _test-buffered-file) into _test-stream-buffer
+279     # . EAX = read-line(_test-buffered-file, _test-stream-buffer)
+280     # . . push args
+281     68/push  _test-stream-buffer/imm32
+282     68/push  _test-buffered-file/imm32
+283     # . . call
+284     e8/call  read-line/disp32
+285     # . . discard args
+286     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+287     # check-ints-equal(EAX, eof, msg)
+288     # . . push args
+289     68/push  "F - test-read-line-reads-final-line-until-eof: return value"/imm32
+290     68/push  0xffffffff/imm32/not-at-eof
+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-stream-equal(_test-stream-buffer, "cd", msg)
+297     # . . push args
+298     68/push  "F - test-read-line-reads-final-line-until-eof"/imm32
+299     68/push  "cd"/imm32
+300     68/push  _test-stream-buffer/imm32
+301     # . . call
+302     e8/call  check-stream-equal/disp32
+303     # . . discard args
+304     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+305     # end
+306     c3/return
+307 
+308 # . . vim:nowrap:textwidth=0
+
+ + + -- cgit 1.4.1-2-gfad0