https://github.com/akkartik/mu/blob/master/074print-int-decimal.subx
  1 # Helper to print an int32 in decimal.
  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 print-int32-decimal:  # out : (address stream), n : int32
  9     # works by generating characters from lowest to highest and pushing them
 10     # to the stack, before popping them one by one into the stream
 11     #
 12     # pseudocode:
 13     #   push sentinel
 14     #   eax = abs(n)
 15     #   while true
 16     #     sign-extend eax into edx
 17     #     eax, edx = eax/10, eax%10
 18 pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* 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 */
discard """
  output: '''
@[1, 2, 3, 4]
123
'''
"""

# bug #5314, bug #6626

import asyncdispatch

proc bar(i: int): Future[int] {.async.} =
    await sleepAsync(2)
    result = i

proc foo(): Future[seq[int]] {.async.} =
    await sleepAsync(2)
    result = @[1, 2, await bar(3), 4] # <--- The bug is here

proc foo2() {.async.} =
    await sleepAsync(2)
    echo(await bar(1), await bar(2), await bar(3))

echo waitFor foo()
waitFor foo2()
an> 84 $print-int32-decimal:write-loop: 85 # pop into eax 86 58/pop-to-eax 87 # if (eax == sentinel) break 88 3d/compare-eax-and 0/imm32/sentinel 89 74/jump-if-equal $print-int32-decimal:write-break/disp8 90 # if (curr >= max) abort 91 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx 92 73/jump-if-greater-or-equal-unsigned $print-int32-decimal:abort/disp8 93 $print-int32-decimal:write-char: 94 # *curr = AL 95 88/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy AL to byte at *ecx 96 # ++curr 97 41/increment-ecx 98 # ++w 99 42/increment-edx 100 eb/jump $print-int32-decimal:write-loop/disp8 101 $print-int32-decimal:write-break: 102 # out->write = w 103 89/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy edx to *edi 104 $print-int32-decimal:end: 105 # . restore registers 106 5f/pop-to-edi 107 5b/pop-to-ebx 108 5a/pop-to-edx 109 59/pop-to-ecx 110 58/pop-to-eax 111 # . epilog 112 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 113 5d/pop-to-ebp 114 c3/return 115 116 $print-int32-decimal:abort: 117 # . _write(2/stderr, error) 118 # . . push args 119 68/push "print-int32-decimal: out of space\n"/imm32 120 68/push 2/imm32/stderr 121 # . . call 122 e8/call _write/disp32 123 # . . discard args 124 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 125 # . syscall(exit, 1) 126 bb/copy-to-ebx 1/imm32 127 b8/copy-to-eax 1/imm32/exit 128 cd/syscall 0x80/imm8 129 # never gets here 130 131 test-print-int32-decimal: 132 # - check that a single-digit number converts correctly 133 # setup 134 # . clear-stream(_test-stream) 135 # . . push args 136 68/push _test-stream/imm32 137 # . . call 138 e8/call clear-stream/disp32 139 # . . discard args 140 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 141 # print-int32-decimal(_test-stream, 9) 142 # . . push args 143 68/push 9/imm32 144 68/push _test-stream/imm32 145 # . . call 146 e8/call print-int32-decimal/disp32 147 # . . discard args 148 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 149 # check-stream-equal(_test-stream, "9", msg) 150 # . . push args 151 68/push "F - test-print-int32-decimal"/imm32 152 68/push "9"/imm32 153 68/push _test-stream/imm32 154 # . . call 155 e8/call check-stream-equal/disp32 156 # . . discard args 157 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 158 # . end 159 c3/return 160 161 test-print-int32-decimal-zero: 162 # - check that 0 converts correctly 163 # setup 164 # . clear-stream(_test-stream) 165 # . . push args 166 68/push _test-stream/imm32 167 # . . call 168 e8/call clear-stream/disp32 169 # . . discard args 170 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 171 # print-int32-decimal(_test-stream, 0) 172 # . . push args 173 68/push 0/imm32 174 68/push _test-stream/imm32 175 # . . call 176 e8/call print-int32-decimal/disp32 177 # . . discard args 178 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 179 # check-stream-equal(_test-stream, "0", msg) 180 # . . push args 181 68/push "F - test-print-int32-decimal-zero"/imm32 182 68/push "0"/imm32 183 68/push _test-stream/imm32 184 # . . call 185 e8/call check-stream-equal/disp32 186 # . . discard args 187 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 188 # . end 189 c3/return 190 191 test-print-int32-decimal-multiple-digits: 192 # - check that a multi-digit number converts correctly 193 # setup 194 # . clear-stream(_test-stream) 195 # . . push args 196 68/push _test-stream/imm32 197 # . . call 198 e8/call clear-stream/disp32 199 # . . discard args 200 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 201 # print-int32-decimal(_test-stream, 10) 202 # . . push args 203 68/push 0xa/imm32 204 68/push _test-stream/imm32 205 # . . call 206 e8/call print-int32-decimal/disp32 207 # . . discard args 208 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 209 # check-stream-equal(_test-stream, "10", msg) 210 # . . push args 211 68/push "F - test-print-int32-decimal-multiple-digits"/imm32 212 68/push "10"/imm32 213 68/push _test-stream/imm32 214 # . . call 215 e8/call check-stream-equal/disp32 216 # . . discard args 217 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 218 # . end 219 c3/return 220 221 test-print-int32-decimal-negative: 222 # - check that a negative single-digit number converts correctly 223 # setup 224 # . clear-stream(_test-stream) 225 # . . push args 226 68/push _test-stream/imm32 227 # . . call 228 e8/call clear-stream/disp32 229 # . . discard args 230 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 231 # print-int32-decimal(_test-stream, -9) 232 # . . push args 233 68/push -9/imm32 234 68/push _test-stream/imm32 235 # . . call 236 e8/call print-int32-decimal/disp32 237 # . . discard args 238 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 239 +-- 26 lines: #? # dump _test-stream --------------------------------------------------------------------------------------------------------------------- 265 # check-stream-equal(_test-stream, "-9", msg) 266 # . . push args 267 68/push "F - test-print-int32-decimal-negative"/imm32 268 68/push "-9"/imm32 269 68/push _test-stream/imm32 270 # . . call 271 e8/call check-stream-equal/disp32 272 # . . discard args 273 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 274 # . end 275 c3/return 276 277 test-print-int32-decimal-negative-multiple-digits: 278 # - check that a multi-digit number converts correctly 279 # setup 280 # . clear-stream(_test-stream) 281 # . . push args 282 68/push _test-stream/imm32 283 # . . call 284 e8/call clear-stream/disp32 285 # . . discard args 286 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 287 # print-int32-decimal(_test-stream, -10) 288 # . . push args 289 68/push -0xa/imm32 290 68/push _test-stream/imm32 291 # . . call 292 e8/call print-int32-decimal/disp32 293 # . . discard args 294 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 295 # check-stream-equal(_test-stream, "-10", msg) 296 # . . push args 297 68/push "F - test-print-int32-decimal-negative-multiple-digits"/imm32 298 68/push "-10"/imm32 299 68/push _test-stream/imm32 300 # . . call 301 e8/call check-stream-equal/disp32 302 # . . discard args 303 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 304 # . end 305 c3/return 306 307 # . . vim:nowrap:textwidth=0