From 113bae7311b63e55e55160970718d19bfeeb56c3 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Wed, 1 Jan 2020 17:23:29 -0800 Subject: 5856 --- html/apps/ex1.subx.html | 77 +++++++++ html/apps/ex10.subx.html | 132 +++++++++++++++ html/apps/ex11.subx.html | 421 +++++++++++++++++++++++++++++++++++++++++++++++ html/apps/ex12.subx.html | 104 ++++++++++++ html/apps/ex2.subx.html | 79 +++++++++ html/apps/ex3.subx.html | 98 +++++++++++ html/apps/ex4.subx.html | 99 +++++++++++ html/apps/ex5.subx.html | 102 ++++++++++++ html/apps/ex6.subx.html | 96 +++++++++++ html/apps/ex7.subx.html | 159 ++++++++++++++++++ html/apps/ex8.subx.html | 123 ++++++++++++++ html/apps/ex9.subx.html | 114 +++++++++++++ 12 files changed, 1604 insertions(+) create mode 100644 html/apps/ex1.subx.html create mode 100644 html/apps/ex10.subx.html create mode 100644 html/apps/ex11.subx.html create mode 100644 html/apps/ex12.subx.html create mode 100644 html/apps/ex2.subx.html create mode 100644 html/apps/ex3.subx.html create mode 100644 html/apps/ex4.subx.html create mode 100644 html/apps/ex5.subx.html create mode 100644 html/apps/ex6.subx.html create mode 100644 html/apps/ex7.subx.html create mode 100644 html/apps/ex8.subx.html create mode 100644 html/apps/ex9.subx.html (limited to 'html/apps') diff --git a/html/apps/ex1.subx.html b/html/apps/ex1.subx.html new file mode 100644 index 00000000..c4105769 --- /dev/null +++ b/html/apps/ex1.subx.html @@ -0,0 +1,77 @@ + + + + +Mu - examples/ex1.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/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:
+ 5 #   $ ./subx translate init.linux examples/ex1.2.subx -o examples/ex1
+ 6 #   $ ./subx run examples/ex1
+ 7 # Expected result:
+ 8 #   $ echo $?
+ 9 #   42
+10 
+11 == code
+12 
+13 Entry:
+14 # exit(42)
+15 bb/copy-to-ebx  2a/imm32  # 42 in hex
+16 e8/call  syscall_exit/disp32
+17 
+18 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex10.subx.html b/html/apps/ex10.subx.html new file mode 100644 index 00000000..bcf0e466 --- /dev/null +++ b/html/apps/ex10.subx.html @@ -0,0 +1,132 @@ + + + + +Mu - examples/ex10.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/examples/ex10.subx +
+ 1 # String comparison: return 1 iff the two args passed in at the commandline are equal.
+ 2 #
+ 3 # To run:
+ 4 #   $ ./subx translate init.linux examples/ex10.subx -o examples/ex10
+ 5 #   $ ./subx run examples/ex10 abc abd
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   0  # false
+ 9 
+10 == code
+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     # . prologue
+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     # exit(eax)
+31     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
+32     e8/call  syscall_exit/disp32
+33 
+34 # compare two null-terminated ascii strings
+35 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
+36 argv-equal:  # (s1, s2) : null-terminated ascii strings -> eax : boolean
+37     # initialize s1 (ecx) and s2 (edx)
+38     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/esp  4/index/none  .           1/r32/ecx   4/disp8         .                 # copy *(esp+4) to ecx
+39     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/esp  4/index/none  .           2/r32/edx   8/disp8         .                 # copy *(esp+8) to edx
+40 $argv-equal:loop:
+41     # c1/eax, c2/ebx = *s1, *s2
+42     b8/copy-to-eax  0/imm32
+43     8a/copy-byte                    0/mod/indirect  1/rm32/ecx    .           .             .           0/r32/AL    .               .                 # copy byte at *ecx to AL
+44     bb/copy-to-ebx  0/imm32
+45     8a/copy-byte                    0/mod/indirect  2/rm32/edx    .           .             .           3/r32/BL    .               .                 # copy byte at *edx to BL
+46     # if (c1 == 0) break
+47     3d/compare-eax-and  0/imm32
+48     74/jump-if-equal  $argv-equal:break/disp8
+49     # if (c1 != c2) return false
+50     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # compare eax and ebx
+51     75/jump-if-not-equal  $argv-equal:false/disp8
+52     # ++s1, ++s2
+53     41/increment-ecx
+54     42/increment-edx
+55     # end while
+56     eb/jump  $argv-equal:loop/disp8
+57 $argv-equal:break:
+58     # if (c2 == 0) return true
+59     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0/imm32           # compare ebx
+60     75/jump-if-not-equal  $argv-equal:false/disp8
+61 $argv-equal:success:
+62     b8/copy-to-eax  1/imm32
+63     c3/return
+64     # return false
+65 $argv-equal:false:
+66     b8/copy-to-eax  0/imm32
+67     c3/return
+68 
+69 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex11.subx.html b/html/apps/ex11.subx.html new file mode 100644 index 00000000..47c0b289 --- /dev/null +++ b/html/apps/ex11.subx.html @@ -0,0 +1,421 @@ + + + + +Mu - examples/ex11.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/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:
+  9 #   $ ./subx translate init.linux 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
+ 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     # exit(eax)
+ 25     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
+ 26     e8/call  syscall_exit/disp32
+ 27 
+ 28 # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
+ 29 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
+ 30 kernel-string-equal?:  # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> eax : boolean
+ 31     # pseudocode:
+ 32     #   n = benchmark->length
+ 33     #   s1 = s
+ 34     #   s2 = benchmark->data
+ 35     #   i = 0
+ 36     #   while i < n
+ 37     #     c1 = *s1
+ 38     #     c2 = *s2
+ 39     #     if (c1 == 0) return false
+ 40     #     if (c1 != c2) return false
+ 41     #     ++s1, ++s2, ++i
+ 42     #   return *s1 == 0
+ 43     #
+ 44     # registers:
+ 45     #   i: ecx
+ 46     #   n: edx
+ 47     #   s1: edi
+ 48     #   s2: esi
+ 49     #   c1: eax
+ 50     #   c2: ebx
+ 51     #
+ 52     # . prologue
+ 53     55/push-ebp
+ 54     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 55     # . save registers
+ 56     51/push-ecx
+ 57     52/push-edx
+ 58     53/push-ebx
+ 59     56/push-esi
+ 60     57/push-edi
+ 61     # s1/edi = s
+ 62     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   8/disp8         .                 # copy *(ebp+8) to edi
+ 63     # n/edx = benchmark->length
+ 64     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+ 65     8b/copy                         0/mod/indirect  2/rm32/edx    .           .             .           2/r32/edx   .               .                 # copy *edx to edx
+ 66     # s2/esi = benchmark->data
+ 67     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   0xc/disp8       .                 # copy *(ebp+12) to esi
+ 68     81          0/subop/add         3/mod/direct    6/rm32/esi    .           .             .           .           .               4/imm32           # add to esi
+ 69     # i/ecx = c1/eax = c2/ebx = 0
+ 70     b9/copy-to-ecx  0/imm32/exit
+ 71     b8/copy-to-eax  0/imm32
+ 72     bb/copy-to-ebx  0/imm32
+ 73 $kernel-string-equal?:loop:
+ 74     # if (i >= n) break
+ 75     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+ 76     7d/jump-if-greater-or-equal  $kernel-string-equal?:break/disp8
+ 77     # c1 = *s1
+ 78     8a/copy-byte                    0/mod/indirect  7/rm32/edi    .           .             .           0/r32/AL    .               .                 # copy byte at *edi to AL
+ 79     # c2 = *s2
+ 80     8a/copy-byte                    0/mod/indirect  6/rm32/esi    .           .             .           3/r32/BL    .               .                 # copy byte at *esi to BL
+ 81     # if (c1 == 0) return false
+ 82     3d/compare-eax-and  0/imm32
+ 83     74/jump-if-equal  $kernel-string-equal?:false/disp8
+ 84     # if (c1 != c2) return false
+ 85     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # compare eax and ebx
+ 86     75/jump-if-not-equal  $kernel-string-equal?:false/disp8
+ 87     # ++i
+ 88     41/increment-ecx
+ 89     # ++s1
+ 90     47/increment-edi
+ 91     # ++s2
+ 92     46/increment-esi
+ 93     eb/jump  $kernel-string-equal?:loop/disp8
+ 94 $kernel-string-equal?:break:
+ 95     # return *s1 == 0
+ 96     8a/copy-byte                    0/mod/indirect  7/rm32/edi    .           .             .           0/r32/AL    .               .                 # copy byte at *edi to AL
+ 97     3d/compare-eax-and  0/imm32
+ 98     75/jump-if-not-equal  $kernel-string-equal?:false/disp8
+ 99 $kernel-string-equal?:true:
+100     b8/copy-to-eax  1/imm32
+101     eb/jump  $kernel-string-equal?:end/disp8
+102 $kernel-string-equal?:false:
+103     b8/copy-to-eax  0/imm32
+104 $kernel-string-equal?:end:
+105     # . restore registers
+106     5f/pop-to-edi
+107     5e/pop-to-esi
+108     5b/pop-to-ebx
+109     5a/pop-to-edx
+110     59/pop-to-ecx
+111     # . epilogue
+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 # - tests
+117 
+118 test-compare-null-kernel-string-with-empty-array:
+119     # eax = kernel-string-equal?(Null-kernel-string, "")
+120     # . . push args
+121     68/push  ""/imm32
+122     68/push  Null-kernel-string/imm32
+123     # . . call
+124     e8/call  kernel-string-equal?/disp32
+125     # . . discard args
+126     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+127     # check-ints-equal(eax, 1, msg)
+128     # . . push args
+129     68/push  "F - test-compare-null-kernel-string-with-empty-array"/imm32
+130     68/push  1/imm32/true
+131     50/push-eax
+132     # . . call
+133     e8/call  check-ints-equal/disp32
+134     # . . discard args
+135     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+136     c3/return
+137 
+138 test-compare-null-kernel-string-with-non-empty-array:
+139     # eax = kernel-string-equal?(Null-kernel-string, "Abc")
+140     # . . push args
+141     68/push  "Abc"/imm32
+142     68/push  Null-kernel-string/imm32
+143     # . . call
+144     e8/call  kernel-string-equal?/disp32
+145     # . . discard args
+146     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+147     # check-ints-equal(eax, 0, msg)
+148     # . . push args
+149     68/push  "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
+150     68/push  0/imm32/false
+151     50/push-eax
+152     # . . call
+153     e8/call  check-ints-equal/disp32
+154     # . . discard args
+155     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+156     c3/return
+157 
+158 test-compare-kernel-string-with-equal-array:
+159     # eax = kernel-string-equal?(_test-Abc-kernel-string, "Abc")
+160     # . . push args
+161     68/push  "Abc"/imm32
+162     68/push  _test-Abc-kernel-string/imm32
+163     # . . call
+164     e8/call  kernel-string-equal?/disp32
+165     # . . discard args
+166     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+167     # check-ints-equal(eax, 1, msg)
+168     # . . push args
+169     68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
+170     68/push  1/imm32/true
+171     50/push-eax
+172     # . . call
+173     e8/call  check-ints-equal/disp32
+174     # . . discard args
+175     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+176     c3/return
+177 
+178 test-compare-kernel-string-with-inequal-array:
+179     # eax = kernel-string-equal?(_test-Abc-kernel-string, "Adc")
+180     # . . push args
+181     68/push  "Adc"/imm32
+182     68/push  _test-Abc-kernel-string/imm32
+183     # . . call
+184     e8/call  kernel-string-equal?/disp32
+185     # . . discard args
+186     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+187     # check-ints-equal(eax, 0, msg)
+188     # . . push args
+189     68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
+190     68/push  0/imm32/false
+191     50/push-eax
+192     # . . call
+193     e8/call  check-ints-equal/disp32
+194     # . . discard args
+195     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+196     c3/return
+197 
+198 test-compare-kernel-string-with-empty-array:
+199     # eax = kernel-string-equal?(_test-Abc-kernel-string, "")
+200     # . . push args
+201     68/push  ""/imm32
+202     68/push  _test-Abc-kernel-string/imm32
+203     # . . call
+204     e8/call  kernel-string-equal?/disp32
+205     # . . discard args
+206     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+207     # check-ints-equal(eax, 0, msg)
+208     # . . push args
+209     68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
+210     68/push  0/imm32/false
+211     50/push-eax
+212     # . . call
+213     e8/call  check-ints-equal/disp32
+214     # . . discard args
+215     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+216     c3/return
+217 
+218 test-compare-kernel-string-with-shorter-array:
+219     # eax = kernel-string-equal?(_test-Abc-kernel-string, "Ab")
+220     # . . push args
+221     68/push  "Ab"/imm32
+222     68/push  _test-Abc-kernel-string/imm32
+223     # . . call
+224     e8/call  kernel-string-equal?/disp32
+225     # . . discard args
+226     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+227     # check-ints-equal(eax, 0, msg)
+228     # . . push args
+229     68/push  "F - test-compare-kernel-string-with-shorter-array"/imm32
+230     68/push  0/imm32/false
+231     50/push-eax
+232     # . . call
+233     e8/call  check-ints-equal/disp32
+234     # . . discard args
+235     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+236     c3/return
+237 
+238 test-compare-kernel-string-with-longer-array:
+239     # eax = kernel-string-equal?(_test-Abc-kernel-string, "Abcd")
+240     # . . push args
+241     68/push  "Abcd"/imm32
+242     68/push  _test-Abc-kernel-string/imm32
+243     # . . call
+244     e8/call  kernel-string-equal?/disp32
+245     # . . discard args
+246     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+247     # check-ints-equal(eax, 0, msg)
+248     # . . push args
+249     68/push  "F - test-compare-kernel-string-with-longer-array"/imm32
+250     68/push  0/imm32/false
+251     50/push-eax
+252     # . . call
+253     e8/call  check-ints-equal/disp32
+254     # . . discard args
+255     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+256     c3/return
+257 
+258 # - helpers
+259 
+260 # print msg to stderr if a != b, otherwise print "."
+261 check-ints-equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
+262     # . prologue
+263     55/push-ebp
+264     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+265     # . save registers
+266     51/push-ecx
+267     53/push-ebx
+268     # load args into eax, ebx and ecx
+269     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           0/r32/eax   8/disp8         .                 # copy *(ebp+8) to eax
+270     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           3/r32/ebx   0xc/disp8       .                 # copy *(ebp+12) to ebx
+271     # if (eax == b/ebx) print('.') and return
+272     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # compare eax and ebx
+273     75/jump-if-unequal  $check-ints-equal:else/disp8
+274     # . write-stderr('.')
+275     # . . push args
+276     68/push  "."/imm32
+277     # . . call
+278     e8/call  write-stderr/disp32
+279     # . . discard args
+280     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+281     # . return
+282     eb/jump  $check-ints-equal:end/disp8
+283     # otherwise print(msg)
+284 $check-ints-equal:else:
+285     # copy msg into ecx
+286     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0x10/disp8       .                # copy *(ebp+16) to ecx
+287     # print(ecx)
+288     # . . push args
+289     51/push-ecx
+290     # . . call
+291     e8/call  write-stderr/disp32
+292     # . . discard args
+293     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+294     # print newline
+295     # . . push args
+296     68/push  Newline/imm32
+297     # . . call
+298     e8/call  write-stderr/disp32
+299     # . . discard args
+300     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+301 $check-ints-equal:end:
+302     # . restore registers
+303     5b/pop-to-ebx
+304     59/pop-to-ecx
+305     # end
+306     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+307     5d/pop-to-ebp
+308     c3/return
+309 
+310 write-stderr:  # s : (address array byte) -> <void>
+311     # . prologue
+312     55/push-ebp
+313     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+314     # . save registers
+315     50/push-eax
+316     51/push-ecx
+317     52/push-edx
+318     53/push-ebx
+319     # syscall(write, 2/stderr, (data) s+4, (size) *s)
+320     # . . fd = 2 (stderr)
+321     bb/copy-to-ebx  2/imm32
+322     # . . x = s+4
+323     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
+324     81          0/subop/add         3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # add to ecx
+325     # . . size = *s
+326     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   8/disp8         .                 # copy *(ebp+8) to edx
+327     8b/copy                         0/mod/indirect  2/rm32/edx    .           .             .           2/r32/edx   .               .                 # copy *edx to edx
+328     # . . syscall
+329     e8/call  syscall_write/disp32
+330     # . restore registers
+331     5b/pop-to-ebx
+332     5a/pop-to-edx
+333     59/pop-to-ecx
+334     58/pop-to-eax
+335     # . end
+336     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+337     5d/pop-to-ebp
+338     c3/return
+339 
+340 == data
+341 
+342 Newline:
+343     # size
+344     1/imm32
+345     # data
+346     0a/newline
+347 
+348 # for kernel-string-equal tests
+349 Null-kernel-string:
+350     00/null
+351 
+352 _test-Abc-kernel-string:
+353     41/A 62/b 63/c 00/null
+354 
+355 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex12.subx.html b/html/apps/ex12.subx.html new file mode 100644 index 00000000..a6b2dc64 --- /dev/null +++ b/html/apps/ex12.subx.html @@ -0,0 +1,104 @@ + + + + +Mu - examples/ex12.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/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:
+ 5 #   $ ./subx translate init.linux examples/ex12.subx -o examples/ex12
+ 6 #   $ ./subx run examples/ex12
+ 7 # You shouldn't get a segmentation fault.
+ 8 
+ 9 == code
+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     # mmap(Mmap-new-segment->len)
+16     bb/copy-to-ebx  Mmap-new-segment/imm32
+17     e8/call  syscall_mmap/disp32
+18 
+19     # write to *eax to check that we have access to the newly-allocated segment
+20     c7          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0x34/imm32        # copy to *eax
+21 
+22     # exit(eax)
+23     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
+24     e8/call  syscall_exit/disp32
+25 
+26 == data
+27 
+28 # various constants used here were found in the Linux sources (search for file mman-common.h)
+29 Mmap-new-segment:  # type mmap_arg_struct
+30     # addr
+31     0/imm32
+32     # len
+33     0x100/imm32
+34     # protection flags
+35     3/imm32  # PROT_READ | PROT_WRITE
+36     # sharing flags
+37     0x22/imm32  # MAP_PRIVATE | MAP_ANONYMOUS
+38     # fd
+39     -1/imm32  # since MAP_ANONYMOUS is specified
+40     # offset
+41     0/imm32  # since MAP_ANONYMOUS is specified
+42 
+43 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex2.subx.html b/html/apps/ex2.subx.html new file mode 100644 index 00000000..c67315e9 --- /dev/null +++ b/html/apps/ex2.subx.html @@ -0,0 +1,79 @@ + + + + +Mu - examples/ex2.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/examples/ex2.subx +
+ 1 # Add 1 and 1, and return the result in the exit code.
+ 2 #
+ 3 # To run:
+ 4 #   $ ./subx translate init.linux examples/ex2.subx -o examples/ex2
+ 5 #   $ ./subx run examples/ex2
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   2
+ 9 
+10 == code
+11 
+12 Entry:
+13 # ebx = 1
+14 bb/copy-to-ebx  1/imm32
+15 # increment ebx
+16 43/increment-ebx
+17 # exit(ebx)
+18 e8/call  syscall_exit/disp32
+19 
+20 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex3.subx.html b/html/apps/ex3.subx.html new file mode 100644 index 00000000..7c3da099 --- /dev/null +++ b/html/apps/ex3.subx.html @@ -0,0 +1,98 @@ + + + + +Mu - examples/ex3.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/examples/ex3.subx +
+ 1 # Add the first 10 numbers, and return the result in the exit code.
+ 2 #
+ 3 # To run:
+ 4 #   $ ./subx translate init.linux examples/ex3.subx -o examples/ex3
+ 5 #   $ ./subx run examples/ex3
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   55
+ 9 
+10 == code
+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     # exit(ebx)
+34     e8/call  syscall_exit/disp32
+35 
+36 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex4.subx.html b/html/apps/ex4.subx.html new file mode 100644 index 00000000..43f5c705 --- /dev/null +++ b/html/apps/ex4.subx.html @@ -0,0 +1,99 @@ + + + + +Mu - examples/ex4.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/examples/ex4.subx +
+ 1 # Read a character from stdin, save it to a global, write it to stdout.
+ 2 #
+ 3 # To run:
+ 4 #   $ ./subx translate init.linux examples/ex4.subx -o examples/ex4
+ 5 #   $ ./subx run examples/ex4
+ 6 
+ 7 == data
+ 8 
+ 9 # the global variable we save to
+10 X:
+11     0/imm32  # space for read() to write to
+12 
+13 == code
+14 
+15 Entry:
+16 # 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 e8/call  syscall_read/disp32
+25 
+26 # write(stdout, X, 1)
+27 # . fd = 1 (stdout)
+28 bb/copy-to-ebx  1/imm32
+29 # . initialize X (location to read from)
+30 b9/copy-to-ecx  X/imm32
+31 # . size = 1 character
+32 ba/copy-to-edx  1/imm32
+33 # . syscall
+34 e8/call  syscall_write/disp32
+35 
+36 # exit(ebx)
+37 e8/call  syscall_exit/disp32
+38 
+39 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex5.subx.html b/html/apps/ex5.subx.html new file mode 100644 index 00000000..f5112fa7 --- /dev/null +++ b/html/apps/ex5.subx.html @@ -0,0 +1,102 @@ + + + + +Mu - examples/ex5.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/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:
+ 4 #   $ ./subx translate init.linux examples/ex5.subx -o examples/ex5
+ 5 #   $ ./subx run examples/ex5
+ 6 
+ 7 == code
+ 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     # 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     e8/call  syscall_read/disp32
+26 
+27     # syscall(write, stdout, x, 1)
+28     # . fd = 1 (stdout)
+29     bb/copy-to-ebx  1/imm32
+30     # . data = x (location to read from)
+31     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
+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     # exit(ebx)
+39     e8/call  syscall_exit/disp32
+40 
+41 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex6.subx.html b/html/apps/ex6.subx.html new file mode 100644 index 00000000..c8bbdd21 --- /dev/null +++ b/html/apps/ex6.subx.html @@ -0,0 +1,96 @@ + + + + +Mu - examples/ex6.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/examples/ex6.subx +
+ 1 # Print out a (global variable) string to stdout.
+ 2 #
+ 3 # To run:
+ 4 #   $ ./subx translate init.linux examples/ex6.subx -o examples/ex6
+ 5 #   $ ./subx run examples/ex6
+ 6 #   Hello, world!
+ 7 
+ 8 == code
+ 9 
+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     # 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     e8/call  syscall_write/disp32
+23 
+24     # exit(ebx)
+25     e8/call  syscall_exit/disp32
+26 
+27 == data
+28 
+29 Size:  # size of string
+30     0x0e/imm32  # 14
+31 X:  # string to print
+32     48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a       00
+33 #   H  e  l  l  o  ,  ␣  w  o  r  l  d  !  newline  null
+34 
+35 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex7.subx.html b/html/apps/ex7.subx.html new file mode 100644 index 00000000..762bf7ec --- /dev/null +++ b/html/apps/ex7.subx.html @@ -0,0 +1,159 @@ + + + + +Mu - examples/ex7.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/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:
+ 8 #   $ ./subx translate init.linux examples/ex7.subx -o examples/ex7
+ 9 #   $ ./subx run examples/ex7
+10 # Expected result:
+11 #   $ echo $?
+12 #   97
+13 
+14 == code
+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     # creat(Filename)
+21     bb/copy-to-ebx  Filename/imm32
+22     b9/copy-to-ecx  0x180/imm32/fixed-perms
+23     e8/call  syscall_creat/disp32
+24 
+25     # stream = open(Filename, O_WRONLY, 0)  # we can't use 'fd' because it looks like a hex byte
+26     bb/copy-to-ebx  Filename/imm32
+27     b9/copy-to-ecx  1/imm32/wronly
+28     ba/copy-to-edx  0x180/imm32/fixed-perms
+29     e8/call  syscall_open/disp32
+30     # save stream
+31     bb/copy-to-ebx  Stream/imm32
+32     89/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to *ebx
+33 
+34     # write(Stream, "a", 1)
+35     # . load stream
+36     bb/copy-to-ebx  Stream/imm32
+37     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
+38     # .
+39     b9/copy-to-ecx  A/imm32
+40     ba/copy-to-edx  1/imm32/size
+41     e8/call  syscall_write/disp32
+42 
+43     # close(Stream)
+44     # . load stream
+45     bb/copy-to-ebx  Stream/imm32
+46     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
+47     # .
+48     e8/call  syscall_close/disp32
+49 
+50     # stream = open(Filename, O_RDONLY, 0)
+51     bb/copy-to-ebx  Filename/imm32
+52     b9/copy-to-ecx  0/imm32/rdonly
+53     ba/copy-to-edx  0x180/imm32/fixed-perms
+54     e8/call  syscall_open/disp32
+55     # . save Stream
+56     bb/copy-to-ebx  Stream/imm32
+57     89/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to *ebx
+58 
+59     # read(Stream, B, 1)
+60     # . load stream
+61     bb/copy-to-ebx  Stream/imm32
+62     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
+63     # .
+64     b9/copy-to-ecx  B/imm32
+65     ba/copy-to-edx  1/imm32/size
+66     e8/call  syscall_read/disp32
+67 
+68     # close(Stream)
+69     # . load stream
+70     bb/copy-to-ebx  Stream/imm32
+71     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
+72     #
+73     e8/call  syscall_close/disp32
+74 
+75     # unlink(filename)
+76     bb/copy-to-ebx  Filename/imm32
+77     e8/call  syscall_unlink/disp32
+78 
+79     # exit(b)
+80     # . load b
+81     bb/copy-to-ebx  B/imm32
+82     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
+83     #
+84     e8/call  syscall_exit/disp32
+85 
+86 == data
+87 
+88 Stream:
+89     0/imm32
+90 A:
+91     61/imm32/A
+92 B:
+93     0/imm32
+94 Filename:
+95     2e 66 6f 6f 00 00 00 00
+96 #   .  f  o  o  null
+97 
+98 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex8.subx.html b/html/apps/ex8.subx.html new file mode 100644 index 00000000..1f57fcdf --- /dev/null +++ b/html/apps/ex8.subx.html @@ -0,0 +1,123 @@ + + + + +Mu - examples/ex8.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/examples/ex8.subx +
+ 1 # Example reading commandline arguments: compute length of first arg.
+ 2 #
+ 3 # To run:
+ 4 #   $ ./subx translate init.linux 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
+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     # . prologue
+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     e8/call  syscall_exit/disp32
+36 
+37 ascii-length:  # s : (address array byte) -> n/eax
+38     # edx = s
+39     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/esp  4/index/none  .           2/r32/edx   4/disp8         .                 # copy *(esp+4) to edx
+40     # var result/eax = 0
+41     b8/copy-to-eax  0/imm32
+42 $ascii-length:loop:
+43     # var c/ecx = *s
+44     8a/copy-byte                    0/mod/*         2/rm32/edx    .           .             .           1/r32/CL    .               .                 # copy byte at *edx to CL
+45     # if (c == '\0') break
+46     81          7/subop/compare     3/mod/direct    1/rm32/ecx    .           .             .           .           .               0/imm32           # compare ecx
+47     74/jump-if-equal  $ascii-length:end/disp8
+48     # ++s
+49     42/increment-edx
+50     # ++result
+51     40/increment-eax
+52     # loop
+53     eb/jump  $ascii-length:loop/disp8
+54 $ascii-length:end:
+55     # return eax
+56     c3/return
+57 
+58 == data
+59 
+60 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex9.subx.html b/html/apps/ex9.subx.html new file mode 100644 index 00000000..fbf7b76c --- /dev/null +++ b/html/apps/ex9.subx.html @@ -0,0 +1,114 @@ + + + + +Mu - examples/ex9.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/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:
+ 7 #   $ ./subx translate init.linux 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
+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     # . prologue
+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     # exit(eax)
+38     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
+39     e8/call  syscall_exit/disp32
+40 
+41 ascii-difference:  # (s1, s2) : null-terminated ascii strings
+42     # a = first letter of s1 (ecx)
+43     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/esp  4/index/none              0/r32/eax   4/disp8         .                 # copy *(esp+4) to eax
+44     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           0/r32/eax   .               .                 # copy *eax to eax
+45     # b = first letter of s2 (edx)
+46     8b/copy                         1/mod/*+disp8   4/rm32/sib    4/base/esp  4/index/none              1/r32/ecx   8/disp8                           # copy *(esp+8) to ecx
+47     8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # copy *ecx to ecx
+48     # a-b
+49     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # subtract ecx from eax
+50     c3/return
+51 
+52 # . . vim:nowrap:textwidth=0
+
+ + + -- cgit 1.4.1-2-gfad0