From 2104d1a75b76dbffc0b15a96c98d94e7a16594e8 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 27 Jan 2020 00:39:46 -0800 Subject: 5925 --- html/apps/survey.subx.html | 104 ++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'html/apps/survey.subx.html') diff --git a/html/apps/survey.subx.html b/html/apps/survey.subx.html index c778979d..c1fe6d8d 100644 --- a/html/apps/survey.subx.html +++ b/html/apps/survey.subx.html @@ -176,12 +176,12 @@ if ('onhashchange' in window) { 113 # labels: (addr stream {string, label-info}) (16 bytes per row) 114 # these are all inefficient; use sequential scans for lookups 115 - 116 subx-survey: # infile : (addr buffered-file), out : (addr buffered-file) + 116 subx-survey: # infile: (addr buffered-file), out: (addr buffered-file) 117 # pseudocode - 118 # var in : (stream byte 4096) + 118 # var in: (stream byte 4096) 119 # slurp(infile, in) - 120 # var segments : (stream segment-info) - 121 # var labels : (stream label-info Max-labels) + 120 # var segments: (stream segment-info) + 121 # var labels: (stream label-info Max-labels) 122 # compute-offsets(in, segments, labels) 123 # compute-addresses(segments, labels) 124 # rewind-stream(in) @@ -194,13 +194,13 @@ if ('onhashchange' in window) { 131 51/push-ecx 132 52/push-edx 133 56/push-esi - 134 # var segments/ecx : (stream {string, segment-info} 160) # 10 rows * 16 bytes/row + 134 # var segments/ecx: (stream {string, segment-info} 160) # 10 rows * 16 bytes/row 135 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 136 68/push 0xa0/imm32/length 137 68/push 0/imm32/read 138 68/push 0/imm32/write 139 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - 140 # var labels/edx : (stream label-info Max-labels*16) + 140 # var labels/edx: (stream label-info Max-labels*16) 141 # . data 142 2b/subtract 0/mod/indirect 5/rm32/.disp32 . . 4/r32/esp Max-labels/disp32 # subtract *Max-labels from esp 143 # . length @@ -210,7 +210,7 @@ if ('onhashchange' in window) { 147 # . write 148 68/push 0/imm32/write 149 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - 150 # var in/esi : (stream byte Input-size) + 150 # var in/esi: (stream byte Input-size) 151 # . data 152 2b/subtract 0/mod/indirect 5/rm32/.disp32 . . 4/r32/esp Input-size/disp32 # subtract *Input-size from esp 153 # . length @@ -449,7 +449,7 @@ if ('onhashchange' in window) { 618 619 == code 620 - 621 compute-offsets: # in : (addr stream byte), segments : (addr stream {string, segment-info}), labels : (addr stream {string, label-info}) + 621 compute-offsets: # in: (addr stream byte), segments: (addr stream {string, segment-info}), labels: (addr stream {string, label-info}) 622 # skeleton: 623 # for lines in 'in' 624 # for words in line @@ -460,8 +460,8 @@ if ('onhashchange' in window) { 629 # default 630 # 631 # pseudocode: - 632 # curr-segment-name : (addr string) = 0 - 633 # var line : (stream byte 512) + 632 # curr-segment-name: (addr string) = 0 + 633 # var line: (stream byte 512) 634 # while true # line loop 635 # clear-stream(line) 636 # read-line(in, line) @@ -492,7 +492,7 @@ if ('onhashchange' in window) { 661 # break (next line) 662 # else if is-label?(word-slice) 663 # strip trailing ':' from word-slice - 664 # x : (addr label-info) = get-or-insert(labels, name) + 664 # x: (addr label-info) = get-or-insert(labels, name) 665 # x->segment-name = curr-segment-name 666 # trace("label '", word-slice, "' is in segment '", curr-segment-name, "'.") 667 # x->segment-offset = segment-offset @@ -519,7 +519,7 @@ if ('onhashchange' in window) { 688 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . compute-offsets:file-offset/disp32 0/imm32 # copy to *compute-offsets:word-slice 689 # segment-offset = 0 690 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . compute-offsets:segment-offset/disp32 0/imm32 # copy to *compute-offsets:word-slice - 691 # var line/ecx : (stream byte 512) + 691 # var line/ecx: (stream byte 512) 692 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp 693 68/push 0x200/imm32/length 694 68/push 0/imm32/read @@ -861,13 +861,13 @@ if ('onhashchange' in window) { 1219 e8/call clear-stream/disp32 1220 # . . discard args 1221 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1222 # var segments/ecx : (stream byte 2*16) +1222 # var segments/ecx: (stream byte 2*16) 1223 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # subtract from esp 1224 68/push 0x20/imm32/length 1225 68/push 0/imm32/read 1226 68/push 0/imm32/write 1227 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1228 # var labels/edx : (stream byte 2*16) +1228 # var labels/edx: (stream byte 2*16) 1229 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # subtract from esp 1230 68/push 0x20/imm32/length 1231 68/push 0/imm32/read @@ -995,9 +995,9 @@ if ('onhashchange' in window) { 1378 5d/pop-to-ebp 1379 c3/return 1380 -1381 compute-addresses: # segments : (addr stream {string, segment-info}), labels : (addr stream {string, label-info}) +1381 compute-addresses: # segments: (addr stream {string, segment-info}), labels: (addr stream {string, label-info}) 1382 # pseudocode: -1383 # srow : (addr segment-info) = segments->data +1383 # srow: (addr segment-info) = segments->data 1384 # max = &segments->data[segments->write] 1385 # num-segments = segments->write / 16 1386 # starting-offset = 0x34 + (num-segments * 0x20) @@ -1008,12 +1008,12 @@ if ('onhashchange' in window) { 1391 # s->address += (s->file-offset & 0x00000fff) 1392 # trace-sssns("segment " s->key " starts at address " s->address) 1393 # srow += 16 # row-size -1394 # lrow : (addr label-info) = labels->data +1394 # lrow: (addr label-info) = labels->data 1395 # max = &labels->data[labels->write] 1396 # while true 1397 # if (lrow >= max) break -1398 # seg-name : (addr string) = lrow->segment-name -1399 # label-seg : (addr segment-info) = get(segments, seg-name) +1398 # var seg-name: (addr string) = lrow->segment-name +1399 # var label-seg: (addr segment-info) = get(segments, seg-name) 1400 # lrow->address = label-seg->address + lrow->segment-offset 1401 # trace-sssns("label " lrow->key " is at address " lrow->address) 1402 # lrow += 16 # row-size @@ -1089,10 +1089,10 @@ if ('onhashchange' in window) { 1497 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 1498 0f 83/jump-if-addr>= $compute-addresses:end/disp32 1499 +-- 26 lines: #? # dump lrow->key ------------------------------------------------------------------------------------------------------------------------ -1525 # seg-name/edx = lrow->segment-name +1525 # var seg-name/edx: (addr array byte) = lrow->segment-name 1526 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 2/r32/edx 4/disp8 . # copy *eax to edx 1527 +-- 26 lines: #? # dump seg-name ------------------------------------------------------------------------------------------------------------------------- -1553 # label-seg/edx : (addr segment-info) = get(segments, seg-name, row-size=16, "segment table") +1553 # var label-seg/edx: (addr segment-info) = get(segments, seg-name, row-size=16, "segment table") 1554 # . save eax 1555 50/push-eax 1556 # . eax = get(segments, seg-name, row-size=16) @@ -1163,13 +1163,13 @@ if ('onhashchange' in window) { 1621 55/push-ebp 1622 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1623 # setup -1624 # . var segments/ecx : (stream byte 10*16) +1624 # . var segments/ecx: (stream byte 10*16) 1625 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 1626 68/push 0xa0/imm32/length 1627 68/push 0/imm32/read 1628 68/push 0/imm32/write 1629 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1630 # . var labels/edx : (stream byte 512*16) +1630 # . var labels/edx: (stream byte 512*16) 1631 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 1632 68/push 0x2000/imm32/length 1633 68/push 0/imm32/read @@ -1307,13 +1307,13 @@ if ('onhashchange' in window) { 1790 55/push-ebp 1791 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1792 # setup -1793 # . var segments/ecx : (stream byte 10*16) +1793 # . var segments/ecx: (stream byte 10*16) 1794 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 1795 68/push 0xa0/imm32/length 1796 68/push 0/imm32/read 1797 68/push 0/imm32/write 1798 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1799 # . var labels/edx : (stream byte 512*16) +1799 # . var labels/edx: (stream byte 512*16) 1800 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 1801 68/push 0x2000/imm32/length 1802 68/push 0/imm32/read @@ -1388,7 +1388,7 @@ if ('onhashchange' in window) { 1871 5d/pop-to-ebp 1872 c3/return 1873 -1874 emit-output: # in : (addr stream byte), out : (addr buffered-file), segments : (addr stream {string, segment-info}), labels : (addr stream {string, label-info}) +1874 emit-output: # in: (addr stream byte), out: (addr buffered-file), segments: (addr stream {string, segment-info}), labels: (addr stream {string, label-info}) 1875 # pseudocode: 1876 # emit-headers(out, segments, labels) 1877 # emit-segments(in, out, segments, labels) @@ -1423,10 +1423,10 @@ if ('onhashchange' in window) { 1922 5d/pop-to-ebp 1923 c3/return 1924 -1925 emit-segments: # in : (addr stream byte), out : (addr buffered-file), segments : (addr stream {string, segment-info}), labels : (addr stream {string, label-info}) +1925 emit-segments: # in: (addr stream byte), out: (addr buffered-file), segments: (addr stream {string, segment-info}), labels: (addr stream {string, label-info}) 1926 # pseudocode: 1927 # var offset-of-next-instruction = 0 -1928 # var line : (stream byte 512) +1928 # var line: (stream byte 512) 1929 # line-loop: 1930 # while true 1931 # clear-stream(line) @@ -1488,17 +1488,17 @@ if ('onhashchange' in window) { 1987 53/push-ebx 1988 56/push-esi 1989 57/push-edi -1990 # var line/ecx : (stream byte 512) +1990 # var line/ecx: (stream byte 512) 1991 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp 1992 68/push 0x200/imm32/length 1993 68/push 0/imm32/read 1994 68/push 0/imm32/write 1995 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1996 # var word-slice/edx : slice +1996 # var word-slice/edx: slice 1997 68/push 0/imm32/end 1998 68/push 0/imm32/start 1999 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx -2000 # var datum/edi : slice +2000 # var datum/edi: slice 2001 68/push 0/imm32/end 2002 68/push 0/imm32/start 2003 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi @@ -1925,13 +1925,13 @@ if ('onhashchange' in window) { 2577 e8/call clear-stream/disp32 2578 # . . discard args 2579 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2580 # . var segments/ecx : (stream byte 10*16) +2580 # . var segments/ecx: (stream byte 10*16) 2581 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 2582 68/push 0xa0/imm32/length 2583 68/push 0/imm32/read 2584 68/push 0/imm32/write 2585 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2586 # . var labels/edx : (stream byte 512*16) +2586 # . var labels/edx: (stream byte 512*16) 2587 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 2588 68/push 0x2000/imm32/length 2589 68/push 0/imm32/read @@ -2130,13 +2130,13 @@ if ('onhashchange' in window) { 2814 e8/call clear-stream/disp32 2815 # . . discard args 2816 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2817 # . var segments/ecx : (stream byte 10*16) +2817 # . var segments/ecx: (stream byte 10*16) 2818 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 2819 68/push 0xa0/imm32/length 2820 68/push 0/imm32/read 2821 68/push 0/imm32/write 2822 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2823 # . var labels/edx : (stream byte 512*16) +2823 # . var labels/edx: (stream byte 512*16) 2824 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 2825 68/push 0x2000/imm32/length 2826 68/push 0/imm32/read @@ -2300,13 +2300,13 @@ if ('onhashchange' in window) { 3016 e8/call clear-stream/disp32 3017 # . . discard args 3018 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3019 # . var segments/ecx : (stream byte 10*16) +3019 # . var segments/ecx: (stream byte 10*16) 3020 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa0/imm32 # subtract from esp 3021 68/push 0xa0/imm32/length 3022 68/push 0/imm32/read 3023 68/push 0/imm32/write 3024 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -3025 # . var labels/edx : (stream byte 512*16) +3025 # . var labels/edx: (stream byte 512*16) 3026 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x2000/imm32 # subtract from esp 3027 68/push 0x2000/imm32/length 3028 68/push 0/imm32/read @@ -2425,7 +2425,7 @@ if ('onhashchange' in window) { 3173 5d/pop-to-ebp 3174 c3/return 3175 -3176 emit-headers: # out : (addr buffered-file), segments : (addr stream {string, segment-info}), labels : (addr stream {string, label-info}) +3176 emit-headers: # out: (addr buffered-file), segments: (addr stream {string, segment-info}), labels: (addr stream {string, label-info}) 3177 # pseudocode: 3178 # emit-elf-header(out, segments, labels) 3179 # curr-segment = segments->data @@ -2485,7 +2485,7 @@ if ('onhashchange' in window) { 3311 5d/pop-to-ebp 3312 c3/return 3313 -3314 emit-elf-header: # out : (addr buffered-file), segments : (addr stream {string, segment-info}), labels : (addr stream {string, label-info}) +3314 emit-elf-header: # out: (addr buffered-file), segments: (addr stream {string, segment-info}), labels: (addr stream {string, label-info}) 3315 # pseudocode 3316 # *$Elf_e_entry = get(labels, "Entry")->address 3317 # *$Elf_e_phnum = segments->write / 16 # size of a row @@ -2553,7 +2553,7 @@ if ('onhashchange' in window) { 3379 5d/pop-to-ebp 3380 c3/return 3381 -3382 emit-elf-program-header-entry: # out : (addr buffered-file), curr-segment : (addr {string, segment-info}) +3382 emit-elf-program-header-entry: # out: (addr buffered-file), curr-segment: (addr {string, segment-info}) 3383 # pseudocode: 3384 # *$Elf_p_offset = curr-segment->file-offset 3385 # *$Elf_p_vaddr = curr-segment->address @@ -2642,7 +2642,7 @@ if ('onhashchange' in window) { 3468 3469 # - some helpers for tests 3470 -3471 stream-add4: # in : (addr stream byte), key : addr, val1 : addr, val2 : addr, val3 : addr +3471 stream-add4: # in: (addr stream byte), key: addr, val1: addr, val2: addr, val3: addr 3472 # . prologue 3473 55/push-ebp 3474 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -2728,7 +2728,7 @@ if ('onhashchange' in window) { 3554 # l: (addr slice) 3555 # one gotcha: 's5' must not be empty 3556 -3557 trace-sssns: # s1 : (addr string), s2 : (addr string), s3 : (addr string), n4 : int, s5 : (addr string) +3557 trace-sssns: # s1: (addr string), s2: (addr string), s3: (addr string), n4: int, s5: (addr string) 3558 # . prologue 3559 55/push-ebp 3560 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -2810,7 +2810,7 @@ if ('onhashchange' in window) { 3661 5d/pop-to-ebp 3662 c3/return 3663 -3664 trace-snsns: # s1 : (addr string), n2 : int, s3 : (addr string), n4 : int, s5 : (addr string) +3664 trace-snsns: # s1: (addr string), n2: int, s3: (addr string), n4: int, s5: (addr string) 3665 # . prologue 3666 55/push-ebp 3667 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -2892,7 +2892,7 @@ if ('onhashchange' in window) { 3768 5d/pop-to-ebp 3769 c3/return 3770 -3771 trace-slsls: # s1 : (addr string), l2 : (addr slice), s3 : (addr string), l4 : (addr slice), s5 : (addr string) +3771 trace-slsls: # s1: (addr string), l2: (addr slice), s3: (addr string), l4: (addr slice), s5: (addr string) 3772 # . prologue 3773 55/push-ebp 3774 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -2954,7 +2954,7 @@ if ('onhashchange' in window) { 3830 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 3831 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 3832 05/add-to-eax 4/imm32 -3833 # var b/ebx : slice = {eax, ecx} +3833 # var b/ebx: slice = {eax, ecx} 3834 51/push-ecx 3835 50/push-eax 3836 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx @@ -2963,7 +2963,7 @@ if ('onhashchange' in window) { 3839 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 3840 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 3841 05/add-to-eax 4/imm32 -3842 # var d/edx : slice = {eax, ecx} +3842 # var d/edx: slice = {eax, ecx} 3843 51/push-ecx 3844 50/push-eax 3845 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx @@ -2992,7 +2992,7 @@ if ('onhashchange' in window) { 3893 5d/pop-to-ebp 3894 c3/return 3895 -3896 trace-slsns: # s1 : (addr string), l2 : (addr slice), s3 : (addr string), n4 : int, s5 : (addr string) +3896 trace-slsns: # s1: (addr string), l2: (addr slice), s3: (addr string), n4: int, s5: (addr string) 3897 # . prologue 3898 55/push-ebp 3899 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -3054,7 +3054,7 @@ if ('onhashchange' in window) { 3955 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 3956 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 3957 05/add-to-eax 4/imm32 -3958 # var b/ebx : slice = {eax, ecx} +3958 # var b/ebx: slice = {eax, ecx} 3959 51/push-ecx 3960 50/push-eax 3961 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx @@ -3083,7 +3083,7 @@ if ('onhashchange' in window) { 4009 5d/pop-to-ebp 4010 c3/return 4011 -4012 trace-slsss: # s1 : (addr string), l2 : (addr slice), s3 : (addr string), s4 : (addr string), s5 : (addr string) +4012 trace-slsss: # s1: (addr string), l2: (addr slice), s3: (addr string), s4: (addr string), s5: (addr string) 4013 # . prologue 4014 55/push-ebp 4015 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp @@ -3145,7 +3145,7 @@ if ('onhashchange' in window) { 4071 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 4072 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 4073 05/add-to-eax 4/imm32 -4074 # var b/ebx : slice = {eax, ecx} +4074 # var b/ebx: slice = {eax, ecx} 4075 51/push-ecx 4076 50/push-eax 4077 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx @@ -3174,7 +3174,7 @@ if ('onhashchange' in window) { 4125 5d/pop-to-ebp 4126 c3/return 4127 -4128 num-bytes: # line : (addr stream byte) -> eax : int +4128 num-bytes: # line: (addr stream byte) -> eax: int 4129 # pseudocode: 4130 # result = 0 4131 # while true @@ -3199,7 +3199,7 @@ if ('onhashchange' in window) { 4150 53/push-ebx 4151 # var result/eax = 0 4152 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -4153 # var word-slice/ecx : slice +4153 # var word-slice/ecx: slice 4154 68/push 0/imm32/end 4155 68/push 0/imm32/start 4156 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -- cgit 1.4.1-2-gfad0