about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-07-09 23:41:32 -0700
committerKartik Agaram <vc@akkartik.com>2019-07-09 23:41:32 -0700
commit48aabc860ad7acd5ad76300f99c66e529b2555d5 (patch)
tree85a299eb0d3b6754ccf873f6f08d4e7d033545d8 /subx
parent20a527702b59f4bc1f739345d29e9591fb62f5d6 (diff)
downloadmu-48aabc860ad7acd5ad76300f99c66e529b2555d5.tar.gz
mostly done with emit-output
Some nooks and crannies will need light final debugging with xxd, but
emit-hex-output covers most of the logic.
Diffstat (limited to 'subx')
-rwxr-xr-xsubx/apps/assortbin31880 -> 32098 bytes
-rwxr-xr-xsubx/apps/dquotesbin38233 -> 38451 bytes
-rwxr-xr-xsubx/apps/packbin44246 -> 44464 bytes
-rw-r--r--subx/apps/subx-common.subx136
-rwxr-xr-xsubx/apps/surveybin36547 -> 38623 bytes
-rw-r--r--subx/apps/survey.subx137
6 files changed, 267 insertions, 6 deletions
diff --git a/subx/apps/assort b/subx/apps/assort
index 6bda81f8..0f9d62ac 100755
--- a/subx/apps/assort
+++ b/subx/apps/assort
Binary files differdiff --git a/subx/apps/dquotes b/subx/apps/dquotes
index 09750e5a..5eb5fac2 100755
--- a/subx/apps/dquotes
+++ b/subx/apps/dquotes
Binary files differdiff --git a/subx/apps/pack b/subx/apps/pack
index 2bc82e55..4ab2bc00 100755
--- a/subx/apps/pack
+++ b/subx/apps/pack
Binary files differdiff --git a/subx/apps/subx-common.subx b/subx/apps/subx-common.subx
index 84108e55..aa6498c1 100644
--- a/subx/apps/subx-common.subx
+++ b/subx/apps/subx-common.subx
@@ -2136,6 +2136,142 @@ test-emit-hex-negative:
     # . end
     c3/return
 
+# print 'arr' in hex with a space after every byte
+emit-hex-array:  # out : (address buffered-file), arr : (address array byte) -> <void>
+    # . prolog
+    55/push-EBP
+    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+    # . save registers
+    50/push-EAX
+    51/push-ECX
+    52/push-EDX
+    57/push-EDI
+    # EDI = out
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
+    # EDX = arr  # <== 0xbdffffe4
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
+    # curr/ECX = arr->data
+    8d/copy-address                 1/mod/*+disp8   2/rm32/EDX    .           .             .           1/r32/ECX   4/disp8         .                 # copy EDX+4 to ECX
+    # max/EDX = arr->data + arr->length
+    8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
+    01/add                          3/mod/direct    2/rm32/EDX    .           .             .           1/r32/ECX   .               .                 # add ECX to EDX
+    # EAX = 0
+    31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+$emit-hex-array:loop:
+    # if (curr >= width) break
+    39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # compare ECX with EDX
+    73/jump-if-greater-or-equal-unsigned  $emit-hex-array:end/disp8
+    # emit-hex(out, *curr, width=1)
+    # . . push args
+    68/push  1/imm32/width
+    8a/copy-byte                    0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/AL    .               .                 # copy byte at *ECX to AL
+    50/push-EAX
+    57/push-EDI
+    # . . call
+    e8/call  emit-hex/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # ++curr
+    41/increment-ECX
+    eb/jump  $emit-hex-array:loop/disp8
+$emit-hex-array:end:
+    # . restore registers
+    5f/pop-to-EDI
+    5a/pop-to-EDX
+    59/pop-to-ECX
+    58/pop-to-EAX
+    # . epilog
+    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+    5d/pop-to-EBP
+    c3/return
+
+test-emit-hex-array:
+    # . prolog
+    55/push-EBP
+    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+    # setup
+    # . clear-stream(_test-output-stream)
+    # . . push args
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  clear-stream/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+    # . clear-stream(_test-output-buffered-file+4)
+    # . . push args
+    b8/copy-to-EAX  _test-output-buffered-file/imm32
+    05/add-to-EAX  4/imm32
+    50/push-EAX
+    # . . call
+    e8/call  clear-stream/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+    # var arr/ECX (address array byte) = [01, 02, 03]
+    68/push  0x00030201/imm32  # bytes 01 02 03
+    68/push  3/imm32/length
+    89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+    # emit-hex-array(_test-output-buffered-file, arr)
+    # . . push args
+    51/push-ECX
+    68/push  _test-output-buffered-file/imm32
+    # . . call
+    e8/call  emit-hex-array/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . flush(_test-output-buffered-file)
+    # . . push args
+    68/push  _test-output-buffered-file/imm32
+    # . . call
+    e8/call  flush/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+#?     # dump output {{{
+#?     # . write(2/stderr, "result: ^")
+#?     # . . push args
+#?     68/push  "result: ^"/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+#?     # . write-stream(2/stderr, _test-output-stream)
+#?     # . . push args
+#?     68/push  _test-output-stream/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write-stream/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+#?     # . write(2/stderr, "$\n")
+#?     # . . push args
+#?     68/push  "$\n"/imm32
+#?     68/push  2/imm32/stderr
+#?     # . . call
+#?     e8/call  write/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+#?     # . rewind-stream(_test-output-stream)
+#?     # . . push args
+#?     68/push  _test-output-stream/imm32
+#?     # . . call
+#?     e8/call  rewind-stream/disp32
+#?     # . . discard args
+#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+#?     # }}}
+    # check-next-stream-line-equal(_test-output-stream, "01 02 03 ", msg)
+    # . . push args
+    68/push  "F - test-emit-hex-array"/imm32
+    68/push  "01 02 03 "/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . epilog
+    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+    5d/pop-to-EBP
+    c3/return
+
 compute-width: # word : (address array byte) -> EAX : int
     # . prolog
     55/push-EBP
diff --git a/subx/apps/survey b/subx/apps/survey
index 4afaec04..0f7434f6 100755
--- a/subx/apps/survey
+++ b/subx/apps/survey
Binary files differdiff --git a/subx/apps/survey.subx b/subx/apps/survey.subx
index 65490596..cd73bbf6 100644
--- a/subx/apps/survey.subx
+++ b/subx/apps/survey.subx
@@ -1967,9 +1967,43 @@ emit-headers:  # out : (address buffered-file), segments : (address stream {stri
     55/push-EBP
     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
     # . save registers
+    50/push-EAX
+    51/push-ECX
+    # emit-elf-header(out, segments, labels)
+    # . . push args
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  emit-elf-header/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # EAX = segments
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(EBP+8) to EAX
+    # ECX = segments->write
+    8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
+    # curr-segment/EAX = segments->data
+    8d/copy-address                 1/mod/*+disp8   0/rm32/EAX    .           .             .           0/r32/EAX   0xc/disp8       .                 # copy EAX+12 to EAX
+    # max/ECX = segments->data + segments->write
+    01/add                          3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # add EAX to ECX
+$emit-headers:loop:
+    # if (curr-segment >= max) break
+    39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX with ECX
+    73/jump-if-greater-or-equal-unsigned  $emit-headers:end/disp8
+    # emit-elf-program-header-entry(curr-segment)
+    # . . push args
+    50/push-EAX
+    # . . call
+    e8/call  emit-elf-program-header-entry/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+    # curr-segment += 20                        # size of a row
+    81          0/subop/add         3/mod/direct    0/rm32/EAX    .           .             .           .           .               0x14/imm32        # add to EAX
+    eb/jump  $emit-headers:loop/disp8
 $emit-headers:end:
-    # . reclaim locals
     # . restore registers
+    59/pop-to-ECX
+    58/pop-to-EAX
     # . epilog
     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
     5d/pop-to-EBP
@@ -1977,17 +2011,57 @@ $emit-headers:end:
 
 emit-elf-header:  # out : (address buffered-file), segments : (address stream {string, segment-info}), labels : (address stream {string, label-info})
     # pseudocode
-    #   *Elf_e_entry = get(labels, "Entry")->address
+    #   *Elf_e_entry = get-or-insert(labels, "Entry")->address
     #   *Elf_e_phnum = segments->write / 20         # size of a row
-    #   write(out, Elf_header)
+    #   emit-hex-array(out, Elf_header)
     #
     # . prolog
     55/push-EBP
     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
     # . save registers
+    50/push-EAX
+    51/push-ECX
+    52/push-EDX  # just because we need to call idiv
+    # *Elf_e_entry = get-or-insert(labels, "Entry")->address
+    # . EAX = labels
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   0x10/disp8      .                 # copy *(EBP+16) to EAX
+    # . label-info/EAX = get-or-insert(labels, "Entry", row-size=16)
+    # . . push args
+    68/push  0x10/imm32/row-size
+    68/push  "Entry"/imm32
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
+    # . . call
+    e8/call  get-or-insert/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . EAX = label-info->address
+    8b/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(EAX+8) to EAX
+    # . *Elf_e_entry = EAX
+    89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Elf_e_entry/disp32                # copy EAX to *Elf_e_entry
+    # *Elf_e_phnum = segments->write / 0x20
+    # . EAX = segments
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   0xc/disp8       .                 # copy *(EBP+12) to EAX
+    # . len/EAX = segments->write
+    8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # copy *EAX to EAX
+    # . EAX = len / 0x20  (destroying EDX)
+    b9/copy-to-ECX  0x20/imm32
+    31/xor                          3/mod/direct    2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # clear EDX
+    f7          7/subop/idiv        3/mod/direct    1/rm32/ECX    .           .             .           .           .               .                 # divide EDX:EAX by ECX, storing quotient in EAX and remainder in EDX
+    # . *Elf_e_phnum = EAX
+    89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Elf_e_phnum/disp32                # copy EAX to *Elf_e_phnum
+    # emit-hex-array(out, Elf_header)
+    # . . push args
+    68/push  Elf_header/imm32
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  emit-hex-array/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
 $emit-elf-header:end:
-    # . reclaim locals
     # . restore registers
+    5a/pop-to-EDX
+    59/pop-to-ECX
+    58/pop-to-EAX
     # . epilog
     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
     5d/pop-to-EBP
@@ -2004,15 +2078,66 @@ emit-elf-program-header-entry:  # curr-segment : {string, segment-info}
     #     *Elf_p_flags = 5  # r-x
     #   else
     #     *Elf_p_flags = 6  # rw-
-    #   write(out, Elf_program_header_entry)
+    #   emit-hex-array(out, Elf_program_header_entry)
     #
     # . prolog
     55/push-EBP
     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
     # . save registers
+    50/push-EAX
+    56/push-ESI
+    # ESI = curr-segment
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(EBP+8) to EAX
+    # *Elf_p_offset = curr-segment->file-offset
+    # . EAX = curr-segment->file-offset
+    8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(ESI+8) to EAX
+    # . *Elf_p_offset = EAX
+    89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Elf_p_offset/disp32               # copy EAX to *Elf_p_offset
+    # *Elf_p_vaddr = curr-segment->address
+    # . EAX = curr-segment->address
+    8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ESI+4) to EAX
+    # . *Elf_p_vaddr = EAX
+    89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Elf_p_vaddr/disp32                # copy EAX to *Elf_p_vaddr
+    # *Elf_p_paddr = curr-segment->address
+    89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Elf_p_paddr/disp32                # copy EAX to *Elf_p_paddr
+    # *Elf_p_filesz = curr-segment->size
+    # . EAX = curr-segment->size
+    8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           0/r32/EAX   0xc/disp8       .                 # copy *(ESI+12) to EAX
+    # . *Elf_p_filesz = EAX
+    89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Elf_p_filesz/disp32               # copy EAX to *Elf_p_filesz
+    # *Elf_p_memsz = curr-segment->size
+    89/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/EAX   Elf_p_memsz/disp32                # copy EAX to *Elf_p_memsz
+    # if (!string-equal?(curr-segment->name, "code") goto next check
+    # . EAX = curr-segment->name
+    8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/EAX   .               .                 # copy *ESI to EAX
+    # . EAX = string-equal?(curr-segment->name, "code")
+    # . . push args
+    68/push  "code"/imm32
+    50/push-EAX
+    # . . call
+    e8/call  string-equal?/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . if (EAX == 0) goto next check
+    3d/compare-EAX-and  0/imm32
+    74/jump-if-equal  $emit-elf-program-header-entry:data/disp8
+    # *Elf_p_flags = rw-
+    c7          0/subop/copy        0/mod/indirect  5/rm32/.disp32            .             .           .           Elf_p_flags/disp32  6/imm32       # copy to *Elf_p_flags
+$emit-elf-program-header-entry:data:
+    # otherwise *Elf_p_flags = r-x
+    c7          0/subop/copy        0/mod/indirect  5/rm32/.disp32            .             .           .           Elf_p_flags/disp32  5/imm32       # copy to *Elf_p_flags
+    # emit-hex-array(out, Elf_program_header_entry)
+    # . . push args
+    68/push  Elf_program_header_entry/imm32
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  emit-hex-array/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
 $emit-elf-program-header-entry:end:
-    # . reclaim locals
     # . restore registers
+    5e/pop-to-ESI
+    58/pop-to-EAX
     # . epilog
     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
     5d/pop-to-EBP