https://github.com/akkartik/mu/blob/main/317abort.subx
  1 # Dump a stack trace when you abort.
  2 
  3 == code
  4 
  5 abort:  # e: (addr array byte)
  6     # . prologue
  7     55/push-ebp
  8     89/<- %ebp 4/r32/esp
  9     #
 10     (set-cursor-position-on-real-screen 0 0)
 11     (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+8) 0xf 0xc)  # 0/real-screen, 0xf/fg=white, 0xc/bg=red
 12     (dump-call-stack)
 13     # crash
 14     {
 15       eb/jump loop/disp8
 16     }
 17 
 18 # Helpers below this point are not intended to be reused; they assume the
 19 # program will soon crash. In particular, they destroy the heap.
 20 
 21 dump-call-stack:
 22     # . prologue
 23     55/push-ebp
 24     89/<- %ebp 4/r32/esp
 25     # . save registers
 26     50/push-eax
 27     51/push-ecx
 28     52/push-edx
 29     53/push-ebx
 30     # var labels/edx: (addr stream {start-address, label-slice} 0x5000)
 31     # start addresses are in ascending order
 32     81 5/subop/subtract %esp 0x3c000/imm32  # 0x5000 labels * 12 bytes per label
 33     68/push  0x3c000/imm32
 34     68/push  0/imm32/read
 35     68/push  0/imm32/write
 36     89/<- %edx 4/r32/esp
 37     #
 38     (load-debug-symbols %edx)  # destroys the heap
 39     # traverse the linked list of ebp pointers: https://wiki.osdev.org/Stack_Trace
 40     8b/-> *ebp 3/r32/ebx
 41     {
 42       # loop termination check
 43       81 7/subop/compare %ebx 0/imm32
 44       0f 84/jump-if-= break/disp32
 45       # loop body
 46       (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "\n" 0 0xc)
 47       (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebx+4) 0xf 0xc)
 48       (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 0 0xc)
 49       (containing-function %edx *(ebx+4))  # => eax, ecx
 50       (draw-slice-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax %ecx 0 0xc)
 51       # loop update
 52       8b/-> *ebx 3/r32/ebx
 53       #
 54       e9/jump loop/disp32
 55     }
 56 $dump-call-stack:end:
 57     # . reclaim locals
 58     81 0/subop/add %esp 0x100c/imm32
 59     # . restore registers
 60     5b/pop-to-ebx
 61     5a/pop-to-edx
 62     59/p
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 106stream.subx</title>
<meta name="Generator" content="Vim/8.1">
<meta name="plugin-version" content="vim8.1_v1">
<meta name="syntax" content="none">
<meta name="settings" content="number_lines,use_css,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal-light">
<style type="text/css">
<!--
pre { font-family: monospace; color: #000000; background-color: #ffffd7; }
body { font-size:12pt; font-family: monospace; color: #000000; background-color: #ffffd7; }
a { color:inherit; }
* { font-size:12pt; font-size: 1em; }
.subxH1Comment { color: #005faf; text-decoration: underline; }
.subxComment { color: #005faf; }
.subxS1Comment { color: #0000af; }
.subxS2Comment { color: #8a8a8a; }
.LineNr { }
.Constant { color: #008787; }
.subxFunction { color: #af5f00; text-decoration: underline; }
.Normal { color: #000000; background-color: #ffffd7; padding-bottom: 1px; }
-->
</style>

<script type='text/javascript'>
<!--

/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
  var lineNum;
  lineNum = window.location.hash;
  lineNum = lineNum.substr(1); /* strip off '#' */

  if (lineNum.indexOf('L') == -1) {
    lineNum = 'L'+lineNum;
  }
  var lineElem = document.getElementById(lineNum);
  /* Always jump to new location even if the line was hidden inside a fold, or
   * we corrected the raw number to a line ID.
   */
  if (lineElem) {
    lineElem.scrollIntoView(true);
  }
  return true;
}
if ('onhashchange' in window) {
  window.onhashchange = JumpToLine;
}

-->
</script>
</head>
<body onload='JumpToLine();'>
<a href='https://github.com/akkartik/mu/blob/main/106stream.subx'>https://github.com/akkartik/mu/blob/main/106stream.subx</a>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="subxComment"># streams: data structure for operating on arrays in a stateful manner</span>
<span id="L2" class="LineNr"> 2 </span><span class="subxComment">#</span>
<span id="L3" class="LineNr"> 3 </span><span class="subxComment"># A stream looks like this:</span>
<span id="L4" class="LineNr"> 4 </span><span class="subxComment">#   write: int  # index at which writes go</span>
<span id="L5" class="LineNr"> 5 </span><span class="subxComment">#   read: int  # index that we've read until</span>
<span id="L6" class="LineNr"> 6 </span><span class="subxComment">#   data: (array byte)  # prefixed by size as usual</span>
<span id="L7" class="LineNr"> 7 </span><span class="subxComment">#</span>
<span id="L8" class="LineNr"> 8 </span><span class="subxComment"># some primitives for operating on streams:</span>
<span id="L9" class="LineNr"> 9