about summary refs log tree commit diff stats
path: root/html/mutable.mu.html
Commit message (Expand)AuthorAgeFilesLines
* 4814Kartik Agaram2018-12-011-9/+12
* 4539Kartik Agaram2018-09-071-3/+3
* 4239Kartik Agaram2018-05-081-3/+3
* 4200Kartik K. Agaram2018-01-271-3/+3
* 4199Kartik K. Agaram2018-01-251-6/+6
* 4161Kartik K. Agaram2017-12-151-4/+4
* 4134 - 'input' = 'ingredient'Kartik K. Agaram2017-12-031-1/+1
* 3764 - better colors for cross-linksKartik K. Agaram2017-03-081-3/+4
* 3761Kartik K. Agaram2017-03-071-1/+1
* 3725Kartik K. Agaram2016-12-271-3/+3
* 3716Kartik K. Agaram2016-12-261-0/+2
* 3710Kartik K. Agaram2016-12-261-13/+13
* 3709 - line numbers in htmlKartik K. Agaram2016-12-261-16/+40
* 3569Kartik K. Agaram2016-10-231-2/+2
* 3431Kartik K. Agaram2016-09-301-1/+1
* 3395Kartik K. Agaram2016-09-171-2/+2
* 3318Kartik K. Agaram2016-09-101-0/+47
6' href='#n166'>166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220



























































































































































































































                                                                                                                                                                                      
# write-buffered: like 'write', but for a buffered-file

== code
#   instruction                     effective address                                                   register    displacement    immediate
# . op          subop               mod             rm32          base        index         scale       r32
# . 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

# main:
#?     e8/call test-write-buffered/disp32
#?     e8/call test-write-buffered-with-intermediate-flush/disp32
    e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
    # syscall(exit, Num-test-failures)
    8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
    b8/copy-to-EAX  1/imm32
    cd/syscall  0x80/imm8

write-buffered:  # f : (address buffered-file), msg : (address array byte) -> <void>
    # pseudocode:
    #   in = msg->data
    #   inend = &msg->data[msg->length]
    #   while in < inend
    #     if f->write >= f->length
    #       flush(f)
    #       clear-stream(f)
    #     f->data[f->write] = *in
    #     ++f->write
    #     ++in
    #
    # registers:
    #   ESI : in
    #   ECX : inend
    #   EDI : f
    #   EDX : f->length
    #   EBX : f->write (cached copy, need to keep in sync)
    #   EAX : temp
    #
    # . prolog
    55/push-EBP
    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    # . save registers
    50/push-EAX
    51/push-ECX
    52/push-EDX
    53/push-EBX
    56/push-ESI
    57/push-EDI
    # EAX = msg
    8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none              0/r32/EAX   0xc/disp8       .                 # copy *(EBP+12) to EAX
    # in/ESI = msg->data
    8d/copy-address                 1/mod/*+disp8   0/rm32/EAX    .           .             .           6/r32/ESI   4/disp8         .                 # copy EAX+4 to ESI
    # inend/ECX = &msg->data[msg->length]
    8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
    8d/copy-address                 0/mod/indirect  4/rm32/sib    6/base/ESI  1/index/ECX   .           1/r32/ECX   .               .                 # copy ESI+ECX to ECX
    # EDI = f
    8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none              7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
    # EDX = f->length
    8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EDI+12) to EDX
    # EBX = f->write
    8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy *(EDI+4) to EBX
$write-buffered:loop:
    # if (in >= inend) break
    39/compare                      3/mod/direct    6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # compare ESI with ECX
    7d/jump-if-greater-or-equal  $write-buffered:loop-end/disp8
    # if (f->write >= f->length) flush and clear f's stream
    39/compare                      3/mod/direct    3/rm32/EBX    .           .             .           2/r32/EDX   .               .                 # compare EBX with EDX
    7c/jump-if-lesser  $write-buffered:to-stream/disp8
    # . persist f->write
    89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy EBX to *(EDI+4)
    # . flush(f)
    # . . push args
    57/push-EDI
    # . . call
    e8/call  flush/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # . clear-stream(stream = f+4)
    # . . push args
    8d/copy-address                 1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EDI+4 to EAX
    50/push-EAX
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # . clear EBX (cached f->write)
    31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
$write-buffered:to-stream:
    # write to stream
    # f->data[f->write] = *in
    # . AL = *in
    31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
    8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/AL    .               .                 # copy byte at *ESI to AL
    # . f->data[f->write] = AL
    88/copy-byte                    1/mod/*+disp8   4/rm32/sib    7/base/EDI  3/index/EBX   .           0/r32/AL    0x10/disp8      .                 # copy AL to *(EDI+EBX+16)
    # ++f->write
    43/increment-EBX
    # ++in
    46/increment-ESI
    eb/jump  $write-buffered:loop/disp8
$write-buffered:loop-end:
    # persist necessary variables from registers
    89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy EBX to *(EDI+4)
$write-buffered:end:
    # . restore registers
    5f/pop-to-EDI
    5e/pop-to-ESI
    5b/pop-to-EBX
    5a/pop-to-EDX
    59/pop-to-ECX
    58/pop-to-EAX
    # . epilog
    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    5d/pop-to-EBP
    c3/return

test-write-buffered:
    # - check that write-buffered writes to the file
    # setup
    # . clear-stream(_test-stream)
    # . . push args
    68/push  _test-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # . clear-stream(_test-buffered-file+4)
    # . . push args
    b8/copy-to-EAX  _test-buffered-file/imm32
    05/add-to-EAX  4/imm32
    50/push-EAX
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # write-buffered(_test-buffered-file, "Abc")
    # . . push args
    68/push  "Abc"/imm32
    68/push  _test-buffered-file/imm32
    # . . call
    e8/call  write-buffered/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # flush(_test-buffered-file)
    # . . push args
    68/push  _test-buffered-file/imm32
    # . . call
    e8/call  flush/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # check-ints-equal(*_test-stream->data, "Abc", msg)
    # . . push args
    68/push  "F - test-write-buffered-single"/imm32
    68/push  0x636241/imm32
    # . . push *_test-stream->data
    b8/copy-to-EAX  _test-stream/imm32
    ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           0xc/disp8       .                 # push *(EAX+12)
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    # . end
    c3/return

test-write-buffered-with-intermediate-flush:
    # - check that write-buffered flushes in the middle if its buffer fills up
    # setup
    # . clear-stream(_test-stream)
    # . . push args
    68/push  _test-stream/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # . clear-stream(_test-buffered-file+4)
    # . . push args
    b8/copy-to-EAX  _test-buffered-file/imm32
    05/add-to-EAX  4/imm32
    50/push-EAX
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # _test-stream can hold 8 bytes, but _test-buffered-file can hold only 6.
    # Try to write 7 bytes.
    # . write-buffered(_test-buffered-file, "Abcdefg")
    # . . push args
    68/push  "Abcdefg"/imm32
    68/push  _test-buffered-file/imm32
    # . . call
    e8/call  write-buffered/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # don't flush
    # 6 bytes should still have gotten to _test-stream
    # . check-ints-equal(*_test-stream->write, 6, msg)
    # . . push args
    68/push  "F - test-write-buffered-with-intermediate-flush: flushed data"/imm32
    68/push  6/imm32
    # . . push *_test-stream->write
    b8/copy-to-EAX  _test-stream/imm32
    ff          6/subop/push        0/mod/indirect  0/rm32/EAX    .           .             .           .           .               .                 # push *EAX
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    # and 1 byte should still be in _test-buffered-file
    # . check-ints-equal(*_test-buffered-file>write, 1, msg)
    # . . push args
    68/push  "F - test-write-buffered-with-intermediate-flush: unflushed bytes"/imm32
    68/push  1/imm32
    # . . push *_test-buffered-file->write
    b8/copy-to-EAX  _test-buffered-file/imm32
    ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    # . end
    c3/return

# . . vim:nowrap:textwidth=0