From 6e1eeeebfb453fa7c871869c19375ce60fbd7413 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 27 Jul 2019 16:01:55 -0700 Subject: 5485 - promote SubX to top-level --- html/examples/ex1.subx.html | 80 ++++++++ html/examples/ex10.subx.html | 135 ++++++++++++++ html/examples/ex11.subx.html | 423 +++++++++++++++++++++++++++++++++++++++++++ html/examples/ex12.subx.html | 106 +++++++++++ html/examples/ex2.subx.html | 82 +++++++++ html/examples/ex3.subx.html | 101 +++++++++++ html/examples/ex4.subx.html | 102 +++++++++++ html/examples/ex5.subx.html | 106 +++++++++++ html/examples/ex6.subx.html | 98 ++++++++++ html/examples/ex7.subx.html | 168 +++++++++++++++++ html/examples/ex8.subx.html | 124 +++++++++++++ html/examples/ex9.subx.html | 117 ++++++++++++ 12 files changed, 1642 insertions(+) create mode 100644 html/examples/ex1.subx.html create mode 100644 html/examples/ex10.subx.html create mode 100644 html/examples/ex11.subx.html create mode 100644 html/examples/ex12.subx.html create mode 100644 html/examples/ex2.subx.html create mode 100644 html/examples/ex3.subx.html create mode 100644 html/examples/ex4.subx.html create mode 100644 html/examples/ex5.subx.html create mode 100644 html/examples/ex6.subx.html create mode 100644 html/examples/ex7.subx.html create mode 100644 html/examples/ex8.subx.html create mode 100644 html/examples/ex9.subx.html (limited to 'html/examples') diff --git a/html/examples/ex1.subx.html b/html/examples/ex1.subx.html new file mode 100644 index 00000000..9a203cdc --- /dev/null +++ b/html/examples/ex1.subx.html @@ -0,0 +1,80 @@ + + + + +Mu - subx/examples/ex1.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex1.subx +
+ 1 # First program: same as https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
+ 2 # Just return 42.
+ 3 #
+ 4 # To run (from the subx directory):
+ 5 #   $ ./subx translate examples/ex1.2.subx -o examples/ex1
+ 6 #   $ ./subx run examples/ex1
+ 7 # Expected result:
+ 8 #   $ echo $?
+ 9 #   42
+10 
+11 == code 0x09000000
+12 
+13 Entry:
+14 # syscall(exit, 42)
+15 bb/copy-to-EBX  2a/imm32  # 42 in hex
+16 b8/copy-to-EAX  1/imm32/exit
+17 cd/syscall  0x80/imm8
+18 
+19 == data 0x0a000000
+20 
+21 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex10.subx.html b/html/examples/ex10.subx.html new file mode 100644 index 00000000..4d84ab28 --- /dev/null +++ b/html/examples/ex10.subx.html @@ -0,0 +1,135 @@ + + + + +Mu - subx/examples/ex10.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex10.subx +
+ 1 # String comparison: return 1 iff the two args passed in at the commandline are equal.
+ 2 #
+ 3 # To run (from the subx directory):
+ 4 #   $ ./subx translate examples/ex10.subx -o examples/ex10
+ 5 #   $ ./subx run examples/ex10 abc abd
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   0  # false
+ 9 
+10 == code 0x09000000
+11 #   instruction                     effective address                                                   register    displacement    immediate
+12 # . op          subop               mod             rm32          base        index         scale       r32
+13 # . 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
+14 
+15 Entry:  # return argv-equal(argv[1], argv[2])
+16 #       At the start of a SubX program:
+17 #         argc: *ESP
+18 #         argv[0]: *(ESP+4)
+19 #         argv[1]: *(ESP+8)
+20 #         ...
+21     # . prolog
+22     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+23     # argv-equal(argv[1], argv[2])
+24     # . . push argv[2]
+25     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+26     # . . push argv[1]
+27     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+28     # . . call
+29     e8/call argv-equal/disp32
+30     # syscall(exit, EAX)
+31     89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to EBX
+32     b8/copy-to-EAX  1/imm32/exit
+33     cd/syscall  0x80/imm8
+34 
+35 # compare two null-terminated ascii strings
+36 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
+37 argv-equal:  # (s1, s2) : null-terminated ascii strings -> EAX : boolean
+38     # initialize s1 (ECX) and s2 (EDX)
+39     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   4/disp8         .                 # copy *(ESP+4) to ECX
+40     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           2/r32/EDX   8/disp8         .                 # copy *(ESP+8) to EDX
+41 $argv-equal:loop:
+42     # c1/EAX, c2/EBX = *s1, *s2
+43     b8/copy-to-EAX  0/imm32
+44     8a/copy-byte                    0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/AL    .               .                 # copy byte at *ECX to AL
+45     bb/copy-to-EBX  0/imm32
+46     8a/copy-byte                    0/mod/indirect  2/rm32/EDX    .           .             .           3/r32/BL    .               .                 # copy byte at *EDX to BL
+47     # if (c1 == 0) break
+48     3d/compare-EAX-and  0/imm32
+49     74/jump-if-equal  $argv-equal:break/disp8
+50     # if (c1 != c2) return false
+51     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
+52     75/jump-if-not-equal  $argv-equal:false/disp8
+53     # ++s1, ++s2
+54     41/increment-ECX
+55     42/increment-EDX
+56     # end while
+57     eb/jump  $argv-equal:loop/disp8
+58 $argv-equal:break:
+59     # if (c2 == 0) return true
+60     81          7/subop/compare     3/mod/direct    3/rm32/EBX    .           .             .           .           .               0/imm32           # compare EBX
+61     75/jump-if-not-equal  $argv-equal:false/disp8
+62 $argv-equal:success:
+63     b8/copy-to-EAX  1/imm32
+64     c3/return
+65     # return false
+66 $argv-equal:false:
+67     b8/copy-to-EAX  0/imm32
+68     c3/return
+69 
+70 == data 0x0a000000
+71 
+72 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex11.subx.html b/html/examples/ex11.subx.html new file mode 100644 index 00000000..c8ad42c9 --- /dev/null +++ b/html/examples/ex11.subx.html @@ -0,0 +1,423 @@ + + + + +Mu - subx/examples/ex11.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex11.subx +
+  1 # Null-terminated vs length-prefixed ascii strings.
+  2 #
+  3 # By default we create strings with a 4-byte length prefix rather than a null suffix.
+  4 # However we still need null-prefixed strings when interacting with the Linux
+  5 # kernel in a few places. This layer implements a function for comparing
+  6 # a null-terminated 'kernel string' with a length-prefixed 'SubX string'.
+  7 #
+  8 # To run (from the subx directory):
+  9 #   $ ./subx translate examples/ex11.subx -o examples/ex11
+ 10 #   $ ./subx run examples/ex11  # runs a series of tests
+ 11 #   ......  # all tests pass
+ 12 #
+ 13 # (We can't yet run the tests when given a "test" commandline argument,
+ 14 # because checking for it would require the function being tested! Breakage
+ 15 # would cause tests to not run, rather than to fail as we'd like.)
+ 16 
+ 17 == code 0x09000000
+ 18 #   instruction                     effective address                                                   register    displacement    immediate
+ 19 # . op          subop               mod             rm32          base        index         scale       r32
+ 20 # . 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
+ 21 
+ 22 Entry:  # run all tests
+ 23     e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
+ 24     # syscall(exit, EAX)
+ 25     89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to EBX
+ 26     b8/copy-to-EAX  1/imm32/exit
+ 27     cd/syscall  0x80/imm8
+ 28 
+ 29 # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
+ 30 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
+ 31 kernel-string-equal?:  # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
+ 32     # pseudocode:
+ 33     #   n = benchmark->length
+ 34     #   s1 = s
+ 35     #   s2 = benchmark->data
+ 36     #   i = 0
+ 37     #   while i < n
+ 38     #     c1 = *s1
+ 39     #     c2 = *s2
+ 40     #     if (c1 == 0) return false
+ 41     #     if (c1 != c2) return false
+ 42     #     ++s1, ++s2, ++i
+ 43     #   return *s1 == 0
+ 44     #
+ 45     # registers:
+ 46     #   i: ECX
+ 47     #   n: EDX
+ 48     #   s1: EDI
+ 49     #   s2: ESI
+ 50     #   c1: EAX
+ 51     #   c2: EBX
+ 52     #
+ 53     # . prolog
+ 54     55/push-EBP
+ 55     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 56     # . save registers
+ 57     51/push-ECX
+ 58     52/push-EDX
+ 59     53/push-EBX
+ 60     56/push-ESI
+ 61     57/push-EDI
+ 62     # s1/EDI = s
+ 63     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
+ 64     # n/EDX = benchmark->length
+ 65     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
+ 66     8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
+ 67     # s2/ESI = benchmark->data
+ 68     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
+ 69     81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               4/imm32           # add to ESI
+ 70     # i/ECX = c1/EAX = c2/EBX = 0
+ 71     b9/copy-to-ECX  0/imm32/exit
+ 72     b8/copy-to-EAX  0/imm32
+ 73     bb/copy-to-EBX  0/imm32
+ 74 $kernel-string-equal?:loop:
+ 75     # if (i >= n) break
+ 76     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # compare ECX with EDX
+ 77     7d/jump-if-greater-or-equal  $kernel-string-equal?:break/disp8
+ 78     # c1 = *s1
+ 79     8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/AL    .               .                 # copy byte at *EDI to AL
+ 80     # c2 = *s2
+ 81     8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/BL    .               .                 # copy byte at *ESI to BL
+ 82     # if (c1 == 0) return false
+ 83     3d/compare-EAX-and  0/imm32
+ 84     74/jump-if-equal  $kernel-string-equal?:false/disp8
+ 85     # if (c1 != c2) return false
+ 86     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
+ 87     75/jump-if-not-equal  $kernel-string-equal?:false/disp8
+ 88     # ++i
+ 89     41/increment-ECX
+ 90     # ++s1
+ 91     47/increment-EDI
+ 92     # ++s2
+ 93     46/increment-ESI
+ 94     eb/jump  $kernel-string-equal?:loop/disp8
+ 95 $kernel-string-equal?:break:
+ 96     # return *s1 == 0
+ 97     8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/AL    .               .                 # copy byte at *EDI to AL
+ 98     3d/compare-EAX-and  0/imm32
+ 99     75/jump-if-not-equal  $kernel-string-equal?:false/disp8
+100 $kernel-string-equal?:true:
+101     b8/copy-to-EAX  1/imm32
+102     eb/jump  $kernel-string-equal?:end/disp8
+103 $kernel-string-equal?:false:
+104     b8/copy-to-EAX  0/imm32
+105 $kernel-string-equal?:end:
+106     # . restore registers
+107     5f/pop-to-EDI
+108     5e/pop-to-ESI
+109     5b/pop-to-EBX
+110     5a/pop-to-EDX
+111     59/pop-to-ECX
+112     # . epilog
+113     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+114     5d/pop-to-EBP
+115     c3/return
+116 
+117 # - tests
+118 
+119 test-compare-null-kernel-string-with-empty-array:
+120     # EAX = kernel-string-equal?(Null-kernel-string, "")
+121     # . . push args
+122     68/push  ""/imm32
+123     68/push  Null-kernel-string/imm32
+124     # . . call
+125     e8/call  kernel-string-equal?/disp32
+126     # . . discard args
+127     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+128     # check-ints-equal(EAX, 1, msg)
+129     # . . push args
+130     68/push  "F - test-compare-null-kernel-string-with-empty-array"/imm32
+131     68/push  1/imm32/true
+132     50/push-EAX
+133     # . . call
+134     e8/call  check-ints-equal/disp32
+135     # . . discard args
+136     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+137     c3/return
+138 
+139 test-compare-null-kernel-string-with-non-empty-array:
+140     # EAX = kernel-string-equal?(Null-kernel-string, "Abc")
+141     # . . push args
+142     68/push  "Abc"/imm32
+143     68/push  Null-kernel-string/imm32
+144     # . . call
+145     e8/call  kernel-string-equal?/disp32
+146     # . . discard args
+147     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+148     # check-ints-equal(EAX, 0, msg)
+149     # . . push args
+150     68/push  "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
+151     68/push  0/imm32/false
+152     50/push-EAX
+153     # . . call
+154     e8/call  check-ints-equal/disp32
+155     # . . discard args
+156     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+157     c3/return
+158 
+159 test-compare-kernel-string-with-equal-array:
+160     # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Abc")
+161     # . . push args
+162     68/push  "Abc"/imm32
+163     68/push  _test-Abc-kernel-string/imm32
+164     # . . call
+165     e8/call  kernel-string-equal?/disp32
+166     # . . discard args
+167     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+168     # check-ints-equal(EAX, 1, msg)
+169     # . . push args
+170     68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
+171     68/push  1/imm32/true
+172     50/push-EAX
+173     # . . call
+174     e8/call  check-ints-equal/disp32
+175     # . . discard args
+176     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+177     c3/return
+178 
+179 test-compare-kernel-string-with-inequal-array:
+180     # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Adc")
+181     # . . push args
+182     68/push  "Adc"/imm32
+183     68/push  _test-Abc-kernel-string/imm32
+184     # . . call
+185     e8/call  kernel-string-equal?/disp32
+186     # . . discard args
+187     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+188     # check-ints-equal(EAX, 0, msg)
+189     # . . push args
+190     68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
+191     68/push  0/imm32/false
+192     50/push-EAX
+193     # . . call
+194     e8/call  check-ints-equal/disp32
+195     # . . discard args
+196     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+197     c3/return
+198 
+199 test-compare-kernel-string-with-empty-array:
+200     # EAX = kernel-string-equal?(_test-Abc-kernel-string, "")
+201     # . . push args
+202     68/push  ""/imm32
+203     68/push  _test-Abc-kernel-string/imm32
+204     # . . call
+205     e8/call  kernel-string-equal?/disp32
+206     # . . discard args
+207     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+208     # check-ints-equal(EAX, 0, msg)
+209     # . . push args
+210     68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
+211     68/push  0/imm32/false
+212     50/push-EAX
+213     # . . call
+214     e8/call  check-ints-equal/disp32
+215     # . . discard args
+216     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+217     c3/return
+218 
+219 test-compare-kernel-string-with-shorter-array:
+220     # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Ab")
+221     # . . push args
+222     68/push  "Ab"/imm32
+223     68/push  _test-Abc-kernel-string/imm32
+224     # . . call
+225     e8/call  kernel-string-equal?/disp32
+226     # . . discard args
+227     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+228     # check-ints-equal(EAX, 0, msg)
+229     # . . push args
+230     68/push  "F - test-compare-kernel-string-with-shorter-array"/imm32
+231     68/push  0/imm32/false
+232     50/push-EAX
+233     # . . call
+234     e8/call  check-ints-equal/disp32
+235     # . . discard args
+236     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+237     c3/return
+238 
+239 test-compare-kernel-string-with-longer-array:
+240     # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Abcd")
+241     # . . push args
+242     68/push  "Abcd"/imm32
+243     68/push  _test-Abc-kernel-string/imm32
+244     # . . call
+245     e8/call  kernel-string-equal?/disp32
+246     # . . discard args
+247     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+248     # check-ints-equal(EAX, 0, msg)
+249     # . . push args
+250     68/push  "F - test-compare-kernel-string-with-longer-array"/imm32
+251     68/push  0/imm32/false
+252     50/push-EAX
+253     # . . call
+254     e8/call  check-ints-equal/disp32
+255     # . . discard args
+256     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+257     c3/return
+258 
+259 # - helpers
+260 
+261 # print msg to stderr if a != b, otherwise print "."
+262 check-ints-equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
+263     # . prolog
+264     55/push-EBP
+265     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+266     # . save registers
+267     51/push-ECX
+268     53/push-EBX
+269     # load args into EAX, EBX and ECX
+270     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(EBP+8) to EAX
+271     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
+272     # if (EAX == b/EBX) print('.') and return
+273     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
+274     75/jump-if-unequal  $check-ints-equal:else/disp8
+275     # . write-stderr('.')
+276     # . . push args
+277     68/push  "."/imm32
+278     # . . call
+279     e8/call  write-stderr/disp32
+280     # . . discard args
+281     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+282     # . return
+283     eb/jump  $check-ints-equal:end/disp8
+284     # otherwise print(msg)
+285 $check-ints-equal:else:
+286     # copy msg into ECX
+287     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   0x10/disp8       .                # copy *(EBP+16) to ECX
+288     # print(ECX)
+289     # . . push args
+290     51/push-ECX
+291     # . . call
+292     e8/call  write-stderr/disp32
+293     # . . discard args
+294     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+295     # print newline
+296     # . . push args
+297     68/push  Newline/imm32
+298     # . . call
+299     e8/call  write-stderr/disp32
+300     # . . discard args
+301     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+302 $check-ints-equal:end:
+303     # . restore registers
+304     5b/pop-to-EBX
+305     59/pop-to-ECX
+306     # end
+307     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+308     5d/pop-to-EBP
+309     c3/return
+310 
+311 write-stderr:  # s : (address array byte) -> <void>
+312     # . prolog
+313     55/push-EBP
+314     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+315     # . save registers
+316     50/push-EAX
+317     51/push-ECX
+318     52/push-EDX
+319     53/push-EBX
+320     # syscall(write, 2/stderr, (data) s+4, (size) *s)
+321     # . . fd = 2 (stderr)
+322     bb/copy-to-EBX  2/imm32
+323     # . . x = s+4
+324     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
+325     81          0/subop/add         3/mod/direct    1/rm32/ECX    .           .             .           .           .               4/imm32           # add to ECX
+326     # . . size = *s
+327     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   8/disp8         .                 # copy *(EBP+8) to EDX
+328     8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
+329     # . . syscall
+330     b8/copy-to-EAX  4/imm32/write
+331     cd/syscall  0x80/imm8
+332     # . restore registers
+333     5b/pop-to-EBX
+334     5a/pop-to-EDX
+335     59/pop-to-ECX
+336     58/pop-to-EAX
+337     # . end
+338     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+339     5d/pop-to-EBP
+340     c3/return
+341 
+342 == data 0x0a000000
+343 
+344 Newline:
+345     # size
+346     1/imm32
+347     # data
+348     0a/newline
+349 
+350 # for kernel-string-equal tests
+351 Null-kernel-string:
+352     00/null
+353 
+354 _test-Abc-kernel-string:
+355     41/A 62/b 63/c 00/null
+356 
+357 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex12.subx.html b/html/examples/ex12.subx.html new file mode 100644 index 00000000..e4ddaee4 --- /dev/null +++ b/html/examples/ex12.subx.html @@ -0,0 +1,106 @@ + + + + +Mu - subx/examples/ex12.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex12.subx +
+ 1 # Example showing mmap syscall.
+ 2 # Create a new segment using mmap, save the address, write to it.
+ 3 #
+ 4 # To run (from the subx directory):
+ 5 #   $ ./subx translate examples/ex12.subx -o examples/ex12
+ 6 #   $ ./subx run examples/ex12
+ 7 # You shouldn't get a segmentation fault.
+ 8 
+ 9 == code 0x09000000
+10 #   instruction                     effective address                                                   register    displacement    immediate
+11 # . op          subop               mod             rm32          base        index         scale       r32
+12 # . 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
+13 
+14 Entry:
+15     # syscall(mmap, 0x1000)
+16     bb/copy-to-EBX  Mmap-new-segment/imm32
+17     b8/copy-to-EAX  0x5a/imm32/mmap
+18     cd/syscall  0x80/imm8
+19 
+20     # write to *EAX to check that we have access to the newly-allocated segment
+21     c7          0/subop/copy        0/mod/direct    0/rm32/EAX    .           .             .           .           .               0x34/imm32        # copy to *EAX
+22 
+23     # syscall(exit, EAX)
+24     89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to EBX
+25     b8/copy-to-EAX  1/imm32/exit
+26     cd/syscall  0x80/imm8
+27 
+28 == data 0x0a000000
+29 
+30 # various constants used here were found in the Linux sources (search for file mman-common.h)
+31 Mmap-new-segment:  # type mmap_arg_struct
+32     # addr
+33     0/imm32
+34     # len
+35     0x100/imm32
+36     # protection flags
+37     3/imm32  # PROT_READ | PROT_WRITE
+38     # sharing flags
+39     0x22/imm32  # MAP_PRIVATE | MAP_ANONYMOUS
+40     # fd
+41     -1/imm32  # since MAP_ANONYMOUS is specified
+42     # offset
+43     0/imm32  # since MAP_ANONYMOUS is specified
+44 
+45 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex2.subx.html b/html/examples/ex2.subx.html new file mode 100644 index 00000000..8df9abb1 --- /dev/null +++ b/html/examples/ex2.subx.html @@ -0,0 +1,82 @@ + + + + +Mu - subx/examples/ex2.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex2.subx +
+ 1 # Add 1 and 1, and return the result in the exit code.
+ 2 #
+ 3 # To run (from the subx directory):
+ 4 #   $ ./subx translate examples/ex2.subx -o examples/ex2
+ 5 #   $ ./subx run examples/ex2
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   2
+ 9 
+10 == code 0x09000000
+11 
+12 Entry:
+13 # EBX = 1
+14 bb/copy-to-EBX  1/imm32
+15 # increment EBX
+16 43/increment-EBX
+17 # syscall(exit, EBX)
+18 b8/copy-to-EAX  1/imm32/exit
+19 cd/syscall  0x80/imm8
+20 
+21 == data 0x0a000000
+22 
+23 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex3.subx.html b/html/examples/ex3.subx.html new file mode 100644 index 00000000..8c0f1642 --- /dev/null +++ b/html/examples/ex3.subx.html @@ -0,0 +1,101 @@ + + + + +Mu - subx/examples/ex3.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex3.subx +
+ 1 # Add the first 10 numbers, and return the result in the exit code.
+ 2 #
+ 3 # To run (from the subx directory):
+ 4 #   $ ./subx translate examples/ex3.subx -o examples/ex3
+ 5 #   $ ./subx run examples/ex3
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   55
+ 9 
+10 == code 0x09000000
+11 #   instruction                     effective address                                                   register    displacement    immediate
+12 # . op          subop               mod             rm32          base        index         scale       r32
+13 # . 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
+14 
+15 Entry:
+16     # result: EBX = 0
+17     bb/copy-to-EBX  0/imm32
+18     # counter: ECX = 1
+19     b9/copy-to-ECX  1/imm32
+20 
+21 $loop:
+22     # if (counter > 10) break
+23     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0xa/imm32         # compare ECX
+24     7f/jump-if-greater  $exit/disp8
+25     # result += counter
+26     01/add                          3/mod/direct    3/rm32/EBX    .           .             .           1/r32/ECX   .               .                 # add ECX to EBX
+27     # ++counter
+28     41/increment-ECX
+29     # loop
+30     eb/jump  $loop/disp8
+31 
+32 $exit:
+33     # syscall(exit, EBX)
+34     b8/copy-to-EAX  1/imm32/exit
+35     cd/syscall  0x80/imm8
+36 
+37 == data 0x0a000000
+38 
+39 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex4.subx.html b/html/examples/ex4.subx.html new file mode 100644 index 00000000..caa0fe5e --- /dev/null +++ b/html/examples/ex4.subx.html @@ -0,0 +1,102 @@ + + + + +Mu - subx/examples/ex4.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex4.subx +
+ 1 # Read a character from stdin, save it to a global, write it to stdout.
+ 2 #
+ 3 # To run (from the subx directory):
+ 4 #   $ ./subx translate examples/ex4.subx -o examples/ex4
+ 5 #   $ ./subx run examples/ex4
+ 6 
+ 7 == data 0x0a000000
+ 8 
+ 9 # the global variable we save to
+10 X:
+11     0/imm32  # space for read() to write to
+12 
+13 == code 0x09000000
+14 
+15 Entry:
+16 # syscall(read, stdin, X, 1)
+17 # . fd = 0 (stdin)
+18 bb/copy-to-EBX  0/imm32
+19 # . data = X (location to write result to)
+20 b9/copy-to-ECX  X/imm32
+21 # . size = 1 character
+22 ba/copy-to-EDX  1/imm32
+23 # . syscall
+24 b8/copy-to-EAX  3/imm32/read
+25 cd/syscall  0x80/imm8
+26 
+27 # syscall(write, stdout, X, 1)
+28 # . fd = 1 (stdout)
+29 bb/copy-to-EBX  1/imm32
+30 # . initialize X (location to read from)
+31 b9/copy-to-ECX  X/imm32
+32 # . size = 1 character
+33 ba/copy-to-EDX  1/imm32
+34 # . syscall
+35 b8/copy-to-EAX  4/imm32/write
+36 cd/syscall  0x80/imm8
+37 
+38 # syscall(exit, EBX)
+39 b8/copy-to-EAX  1/imm32/exit
+40 cd/syscall  0x80/imm8
+41 
+42 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex5.subx.html b/html/examples/ex5.subx.html new file mode 100644 index 00000000..de88308a --- /dev/null +++ b/html/examples/ex5.subx.html @@ -0,0 +1,106 @@ + + + + +Mu - subx/examples/ex5.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex5.subx +
+ 1 # Read a character from stdin, save it to a local on the stack, write it to stdout.
+ 2 #
+ 3 # To run (from the subx directory):
+ 4 #   $ ./subx translate examples/ex5.subx -o examples/ex5
+ 5 #   $ ./subx run examples/ex5
+ 6 
+ 7 == code 0x09000000
+ 8 #   instruction                     effective address                                                   register    displacement    immediate
+ 9 # . op          subop               mod             rm32          base        index         scale       r32
+10 # . 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
+11 
+12 Entry:
+13 
+14     # allocate x on the stack
+15     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # subtract from ESP
+16 
+17     # syscall(read, stdin, x, 1)
+18     # . fd = 0 (stdin)
+19     bb/copy-to-EBX  0/imm32
+20     # . data = x (location to write result to)
+21     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              1/r32/ECX   4/disp8         .                 # copy ESP+4 to ECX
+22     # . size = 1 character
+23     ba/copy-to-EDX  1/imm32
+24     # . syscall
+25     b8/copy-to-EAX  3/imm32/read
+26     cd/syscall  0x80/imm8
+27 
+28     # syscall(write, stdout, x, 1)
+29     # . fd = 1 (stdout)
+30     bb/copy-to-EBX  1/imm32
+31     # . data = x (location to read from)
+32     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              1/r32/ECX   4/disp8         .                 # copy ESP+4 to ECX
+33     # . size = 1 character
+34     ba/copy-to-EDX  1/imm32
+35     # . syscall
+36     b8/copy-to-EAX  4/imm32/write
+37     cd/syscall  0x80/imm8
+38 
+39     # syscall(exit, EBX)
+40     b8/copy-to-EAX  1/imm32/exit
+41     cd/syscall  0x80/imm8
+42 
+43 == data 0x0a000000
+44 
+45 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex6.subx.html b/html/examples/ex6.subx.html new file mode 100644 index 00000000..45c779a6 --- /dev/null +++ b/html/examples/ex6.subx.html @@ -0,0 +1,98 @@ + + + + +Mu - subx/examples/ex6.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex6.subx +
+ 1 # Print out a (global variable) string to stdout.
+ 2 #
+ 3 # To run (from the subx directory):
+ 4 #   $ ./subx translate examples/ex6.subx -o examples/ex6
+ 5 #   $ ./subx run examples/ex6
+ 6 #   Hello, world!
+ 7 
+ 8 == code 0x09000000
+ 9 #   instruction                     effective address                                                   register    displacement    immediate
+10 # . op          subop               mod             rm32          base        index         scale       r32
+11 # . 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
+12 
+13 Entry:
+14     # syscall(write, stdout, X, Size)
+15     # . fd = 1 (stdout)
+16     bb/copy-to-EBX  1/imm32
+17     # . initialize X (location to write result to)
+18     b9/copy-to-ECX  X/imm32
+19     # . initialize Size
+20     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           2/r32/EDX   Size/disp32     .                 # copy *Size to EDX
+21     # . syscall
+22     b8/copy-to-EAX  4/imm32/write
+23     cd/syscall  0x80/imm8
+24 
+25     # syscall(exit, EBX)
+26     b8/copy-to-EAX  1/imm32/exit
+27     cd/syscall  0x80/imm8
+28 
+29 == data 0x0a000000
+30 
+31 Size:  # size of string
+32     0x0e/imm32  # 14
+33 X:  # string to print
+34     48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a       00
+35 #   H  e  l  l  o  ,  ␣  w  o  r  l  d  !  newline  null
+36 
+37 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex7.subx.html b/html/examples/ex7.subx.html new file mode 100644 index 00000000..23d0d31a --- /dev/null +++ b/html/examples/ex7.subx.html @@ -0,0 +1,168 @@ + + + + +Mu - subx/examples/ex7.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex7.subx +
+  1 # Example showing file syscalls.
+  2 #
+  3 # Create a file, open it for writing, write a character to it, close it, open
+  4 # it for reading, read a character from it, close it, delete it, and return
+  5 # the character read.
+  6 #
+  7 # To run (from the subx directory):
+  8 #   $ ./subx translate examples/ex7.subx -o examples/ex7
+  9 #   $ ./subx run examples/ex7
+ 10 # Expected result:
+ 11 #   $ echo $?
+ 12 #   97
+ 13 
+ 14 == code 0x09000000
+ 15 #   instruction                     effective address                                                   register    displacement    immediate
+ 16 # . op          subop               mod             rm32          base        index         scale       r32
+ 17 # . 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
+ 18 
+ 19 Entry:
+ 20     # syscall(creat, Filename)
+ 21     bb/copy-to-EBX  Filename/imm32
+ 22     b9/copy-to-ECX  0x180/imm32/fixed-perms
+ 23     b8/copy-to-EAX  8/imm32/creat
+ 24     cd/syscall  0x80/imm8
+ 25 
+ 26     # stream = syscall(open, Filename, O_WRONLY, 0)  # we can't use 'fd' because it looks like a hex byte
+ 27     bb/copy-to-EBX  Filename/imm32
+ 28     b9/copy-to-ECX  1/imm32/wronly
+ 29     ba/copy-to-EDX  0x180/imm32/fixed-perms
+ 30     b8/copy-to-EAX  5/imm32/open
+ 31     cd/syscall  0x80/imm8
+ 32     # save stream
+ 33     bb/copy-to-EBX  Stream/imm32
+ 34     89/copy                         0/mod/indirect  3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to *EBX
+ 35 
+ 36     # syscall(write, Stream, "a", 1)
+ 37     # . load stream
+ 38     bb/copy-to-EBX  Stream/imm32
+ 39     8b/copy                         0/mod/indirect  3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # copy *EBX to EBX
+ 40     # .
+ 41     b9/copy-to-ECX  A/imm32
+ 42     ba/copy-to-EDX  1/imm32/size
+ 43     b8/copy-to-EAX  4/imm32/write
+ 44     cd/syscall  0x80/imm8
+ 45 
+ 46     # syscall(close, Stream)
+ 47     # . load stream
+ 48     bb/copy-to-EBX  Stream/imm32
+ 49     8b/copy                         0/mod/indirect  3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # copy *EBX to EBX
+ 50     # .
+ 51     b8/copy-to-EAX  6/imm32/close
+ 52     cd/syscall  0x80/imm8
+ 53 
+ 54     # stream = syscall(open, Filename, O_RDONLY, 0)
+ 55     bb/copy-to-EBX  Filename/imm32
+ 56     b9/copy-to-ECX  0/imm32/rdonly
+ 57     ba/copy-to-EDX  0x180/imm32/fixed-perms
+ 58     b8/copy-to-EAX  5/imm32/open
+ 59     cd/syscall  0x80/imm8
+ 60     # . save Stream
+ 61     bb/copy-to-EBX  Stream/imm32
+ 62     89/copy                         0/mod/indirect  3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to *EBX
+ 63 
+ 64     # syscall(read, Stream, B, 1)
+ 65     # . load stream
+ 66     bb/copy-to-EBX  Stream/imm32
+ 67     8b/copy                         0/mod/indirect  3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # copy *EBX to EBX
+ 68     # .
+ 69     b9/copy-to-ECX  B/imm32
+ 70     ba/copy-to-EDX  1/imm32/size
+ 71     b8/copy-to-EAX  3/imm32/read
+ 72     cd/syscall  0x80/imm8
+ 73 
+ 74     # syscall(close, Stream)
+ 75     # . load stream
+ 76     bb/copy-to-EBX  Stream/imm32
+ 77     8b/copy                         0/mod/indirect  3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # copy *EBX to EBX
+ 78     #
+ 79     b8/copy-to-EAX  6/imm32/close
+ 80     cd/syscall  0x80/imm8
+ 81 
+ 82     # syscall(unlink, filename)
+ 83     bb/copy-to-EBX  Filename/imm32
+ 84     b8/copy-to-EAX  0xa/imm32/unlink
+ 85     cd/syscall  0x80/imm8
+ 86 
+ 87     # syscall(exit, b)
+ 88     # . load b
+ 89     bb/copy-to-EBX  B/imm32
+ 90     8b/copy                         0/mod/indirect  3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # copy *EBX to EBX
+ 91     #
+ 92     b8/copy-to-EAX  1/imm32/exit
+ 93     cd/syscall  0x80/imm8
+ 94 
+ 95 == data 0x0a000000
+ 96 
+ 97 Stream:
+ 98     0/imm32
+ 99 A:
+100     61/imm32/A
+101 B:
+102     0/imm32
+103 Filename:
+104     2e 66 6f 6f 00 00 00 00
+105 #   .  f  o  o  null
+106 
+107 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex8.subx.html b/html/examples/ex8.subx.html new file mode 100644 index 00000000..c636cebe --- /dev/null +++ b/html/examples/ex8.subx.html @@ -0,0 +1,124 @@ + + + + +Mu - subx/examples/ex8.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex8.subx +
+ 1 # Example reading commandline arguments: compute length of first arg.
+ 2 #
+ 3 # To run (from the subx directory):
+ 4 #   $ ./subx translate examples/ex8.subx -o examples/ex8
+ 5 #   $ ./subx run examples/ex8 abc de fghi
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   3  # length of 'abc'
+ 9 #
+10 # At the start of a SubX program:
+11 #   argc: *ESP
+12 #   argv[0]: *(ESP+4)
+13 #   argv[1]: *(ESP+8)
+14 #   ...
+15 # Locals start from ESP-4 downwards.
+16 
+17 == code 0x09000000
+18 #   instruction                     effective address                                                   register    displacement    immediate
+19 # . op          subop               mod             rm32          base        index         scale       r32
+20 # . 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
+21 
+22 Entry:
+23     # . prolog
+24     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+25     # EAX = ascii-length(argv[1])
+26     # . . push args
+27     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+28     # . . call
+29     e8/call  ascii-length/disp32
+30     # . . discard args
+31     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+32 
+33     # exit(EAX)
+34     89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to EBX
+35     b8/copy-to-EAX  1/imm32/exit
+36     cd/syscall  0x80/imm8
+37 
+38 ascii-length:  # s : (address array byte) -> n/EAX
+39     # EDX = s
+40     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none  .           2/r32/EDX   4/disp8         .                 # copy *(ESP+4) to EDX
+41     # var result/EAX = 0
+42     b8/copy-to-EAX  0/imm32
+43 $ascii-length:loop:
+44     # var c/ECX = *s
+45     8a/copy-byte                    0/mod/*         2/rm32/EDX    .           .             .           1/r32/CL    .               .                 # copy byte at *EDX to CL
+46     # if (c == '\0') break
+47     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0/imm32           # compare ECX
+48     74/jump-if-equal  $ascii-length:end/disp8
+49     # ++s
+50     42/increment-EDX
+51     # ++result
+52     40/increment-EAX
+53     # loop
+54     eb/jump  $ascii-length:loop/disp8
+55 $ascii-length:end:
+56     # return EAX
+57     c3/return
+58 
+59 == data 0x0a000000
+60 
+61 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/examples/ex9.subx.html b/html/examples/ex9.subx.html new file mode 100644 index 00000000..61491047 --- /dev/null +++ b/html/examples/ex9.subx.html @@ -0,0 +1,117 @@ + + + + +Mu - subx/examples/ex9.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/examples/ex9.subx +
+ 1 # Example showing arg order on the stack.
+ 2 #
+ 3 # Show difference between ascii codes of first letter of first arg and first
+ 4 # letter of second arg.
+ 5 #
+ 6 # To run (from the subx directory):
+ 7 #   $ ./subx translate examples/ex9.subx -o examples/ex9
+ 8 #   $ ./subx run examples/ex9 z x
+ 9 # Expected result:
+10 #   $ echo $?
+11 #   2
+12 #
+13 # At the start of a SubX program:
+14 #   argc: *ESP
+15 #   argv[0]: *(ESP+4)
+16 #   argv[1]: *(ESP+8)
+17 #   ...
+18 # Locals start from ESP-4 downwards.
+19 
+20 == code 0x09000000
+21 #   instruction                     effective address                                                   register    displacement    immediate
+22 # . op          subop               mod             rm32          base        index         scale       r32
+23 # . 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
+24 
+25 Entry:
+26     # . prolog
+27     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+28     # ascii-difference(argv[1], argv[2])
+29     # . . push argv[2]
+30     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+31     # . . push argv[1]
+32     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+33     # . . call
+34     e8/call  ascii-difference/disp32
+35     # . . discard args
+36     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+37     # syscall(exit, EAX)
+38     89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to EBX
+39     b8/copy-to-EAX  1/imm32/exit
+40     cd/syscall  0x80/imm8
+41 
+42 ascii-difference:  # (s1, s2) : null-terminated ascii strings
+43     # a = first letter of s1 (ECX)
+44     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              0/r32/EAX   4/disp8         .                 # copy *(ESP+4) to EAX
+45     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # copy *EAX to EAX
+46     # b = first letter of s2 (EDX)
+47     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/ESP  4/index/none              1/r32/ECX   8/disp8                           # copy *(ESP+8) to ECX
+48     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # copy *ECX to ECX
+49     # a-b
+50     29/subtract                     3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # subtract ECX from EAX
+51     c3/return
+52 
+53 == data 0x0a000000
+54 
+55 # . . vim:nowrap:textwidth=0
+
+ + + -- cgit 1.4.1-2-gfad0