parent
8836afbcbd
commit
c88af82232
BIN
apps/survey_elf
BIN
apps/survey_elf
Binary file not shown.
|
@ -1839,6 +1839,8 @@ emit-segments: # in: (addr stream byte), out: (addr buffered-file), labels: (ad
|
|||
# read-line(in, line)
|
||||
# if (line->write == 0) break # end of file
|
||||
# offset-of-next-instruction += num-bytes(line)
|
||||
# var is-far-jump-or-call? = is-far-jump-or-call?(line)
|
||||
# rewind-stream(line)
|
||||
# while true
|
||||
# var word-slice = next-word(line)
|
||||
# if slice-empty?(word-slice) # end of line
|
||||
|
@ -1855,22 +1857,18 @@ emit-segments: # in: (addr stream byte), out: (addr buffered-file), labels: (ad
|
|||
# continue
|
||||
# var datum: (addr slice) = next-token-from-slice(word-slice->start, word-slice->end, "/")
|
||||
# var info: (addr label-info) = get-slice(labels, datum)
|
||||
# if !string-equal?(info->segment-name, "code")
|
||||
# if has-metadata?(word-slice, "disp8")
|
||||
# abort
|
||||
# if has-metadata?(word-slice, "imm8")
|
||||
# abort
|
||||
# emit(out, info->address, 4) # global variables always translate to absolute addresses
|
||||
# # code segment cases
|
||||
# else if has-metadata?(word-slice, "imm8")
|
||||
# abort # label should never go to imm8
|
||||
# if has-metadata?(word-slice, "imm8")
|
||||
# abort
|
||||
# else if has-metadata?(word-slice, "imm32")
|
||||
# emit(out, info->address, 4)
|
||||
# else if has-metadata?(word-slice, "disp8")
|
||||
# value = info->offset - offset-of-next-instruction
|
||||
# emit(out, value, 1)
|
||||
# else if has-metadata?(word-slice, "disp32")
|
||||
# value = info->offset - offset-of-next-instruction
|
||||
# if is-far-jump-or-call?
|
||||
# value = info->offset - offset-of-next-instruction
|
||||
# else
|
||||
# value = info->address
|
||||
# emit(out, value, 4)
|
||||
# else
|
||||
# abort
|
||||
|
@ -1880,6 +1878,7 @@ emit-segments: # in: (addr stream byte), out: (addr buffered-file), labels: (ad
|
|||
# line: ecx
|
||||
# word-slice: edx
|
||||
# offset-of-next-instruction: ebx
|
||||
# is-far-jump-or-call?: edi
|
||||
# info: esi (inner loop only)
|
||||
# temporaries: eax, esi (outer loop)
|
||||
#
|
||||
|
@ -1968,6 +1967,20 @@ $emit-segments:check-for-end-of-input:
|
|||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
||||
# . ebx += eax
|
||||
01/add 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # add eax to ebx
|
||||
# var is-far-jump-or-call?/edi: boolean = is-far-jump-or-call?(line)
|
||||
# . . push args
|
||||
51/push-ecx
|
||||
# . . call
|
||||
e8/call is-far-jump-or-call?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
||||
# rewind-stream(line)
|
||||
# . . push args
|
||||
51/push-ecx
|
||||
# . . call
|
||||
e8/call rewind-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
||||
$emit-segments:word-loop:
|
||||
# next-word(line, word-slice)
|
||||
# . . push args
|
||||
|
@ -2141,66 +2154,7 @@ $emit-segments:check-metadata:
|
|||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
|
||||
# . esi = eax
|
||||
89/copy 3/mod/direct 6/rm32/esi . . . 0/r32/eax . . # copy eax to esi
|
||||
$emit-segments:check-global-variable:
|
||||
# if string-equal?(info->segment-name, "code") goto code label checks
|
||||
# . eax = lookup(info->segment-name)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4)
|
||||
ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi
|
||||
# . . call
|
||||
e8/call lookup/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . eax = string-equal?(eax, "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 != false) goto code label checks
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 85/jump-if-!= $emit-segments:check-code-label-for-imm8/disp32
|
||||
$emit-segments:check-global-variable-for-disp8:
|
||||
# if has-metadata?(word-slice, "disp8") abort
|
||||
# . eax = has-metadata?(word-slice, "disp8")
|
||||
# . . push args
|
||||
68/push "disp8"/imm32
|
||||
52/push-edx
|
||||
# . . call
|
||||
e8/call has-metadata?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . if (eax != false) abort
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 85/jump-if-!= $emit-segments:global-variable-abort/disp32
|
||||
$emit-segments:check-global-variable-for-imm8:
|
||||
# if has-metadata?(word-slice, "imm8") abort
|
||||
# . eax = has-metadata?(word-slice, "imm8")
|
||||
# . . push args
|
||||
68/push "imm8"/imm32
|
||||
52/push-edx
|
||||
# . . call
|
||||
e8/call has-metadata?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . if (eax != false) abort
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 85/jump-if-!= $emit-segments:global-variable-abort/disp32
|
||||
$emit-segments:emit-global-variable:
|
||||
# emit-hex(out, info->address, 4)
|
||||
# . . push args
|
||||
68/push 4/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 0xc/disp8 . # push *(esi+12)
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
||||
# . . call
|
||||
e8/call emit-hex/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
||||
# continue
|
||||
e9/jump $emit-segments:word-loop/disp32
|
||||
$emit-segments:check-code-label-for-imm8:
|
||||
$emit-segments:check-imm8:
|
||||
# if (has-metadata?(word-slice, "imm8")) abort
|
||||
# . eax = has-metadata?(edx, "imm8")
|
||||
# . . push args
|
||||
|
@ -2213,7 +2167,7 @@ $emit-segments:check-code-label-for-imm8:
|
|||
# . if (eax != false) abort
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 85/jump-if-!= $emit-segments:imm8-abort/disp32
|
||||
$emit-segments:check-code-label-for-imm32:
|
||||
$emit-segments:check-imm32:
|
||||
# if (!has-metadata?(word-slice, "imm32")) goto next check
|
||||
# . eax = has-metadata?(edx, "imm32")
|
||||
# . . push args
|
||||
|
@ -2225,7 +2179,7 @@ $emit-segments:check-code-label-for-imm32:
|
|||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . if (eax == false) goto next check
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
74/jump-if-= $emit-segments:check-code-label-for-disp8/disp8
|
||||
74/jump-if-= $emit-segments:check-disp8/disp8
|
||||
#? # dump info->address {{{
|
||||
#? # . write(2/stderr, "info->address: ")
|
||||
#? # . . push args
|
||||
|
@ -2259,7 +2213,7 @@ $emit-segments:check-code-label-for-imm32:
|
|||
#? # . . discard args
|
||||
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
#? # }}}
|
||||
$emit-segments:emit-code-label-imm32:
|
||||
$emit-segments:emit-imm32:
|
||||
# emit-hex(out, info->address, 4)
|
||||
# . . push args
|
||||
68/push 4/imm32
|
||||
|
@ -2271,7 +2225,7 @@ $emit-segments:emit-code-label-imm32:
|
|||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
||||
# continue
|
||||
e9/jump $emit-segments:word-loop/disp32
|
||||
$emit-segments:check-code-label-for-disp8:
|
||||
$emit-segments:check-disp8:
|
||||
# if (!has-metadata?(word-slice, "disp8")) goto next check
|
||||
# . eax = has-metadata?(edx, "disp8")
|
||||
# . . push args
|
||||
|
@ -2283,8 +2237,8 @@ $emit-segments:check-code-label-for-disp8:
|
|||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . if (eax == false) goto next check
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
74/jump-if-= $emit-segments:check-code-label-for-disp32/disp8
|
||||
$emit-segments:emit-code-label-disp8:
|
||||
74/jump-if-= $emit-segments:check-disp32/disp8
|
||||
$emit-segments:emit-disp8:
|
||||
# emit-hex(out, info->offset - offset-of-next-instruction, 1)
|
||||
# . . push args
|
||||
68/push 1/imm32
|
||||
|
@ -2298,7 +2252,7 @@ $emit-segments:emit-code-label-disp8:
|
|||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
||||
# continue
|
||||
e9/jump $emit-segments:word-loop/disp32
|
||||
$emit-segments:check-code-label-for-disp32:
|
||||
$emit-segments:check-disp32:
|
||||
# if (!has-metadata?(word-slice, "disp32")) abort
|
||||
# . eax = has-metadata?(edx, "disp32")
|
||||
# . . push args
|
||||
|
@ -2311,12 +2265,18 @@ $emit-segments:check-code-label-for-disp32:
|
|||
# . if (eax == false) abort
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 84/jump-if-= $emit-segments:abort/disp32
|
||||
$emit-segments:emit-code-label-disp32:
|
||||
# emit-hex(out, info->offset - offset-of-next-instruction, 4)
|
||||
# . . push args
|
||||
68/push 4/imm32
|
||||
$emit-segments:emit-disp32:
|
||||
# var value/eax = info->address
|
||||
8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 0xc/disp8 . # copy *(esi+12) to eax
|
||||
# if (is-far-jump-or-call?) value = info->offset - offset-of-next-instruction
|
||||
81 7/subop/compare 3/mod/direct 7/rm32/edi . . . . . 0/imm32/false # compare edi
|
||||
74/jump-if-= $emit-segments:really-emit-disp32/disp8
|
||||
8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 8/disp8 . # copy *(esi+8) to eax
|
||||
29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax
|
||||
$emit-segments:really-emit-disp32:
|
||||
# emit-hex(out, value, 4)
|
||||
# . . push args
|
||||
68/push 4/imm32
|
||||
50/push-eax
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
||||
# . . call
|
||||
|
@ -2409,8 +2369,8 @@ $emit-segments:abort:
|
|||
e8/call syscall_exit/disp32
|
||||
# never gets here
|
||||
|
||||
test-emit-segments-global-variable:
|
||||
# global variables always convert to absolute addresses, regardless of metadata
|
||||
test-emit-segments-non-far-control-flow:
|
||||
# labels turn into absolute addresses if opcodes are not far jumps or calls
|
||||
#
|
||||
# input:
|
||||
# in:
|
||||
|
@ -2640,7 +2600,7 @@ test-emit-segments-global-variable:
|
|||
c3/return
|
||||
|
||||
test-emit-segments-code-label:
|
||||
# labels usually convert to displacements
|
||||
# labels turn into PC-relative addresses if opcodes are far jumps or calls
|
||||
#
|
||||
# input:
|
||||
# in:
|
||||
|
@ -2648,14 +2608,14 @@ test-emit-segments-code-label:
|
|||
# ab cd
|
||||
# l1:
|
||||
# ef gh
|
||||
# ij l1/disp32
|
||||
# e8 l1/disp32
|
||||
# labels:
|
||||
# - 'l1': {'code', 2, 0x1056}
|
||||
#
|
||||
# output:
|
||||
# ab cd
|
||||
# ef gh
|
||||
# ij f9 ff ff ff # -7
|
||||
# e8 f9 ff ff ff # -7
|
||||
#
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
|
@ -2725,9 +2685,9 @@ test-emit-segments-code-label:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . write(_test-input-stream, " ij l1/disp32\n")
|
||||
# . write(_test-input-stream, " e8 l1/disp32\n")
|
||||
# . . push args
|
||||
68/push " ij l1/disp32\n"/imm32
|
||||
68/push " e8 l1/disp32\n"/imm32
|
||||
68/push _test-input-stream/imm32
|
||||
# . . call
|
||||
e8/call write/disp32
|
||||
|
@ -2827,10 +2787,10 @@ test-emit-segments-code-label:
|
|||
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
|
||||
# . check-next-stream-line-equal(_test-output-stream, "ij f9 ff ff ff ", msg)
|
||||
# . check-next-stream-line-equal(_test-output-stream, "e8 f9 ff ff ff ", msg)
|
||||
# . . push args
|
||||
68/push "F - test-emit-segments-code-label/2"/imm32
|
||||
68/push "ij f9 ff ff ff "/imm32
|
||||
68/push "e8 f9 ff ff ff "/imm32
|
||||
68/push _test-output-stream/imm32
|
||||
# . . call
|
||||
e8/call check-next-stream-line-equal/disp32
|
||||
|
@ -3043,6 +3003,140 @@ test-emit-segments-code-label-absolute:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
# reads line to make some checks
|
||||
# don't assume the read state of line after calling this function
|
||||
is-far-jump-or-call?: # line: (addr stream byte) -> result/edi: boolean
|
||||
# . prologue
|
||||
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
|
||||
53/push-ebx
|
||||
# ecx = line
|
||||
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
|
||||
# var word-slice/edx: slice
|
||||
68/push 0/imm32/end
|
||||
68/push 0/imm32/start
|
||||
89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx
|
||||
# var datum-slice/ebx: slice
|
||||
68/push 0/imm32/end
|
||||
68/push 0/imm32/start
|
||||
89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx
|
||||
# result = false
|
||||
bf/copy-to-edi 0/imm32/false
|
||||
$is-far-jump-or-call?:check-first-word:
|
||||
# next-word(line, word-slice)
|
||||
# . . push args
|
||||
52/push-edx
|
||||
51/push-ecx
|
||||
# . . call
|
||||
e8/call next-word/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# if (slice-empty?(word-slice)) return false
|
||||
# . eax = slice-empty?(word-slice)
|
||||
# . . push args
|
||||
52/push-edx
|
||||
# . . call
|
||||
e8/call slice-empty?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
||||
# . if (eax != 0) return
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 85/jump-if-!= $is-far-jump-or-call?:end/disp32
|
||||
# datum = next-token-from-slice(word-slice->start, word-slice->end, "/")
|
||||
# . . push args
|
||||
53/push-ebx
|
||||
68/push 0x2f/imm32/slash
|
||||
ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4)
|
||||
ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx
|
||||
# . . call
|
||||
e8/call next-token-from-slice/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
|
||||
# if (datum-slice == "e8") return true
|
||||
# . eax = slice-equal?(datum-slice, "e8")
|
||||
# . . push args
|
||||
68/push "e8"/imm32
|
||||
53/push-ebx
|
||||
# . . call
|
||||
e8/call slice-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . if (eax != false) return true
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
75/jump-if-!= $is-far-jump-or-call?:return-true/disp8
|
||||
# if (datum-slice == "e9") return true
|
||||
# . eax = slice-equal?(datum-slice, "e9")
|
||||
# . . push args
|
||||
68/push "e9"/imm32
|
||||
53/push-ebx
|
||||
# . . call
|
||||
e8/call slice-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . if (eax != false) return true
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
75/jump-if-!= $is-far-jump-or-call?:return-true/disp8
|
||||
# if (datum-slice != "0f") return false
|
||||
# . eax = slice-equal?(datum-slice, "0f")
|
||||
# . . push args
|
||||
68/push "0f"/imm32
|
||||
53/push-ebx
|
||||
# . . call
|
||||
e8/call slice-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . if (eax == false) return
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
74/jump-if-= $is-far-jump-or-call?:end/disp8
|
||||
$is-far-jump-or-call?:check-second-word:
|
||||
# next-word(line, word-slice)
|
||||
# . . push args
|
||||
52/push-edx
|
||||
51/push-ecx
|
||||
# . . call
|
||||
e8/call next-word/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# if (slice-empty?(word-slice)) return false
|
||||
# . eax = slice-empty?(word-slice)
|
||||
# . . push args
|
||||
52/push-edx
|
||||
# . . call
|
||||
e8/call slice-empty?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
||||
# . if (eax != 0) return
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
75/jump-if-!= $is-far-jump-or-call?:end/disp8
|
||||
# if datum of word-slice does not start with "8", return false
|
||||
# . start/eax = word-slice->start
|
||||
8b/copy 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # copy *edx to eax
|
||||
# . c/eax = *start
|
||||
8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL
|
||||
81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax
|
||||
# . if (eax != '8') return
|
||||
3d/compare-eax-and 0x38/imm32/8
|
||||
75/jump-if-!= $is-far-jump-or-call?:end/disp8
|
||||
# otherwise return true
|
||||
$is-far-jump-or-call?:return-true:
|
||||
bf/copy-to-edi 1/imm32/true
|
||||
$is-far-jump-or-call?:end:
|
||||
# . reclaim locals
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
|
||||
# . restore registers
|
||||
5b/pop-to-ebx
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
58/pop-to-eax
|
||||
# . epilogue
|
||||
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
emit-headers: # out: (addr buffered-file), segments: (addr stream {(handle array byte), segment-info}), labels: (addr stream {(handle array byte), label-info})
|
||||
# pseudocode:
|
||||
# emit-elf-header(out, segments, labels)
|
||||
|
|
Loading…
Reference in New Issue