about summary refs log tree commit diff stats
path: root/subx/apps/factorial.subx
Commit message (Expand)AuthorAgeFilesLines
* 5037Kartik Agaram2019-03-291-1/+1
* 4981 - no, go back to 3 phasesKartik Agaram2019-02-181-1/+6
* 4961Kartik Agaram2019-02-141-1/+1
* 4933Kartik Agaram2019-01-161-1/+1
* 4931Kartik Agaram2019-01-161-1/+0
* 4893Kartik Agaram2018-12-301-1/+1
* 4888Kartik Agaram2018-12-291-5/+5
* 4881Kartik Agaram2018-12-281-1/+1
* 4847Kartik Agaram2018-12-061-1/+1
* 4819Kartik Agaram2018-12-021-1/+1
* 4812Kartik Agaram2018-11-301-2/+2
* 4808 - clean up comments in all subx filesKartik Agaram2018-11-301-10/+10
* 4802Kartik Agaram2018-11-301-22/+22
* 4801Kartik Agaram2018-11-301-63/+63
* 4731Kartik Agaram2018-10-281-5/+5
* 4703Kartik Agaram2018-10-161-4/+4
* 4700Kartik Agaram2018-10-161-2/+2
* 4684Kartik Agaram2018-10-111-2/+3
* 4670Kartik Agaram2018-10-051-1/+1
* 4668Kartik Agaram2018-10-051-2/+2
* 4667Kartik Agaram2018-10-051-11/+11
* 4663Kartik Agaram2018-10-051-1/+1
* 4662Kartik Agaram2018-10-051-1/+1
* 4655Kartik Agaram2018-10-021-1/+1
* 4653Kartik Agaram2018-10-021-3/+3
* 4651Kartik Agaram2018-10-021-1/+3
* 4644Kartik Agaram2018-10-011-11/+11
* 4641Kartik Agaram2018-10-011-1/+1
* 4638 - extract some common libraries from appsKartik Agaram2018-10-011-321/+1
* 4624Kartik Agaram2018-09-301-1/+1
* 4518Kartik Agaram2018-09-241-8/+41
* 4517Kartik Agaram2018-09-241-5/+5
* 4516Kartik K. Agaram2018-09-241-38/+50
* 4514Kartik Agaram2018-09-241-3/+11
* 4513Kartik Agaram2018-09-241-8/+0
* 4508Kartik Agaram2018-09-231-20/+184
* 4506Kartik Agaram2018-09-231-0/+13
* 4505Kartik Agaram2018-09-231-8/+27
* 4502 - support string literals directly in codeKartik Agaram2018-09-221-14/+2
* 4591Kartik Agaram2018-09-221-19/+19
* 4586 - factorial checks commandline to run testsKartik Agaram2018-09-211-15/+85
* 4581Kartik Agaram2018-09-211-2/+2
* 4567 - support automated tests in SubXKartik Agaram2018-09-211-11/+75
* 4554Kartik Agaram2018-09-201-2/+2
* 4537Kartik Agaram2018-09-071-5/+3
* 4531 - automatically compute segment addressesKartik Agaram2018-09-011-1/+1
* 4530 - create an apps/ directoryKartik Agaram2018-09-011-0/+64
d } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# Write out the (hex) textual representation of numbers.

== 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

# convert the lowest nibble of eax to ascii and return it in the lowest byte of eax
to-hex-char:  # in/eax: int -> out/eax: int
    # no error checking; accepts argument in eax
    # if (eax <= 9) return eax + '0'
    3d/compare-eax-with  0x9/imm32/9
    7f/jump-if->  $to-hex-char:else/disp8
    05/add-to-eax  0x30/imm32/0
    c3/return
$to-hex-char:else:
    # otherwise return eax + 'a' - 10
    05/add-to-eax  0x57/imm32/a-10
    c3/return

append-byte-hex:  # f: (addr stream byte), n: int
    # . prologue
    55/push-ebp
    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
    # . save registers
    50/push-eax
    # AL = convert upper nibble to hex
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   0xc/disp8       .                 # copy *(ebp+12) to eax
    c1/shift    5/subop/logic-right 3/mod/direct    0/rm32/eax    .           .             .           .           .               4/imm8            # shift eax right by 4 bits, while padding zeroes
    25/and-eax  0xf/imm32
    # . AL = to-hex-char(AL)
    e8/call  to-hex-char/disp32
    # append-byte(f, AL)
    # . . push args
    50/push-eax
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  append-byte/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # AL = convert lower nibble to hex
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   0xc/disp8       .                 # copy *(ebp+12) to eax
    25/and-eax  0xf/imm32
    # . AL = to-hex-char(AL)
    e8/call  to-hex-char/disp32
    # append-byte(f, AL)
    # . . push args
    50/push-eax
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  append-byte/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
$append-byte-hex:end:
    # . restore registers
    58/pop-to-eax
    # . epilogue
    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    5d/pop-to-ebp
    c3/return

test-append-byte-hex:
    # - check that append-byte-hex adds the hex textual representation
    # 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
    # append-byte-hex(_test-stream, 0xa)  # exercises digit, non-digit as well as leading zero
    # . . push args
    68/push  0xa/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  append-byte-hex/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # check-stream-equal(_test-stream, "0a", msg)
    # . . push args
    68/push  "F - test-append-byte-hex"/imm32
    68/push  "0a"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
    # . end
    c3/return

# print the hex representation for the lowest byte of a number
write-byte-hex-buffered:  # f: (addr buffered-file), n: int
    # . prologue
    55/push-ebp
    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
    # . save registers
    50/push-eax
    # AL = convert upper nibble to hex
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   0xc/disp8       .                 # copy *(ebp+12) to eax
    c1/shift    5/subop/logic-right 3/mod/direct    0/rm32/eax    .           .             .           .           .               4/imm8            # shift eax right by 4 bits, while padding zeroes
    25/and-eax  0xf/imm32
    # . AL = to-hex-char(AL)
    e8/call  to-hex-char/disp32
    # write-byte-buffered(f, AL)
    # . . push args
    50/push-eax
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  write-byte-buffered/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # AL = convert lower nibble to hex
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   0xc/disp8       .                 # copy *(ebp+12) to eax
    25/and-eax  0xf/imm32
    # . AL = to-hex-char(AL)
    e8/call  to-hex-char/disp32
    # write-byte-buffered(f, AL)
    # . . push args
    50/push-eax
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  write-byte-buffered/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
$write-byte-hex-buffered:end:
    # . restore registers
    58/pop-to-eax
    # . epilogue
    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    5d/pop-to-ebp
    c3/return

test-write-byte-hex-buffered:
    # - check that write-byte-hex-buffered prints the hex textual representation
    # 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->buffer)
    # . . push args
    68/push  $_test-buffered-file->buffer/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
    # write-byte-hex-buffered(_test-buffered-file, 0xa)  # exercises digit, non-digit as well as leading zero
    # . . push args
    68/push  0xa/imm32
    68/push  _test-buffered-file/imm32
    # . . call
    e8/call  write-byte-hex-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-stream-equal(_test-stream, "0a", msg)
    # . . push args
    68/push  "F - test-write-byte-hex-buffered"/imm32
    68/push  "0a"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
    # . end
    c3/return

write-int32-hex:  # f: (addr stream byte), n: int
    # . prologue
    55/push-ebp
    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
$write-int32-hex:hex-prefix:
    # write(f, "0x")
    # . . push args
    68/push  "0x"/imm32
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  write/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
$write-int32-hex:rest:
    # write-int32-hex-bits(f, n, 32)
    # . . push args
    68/push  0x20/imm32
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  write-int32-hex-bits/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
$write-int32-hex:end:
    # . epilogue
    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    5d/pop-to-ebp
    c3/return

# print rightmost 'bits' of 'n'
# bits must be multiple of 4
write-int32-hex-bits:  # f: (addr stream byte), n: int, bits: int
    # pseudocode:
    #  bits -= 4
    #  while true
    #    if (bits < 0) break
    #    eax = n >> bits
    #    eax = eax & 0xf
    #    append-byte(f, AL)
    #    bits -= 4
    #
    # . prologue
    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
    # ecx = bits-4
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0x10/disp8      .                 # copy *(ebp+16) to ecx
    81          5/subop/subtract    3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # subtract from ecx
$write-int32-hex-bits:loop:
    # if (bits < 0) break
    81          7/subop/compare     3/mod/direct    1/rm32/ecx    .           .             .           .           .               0/imm32           # compare ecx
    7c/jump-if-<  $write-int32-hex-bits:end/disp8
    # eax = n >> bits
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   0xc/disp8       .                 # copy *(ebp+12) to eax
    d3/>>ecx    5/subop/pad-zeroes  3/mod/direct    0/rm32/eax    .           .             .           .           .               .                 # shift eax right by ecx bits, padding zeroes
    # eax = to-hex-char(AL)
    25/and-eax  0xf/imm32
    e8/call  to-hex-char/disp32
    # append-byte(f, AL)
    # . . push args
    50/push-eax
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  append-byte/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # bits -= 4
    81          5/subop/subtract    3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # subtract from ecx
    eb/jump  $write-int32-hex-bits:loop/disp8
$write-int32-hex-bits:end:
    # . restore registers
    59/pop-to-ecx
    58/pop-to-eax
    # . epilogue
    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    5d/pop-to-ebp
    c3/return

test-write-int32-hex:
    # - check that write-int32-hex prints the hex textual representation
    # 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
    # write-int32-hex(_test-stream, 0x8899aa)
    # . . push args
    68/push  0x8899aa/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  write-int32-hex/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # check-stream-equal(_test-stream, "0x008899aa", msg)
    # . . push args
    68/push  "F - test-write-int32-hex"/imm32
    68/push  "0x008899aa"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
    # . end
    c3/return

write-int32-hex-buffered:  # f: (addr buffered-file), n: int
    # . prologue
    55/push-ebp
    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
$write-int32-hex-buffered:hex-prefix:
    # write-buffered(f, "0x")
    # . . push args
    68/push  "0x"/imm32
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  write-buffered/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
$write-int32-hex-buffered:rest:
    # write-int32-hex-bits-buffered(f, n, 32)
    # . . push args
    68/push  0x20/imm32
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  write-int32-hex-bits-buffered/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
$write-int32-hex-buffered:end:
    # . epilogue
    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    5d/pop-to-ebp
    c3/return

# print rightmost 'bits' of 'n'
# bits must be multiple of 4
write-int32-hex-bits-buffered:  # f: (addr buffered-file), n: int, bits: int
    # pseudocode:
    #  bits -= 4
    #  while true
    #    if (bits < 0) break
    #    eax = n >> bits
    #    eax = eax & 0xf
    #    write-byte-buffered(f, AL)
    #    bits -= 4
    #
    # . prologue
    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
    # ecx = bits-4
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0x10/disp8      .                 # copy *(ebp+16) to ecx
    81          5/subop/subtract    3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # subtract from ecx
$write-int32-hex-bits-buffered:loop:
    # if (bits < 0) break
    81          7/subop/compare     3/mod/direct    1/rm32/ecx    .           .             .           .           .               0/imm32           # compare ecx
    7c/jump-if-<  $write-int32-hex-bits-buffered:end/disp8
    # eax = n >> bits
    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   0xc/disp8       .                 # copy *(ebp+12) to eax
    d3/>>ecx    5/subop/pad-zeroes  3/mod/direct    0/rm32/eax    .           .             .           .           .               .                 # shift eax right by ecx bits, padding zeroes
    # eax = to-hex-char(AL)
    25/and-eax  0xf/imm32
    e8/call  to-hex-char/disp32
    # write-byte-buffered(f, AL)
    # . . push args
    50/push-eax
    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
    # . . call
    e8/call  write-byte-buffered/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    # bits -= 4
    81          5/subop/subtract    3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # subtract from ecx
    eb/jump  $write-int32-hex-bits-buffered:loop/disp8
$write-int32-hex-bits-buffered:end:
    # . restore registers
    59/pop-to-ecx
    58/pop-to-eax
    # . epilogue
    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    5d/pop-to-ebp
    c3/return

test-write-int32-hex-buffered:
    # - check that write-int32-hex-buffered prints the hex textual representation
    # 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->buffer)
    # . . push args
    68/push  $_test-buffered-file->buffer/imm32
    # . . call
    e8/call  clear-stream/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
    # write-int32-hex-buffered(_test-buffered-file, 0x8899aa)
    # . . push args
    68/push  0x8899aa/imm32
    68/push  _test-buffered-file/imm32
    # . . call
    e8/call  write-int32-hex-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
#?     # dump line {{{
#?     # . write-stream(2/stderr, line)
#?     # . . push args
#?     68/push  _test-stream/imm32
#?     68/push  2/imm32/stderr
#?     # . . call
#?     e8/call  write-stream/disp32
#?     # . . discard args
#?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
#?     # . write(2/stderr, "$\n")
#?     # . . push args
#?     68/push  "$\n"/imm32
#?     68/push  2/imm32/stderr
#?     # . . call
#?     e8/call  write/disp32
#?     # . . discard args
#?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
#?     # }}}
    # check-stream-equal(_test-stream, "0x008899aa", msg)
    # . . push args
    68/push  "F - test-write-int32-hex-buffered"/imm32
    68/push  "0x008899aa"/imm32
    68/push  _test-stream/imm32
    # . . call
    e8/call  check-stream-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