start throwing error on duplicate label
One less error that's only in the bootstrap phase. On the other hand, for simplicity I got rid of the ability to override the Entry label. One less special case, but we're also going further from the ability to run subsets of layers. We haven't really been exercising it for a long time, though (commit 7842, March 2021 when we made baremetal the default).
This commit is contained in:
parent
b41aed4a9a
commit
827dd4a7fe
|
@ -5,9 +5,9 @@
|
|||
# . op subop mod rm32 base index scale r32
|
||||
# . 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
|
||||
|
||||
Entry: # just exit; can't test _write just yet
|
||||
bb/copy-to-ebx 0/imm32
|
||||
e8/call syscall_exit/disp32
|
||||
#? Entry: # just exit; can't test _write just yet
|
||||
#? bb/copy-to-ebx 0/imm32
|
||||
#? e8/call syscall_exit/disp32
|
||||
|
||||
_write: # fd: int, s: (addr array byte)
|
||||
# . prologue
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
# . op subop mod rm32 base index scale r32
|
||||
# . 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
|
||||
|
||||
Entry: # manual test
|
||||
# check-ints-equal(34, 34)
|
||||
# . . push args
|
||||
68/push "error in check-ints-equal"/imm32
|
||||
68/push 34/imm32
|
||||
68/push 34/imm32
|
||||
# . . call
|
||||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
||||
# syscall_exit(0)
|
||||
bb/copy-to-ebx 0/imm32
|
||||
e8/call syscall_exit/disp32
|
||||
#? Entry: # manual test
|
||||
#? # check-ints-equal(34, 34)
|
||||
#? # . . push args
|
||||
#? 68/push "error in check-ints-equal"/imm32
|
||||
#? 68/push 34/imm32
|
||||
#? 68/push 34/imm32
|
||||
#? # . . call
|
||||
#? e8/call check-ints-equal/disp32
|
||||
#? # . . discard args
|
||||
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
||||
#? # syscall_exit(0)
|
||||
#? bb/copy-to-ebx 0/imm32
|
||||
#? e8/call syscall_exit/disp32
|
||||
|
||||
# print msg to stderr if a != b, otherwise print "."
|
||||
check-ints-equal: # a: int, b: int, msg: (addr array byte)
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
# . op subop mod rm32 base index scale r32
|
||||
# . 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
|
||||
|
||||
Entry: # run all tests
|
||||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
# syscall_exit(Num-test-failures)
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx
|
||||
e8/call syscall_exit/disp32
|
||||
#? Entry: # run all tests
|
||||
#? e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
#? # syscall_exit(Num-test-failures)
|
||||
#? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx
|
||||
#? e8/call syscall_exit/disp32
|
||||
|
||||
kernel-string-equal?: # s: (addr kernel-string), benchmark: (addr array byte) -> result/eax: boolean
|
||||
# pseudocode:
|
||||
|
|
|
@ -16,26 +16,26 @@
|
|||
# . op subop mod rm32 base index scale r32
|
||||
# . 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
|
||||
|
||||
Entry: # manual test
|
||||
# var ad/ecx: allocation-descriptor
|
||||
68/push 0/imm32/limit
|
||||
68/push 0/imm32/curr
|
||||
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
||||
# new-segment(0x1000, ad)
|
||||
# . . push args
|
||||
51/push-ecx
|
||||
68/push 0x1000/imm32
|
||||
# . . call
|
||||
e8/call new-segment/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# var eax: (addr _) = ad->curr
|
||||
8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax
|
||||
# write to *eax to check that we have access to the newly-allocated segment
|
||||
c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0x34/imm32 # copy to *eax
|
||||
# syscall_exit(eax)
|
||||
89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx
|
||||
e8/call syscall_exit/disp32
|
||||
#? Entry: # manual test
|
||||
#? # var ad/ecx: allocation-descriptor
|
||||
#? 68/push 0/imm32/limit
|
||||
#? 68/push 0/imm32/curr
|
||||
#? 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
||||
#? # new-segment(0x1000, ad)
|
||||
#? # . . push args
|
||||
#? 51/push-ecx
|
||||
#? 68/push 0x1000/imm32
|
||||
#? # . . call
|
||||
#? e8/call new-segment/disp32
|
||||
#? # . . discard args
|
||||
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
#? # var eax: (addr _) = ad->curr
|
||||
#? 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax
|
||||
#? # write to *eax to check that we have access to the newly-allocated segment
|
||||
#? c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0x34/imm32 # copy to *eax
|
||||
#? # syscall_exit(eax)
|
||||
#? 89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx
|
||||
#? e8/call syscall_exit/disp32
|
||||
|
||||
new-segment: # len: int, ad: (addr allocation-descriptor)
|
||||
# . prologue
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
# . op subop mod rm32 base index scale r32
|
||||
# . 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
|
||||
|
||||
Entry: # run all tests
|
||||
#? e8/call test-compare-equal-strings/disp32
|
||||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
# syscall_exit(Num-test-failures)
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx
|
||||
e8/call syscall_exit/disp32
|
||||
#? Entry: # run all tests
|
||||
#? #? e8/call test-compare-equal-strings/disp32
|
||||
#? e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
#? # syscall_exit(Num-test-failures)
|
||||
#? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx
|
||||
#? e8/call syscall_exit/disp32
|
||||
|
||||
string-equal?: # s: (addr array byte), benchmark: (addr array byte) -> result/eax: boolean
|
||||
# pseudocode:
|
||||
|
|
|
@ -42,18 +42,18 @@ Next-alloc-id: # int
|
|||
# . op subop mod rm32 base index scale r32
|
||||
# . 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
|
||||
|
||||
# Let's start initializing the default allocation descriptor.
|
||||
|
||||
Entry:
|
||||
# initialize heap
|
||||
# . Heap = new-segment(Heap-size)
|
||||
# . . push args
|
||||
68/push Heap/imm32
|
||||
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size
|
||||
# . . call
|
||||
e8/call new-segment/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
#? # Let's start initializing the default allocation descriptor.
|
||||
#?
|
||||
#? Entry:
|
||||
#? # initialize heap
|
||||
#? # . Heap = new-segment(Heap-size)
|
||||
#? # . . push args
|
||||
#? 68/push Heap/imm32
|
||||
#? ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size
|
||||
#? # . . call
|
||||
#? e8/call new-segment/disp32
|
||||
#? # . . discard args
|
||||
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
|
||||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
$array-equal-main:end:
|
||||
|
|
|
@ -700,6 +700,154 @@ $test-get-or-insert:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
# save 'key' to the next available row
|
||||
# if key already exists, abort
|
||||
# if there are no rows free, abort
|
||||
# return the address of the value
|
||||
insert-or-abort: # table: (addr stream {(handle array byte), T}), key: (addr array byte), row-size: int, ad: (addr allocation-descriptor) -> result/eax: (addr T)
|
||||
# pseudocode:
|
||||
# curr = table->data
|
||||
# max = &table->data[table->write]
|
||||
# while curr < max
|
||||
# var c: (addr array byte) = lookup(*curr)
|
||||
# if string-equal?(key, c)
|
||||
# abort
|
||||
# curr += row-size
|
||||
# if table->write >= table->size
|
||||
# abort
|
||||
# zero-out(max, row-size)
|
||||
# copy-array(ad, key, max)
|
||||
# table->write += row-size
|
||||
# return max+8
|
||||
#
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
||||
# . save registers
|
||||
51/push-ecx
|
||||
52/push-edx
|
||||
56/push-esi
|
||||
# esi = table
|
||||
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
|
||||
# var curr/ecx: (addr handle array byte) = table->data
|
||||
8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx
|
||||
# var max/edx: (addr byte) = &table->data[table->write]
|
||||
8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx
|
||||
$insert-or-abort:search-loop:
|
||||
# if (curr >= max) break
|
||||
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
|
||||
73/jump-if-addr>= $insert-or-abort:not-found/disp8
|
||||
# var c/eax: (addr array byte) = lookup(*curr)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4)
|
||||
ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx
|
||||
# . . call
|
||||
e8/call lookup/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# if (string-equal?(key, c)) abort
|
||||
# . eax = string-equal?(key, c)
|
||||
# . . push args
|
||||
50/push-eax
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
||||
# . . 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) abort
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 85/jump-if-!= $insert-or-abort:error-duplicate/disp32
|
||||
# curr += row-size
|
||||
03/add 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # add *(ebp+16) to ecx
|
||||
# loop
|
||||
eb/jump $insert-or-abort:search-loop/disp8
|
||||
$insert-or-abort:not-found:
|
||||
# if (table->write >= table->size) abort
|
||||
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
|
||||
3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(esi+8)
|
||||
0f 83/jump-if-addr>= $insert-or-abort:error-full/disp32
|
||||
# zero-out(max, row-size)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
|
||||
52/push-edx
|
||||
# . . call
|
||||
e8/call zero-out/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# copy-array(ad, key, max)
|
||||
# . . push args
|
||||
52/push-edx
|
||||
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 . . . . 0x14/disp8 . # push *(ebp+20)
|
||||
# . . call
|
||||
e8/call copy-array/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
||||
# table->write += row-size
|
||||
# . eax = row-size
|
||||
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
|
||||
# . table->write += eax
|
||||
01/add 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # add eax to *esi
|
||||
# return max+8
|
||||
# . eax = max
|
||||
89/copy 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # copy edx to eax
|
||||
# . eax += 8
|
||||
05/add-to-eax 8/imm32
|
||||
$insert-or-abort:end:
|
||||
# . restore registers
|
||||
5e/pop-to-esi
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
# . epilogue
|
||||
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
$insert-or-abort:error-duplicate:
|
||||
# . _write(2/stderr, error)
|
||||
# . . push args
|
||||
68/push "insert-or-abort: key already exists: "/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(2/stderr, key)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
||||
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(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
|
||||
# . syscall_exit(1)
|
||||
bb/copy-to-ebx 1/imm32
|
||||
e8/call syscall_exit/disp32
|
||||
# never gets here
|
||||
|
||||
$insert-or-abort:error-full:
|
||||
# . _write(2/stderr, error)
|
||||
# . . push args
|
||||
68/push "insert-or-abort: table is full\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
|
||||
# . syscall_exit(1)
|
||||
bb/copy-to-ebx 1/imm32
|
||||
e8/call syscall_exit/disp32
|
||||
# never gets here
|
||||
|
||||
# if no row is found, save 'key' to the next available row
|
||||
# if there are no rows free, abort
|
||||
# return the address of the value
|
||||
|
@ -1321,6 +1469,169 @@ $test-get-or-insert-slice:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
# if no row is found, save 'key' in the next available row
|
||||
# if there are no rows free, abort
|
||||
insert-slice-or-abort: # table: (addr stream {(handle array byte), T}), key: (addr slice), row-size: int, ad: (addr allocation-descriptor) -> result/eax: (addr T)
|
||||
# pseudocode:
|
||||
# curr = table->data
|
||||
# max = &table->data[table->write]
|
||||
# while curr < max
|
||||
# var c: (addr array byte) = lookup(*curr)
|
||||
# if slice-equal?(key, *curr)
|
||||
# return curr+8
|
||||
# curr += row-size
|
||||
# if table->write >= table->size
|
||||
# abort
|
||||
# zero-out(max, row-size)
|
||||
# slice-to-string(ad, key, max)
|
||||
# table->write += row-size
|
||||
# return max+8
|
||||
#
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
||||
# . save registers
|
||||
51/push-ecx
|
||||
52/push-edx
|
||||
56/push-esi
|
||||
# esi = table
|
||||
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
|
||||
# var curr/ecx: (addr handle array byte) = table->data
|
||||
8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx
|
||||
# var max/edx: (addr byte) = &table->data[table->write]
|
||||
8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx
|
||||
$insert-slice-or-abort:search-loop:
|
||||
# if (curr >= max) break
|
||||
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
|
||||
73/jump-if-addr>= $insert-slice-or-abort:not-found/disp8
|
||||
# var c/eax: (addr array byte) = lookup(*curr)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4)
|
||||
ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx
|
||||
# . . call
|
||||
e8/call lookup/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# if (slice-equal?(key, c)) abort
|
||||
# . eax = slice-equal?(key, c)
|
||||
# . . push args
|
||||
50/push-eax
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
||||
# . . 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) abort
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 85/jump-if-!= $insert-slice-or-abort:error-duplicate/disp32
|
||||
# curr += row-size
|
||||
03/add 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # add *(ebp+16) to ecx
|
||||
# loop
|
||||
eb/jump $insert-slice-or-abort:search-loop/disp8
|
||||
$insert-slice-or-abort:not-found:
|
||||
# result/eax = 0
|
||||
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
|
||||
# if (table->write >= table->size) abort
|
||||
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
|
||||
3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(esi+8)
|
||||
0f 8d/jump-if->= $insert-slice-or-abort:error-full/disp32
|
||||
# zero-out(max, row-size)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
|
||||
52/push-edx
|
||||
# . . call
|
||||
e8/call zero-out/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# slice-to-string(ad, key, max)
|
||||
# . . push args
|
||||
52/push-edx
|
||||
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 . . . . 0x14/disp8 . # push *(ebp+20)
|
||||
# . . call
|
||||
e8/call slice-to-string/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
||||
# table->write += row-size
|
||||
# . eax = row-size
|
||||
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
|
||||
# . table->write += eax
|
||||
01/add 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # add eax to *esi
|
||||
# return max+8
|
||||
# . eax = max
|
||||
89/copy 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # copy edx to eax
|
||||
# . eax += 8
|
||||
05/add-to-eax 8/imm32
|
||||
$insert-slice-or-abort:end:
|
||||
# . restore registers
|
||||
5e/pop-to-esi
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
# . epilogue
|
||||
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
$insert-slice-or-abort:error-duplicate:
|
||||
# . flush(Stderr)
|
||||
# . . push args
|
||||
68/push Stderr/imm32
|
||||
# . . call
|
||||
e8/call flush/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
||||
# . _write(2/stderr, error)
|
||||
# . . push args
|
||||
68/push "insert-slice-or-abort: key already exists: "/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-slice-buffered(Stderr, key)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
||||
68/push Stderr/imm32
|
||||
# . . call
|
||||
e8/call write-slice-buffered/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
# . flush(Stderr)
|
||||
# . . push args
|
||||
68/push Stderr/imm32
|
||||
# . . call
|
||||
e8/call flush/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/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
|
||||
# . syscall_exit(1)
|
||||
bb/copy-to-ebx 1/imm32
|
||||
e8/call syscall_exit/disp32
|
||||
# never gets here
|
||||
|
||||
$insert-slice-or-abort:error-full:
|
||||
# . _write(2/stderr, error)
|
||||
# . . push args
|
||||
68/push "insert-slice-or-abort: table is full\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
|
||||
# . syscall_exit(1)
|
||||
bb/copy-to-ebx 1/imm32
|
||||
e8/call syscall_exit/disp32
|
||||
# never gets here
|
||||
|
||||
|
||||
# if no row is found, stop(ed)
|
||||
get-or-stop: # table: (addr stream {(handle array byte), T}), key: (addr array byte), row-size: int,
|
||||
# abort-message-prefix: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor)
|
||||
|
|
BIN
linux/assort
BIN
linux/assort
Binary file not shown.
BIN
linux/braces
BIN
linux/braces
Binary file not shown.
BIN
linux/calls
BIN
linux/calls
Binary file not shown.
BIN
linux/dquotes
BIN
linux/dquotes
Binary file not shown.
Binary file not shown.
|
@ -216,7 +216,7 @@ load-labels: # in: (addr buffered-file), labels: (stream {label-name, address}
|
|||
# read-line-buffered(in, line)
|
||||
# if (line->write == 0) break # end of file
|
||||
# var word-slice/ecx: (addr slice) = next-word(line)
|
||||
# var dest/edi: (addr int) = get-or-insert-slice(labels, word-slice, 12 bytes/row)
|
||||
# var dest/edi: (addr int) = insert-slice-or-abort(labels, word-slice, 12 bytes/row)
|
||||
# word-slice = next-word(line)
|
||||
# var address/eax: int = parse-hex-int-from-slice(word-slice)
|
||||
# *dest = address
|
||||
|
@ -333,15 +333,15 @@ $load-labels:loop:
|
|||
#? # . . discard args
|
||||
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
||||
#? # }}}
|
||||
# var dest/edi: (addr int) = get-or-insert-slice(labels, word-slice, 12 bytes/row, Heap)
|
||||
# . eax = get-or-insert-slice(labels, word-slice, 12 bytes/row, Heap)
|
||||
# var dest/edi: (addr int) = insert-slice-or-abort(labels, word-slice, 12 bytes/row, Heap)
|
||||
# . eax = insert-slice-or-abort(labels, word-slice, 12 bytes/row, Heap)
|
||||
# . . push args
|
||||
68/push Heap/imm32
|
||||
68/push 0xc/imm32/row-size
|
||||
52/push-edx
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
||||
# . . call
|
||||
e8/call get-or-insert-slice/disp32
|
||||
e8/call insert-slice-or-abort/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
|
||||
# . edi = eax
|
||||
|
|
BIN
linux/pack
BIN
linux/pack
Binary file not shown.
BIN
linux/sigils
BIN
linux/sigils
Binary file not shown.
Binary file not shown.
|
@ -468,6 +468,8 @@ compute-addresses: # in: (addr stream byte), labels: (addr stream {(handle arra
|
|||
# current-address = new-address
|
||||
# else if label?(word-slice)
|
||||
# strip trailing ':' from word-slice
|
||||
# var tmp/eax: (addr int) = insert-slice-or-abort(labels, word-slice)
|
||||
# *tmp = current-address
|
||||
# trace("label '" word-slice "' is at address " current-address ".")
|
||||
# # labels occupy no space, so no need to increment offsets
|
||||
# else
|
||||
|
@ -661,14 +663,14 @@ $compute-addresses:case-label:
|
|||
0f 84/jump-if-= $compute-addresses:case-default/disp32
|
||||
# strip trailing ':' from word-slice
|
||||
ff 1/subop/decrement 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # decrement *(edx+4)
|
||||
# var tmp/eax: (addr int) = get-or-insert-slice(labels, word-slice, row-size=12)
|
||||
# var tmp/eax: (addr int) = insert-slice-or-abort(labels, word-slice, row-size=12)
|
||||
# . . push args
|
||||
68/push Heap/imm32
|
||||
68/push 0xc/imm32/row-size
|
||||
52/push-edx
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
|
||||
# . . call
|
||||
e8/call get-or-insert-slice/disp32
|
||||
e8/call insert-slice-or-abort/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
|
||||
# *tmp = current-address
|
||||
|
|
BIN
linux/survey_elf
BIN
linux/survey_elf
Binary file not shown.
|
@ -451,7 +451,7 @@ compute-offsets: # in: (addr stream byte), segments: (addr stream {(handle arra
|
|||
# break (next line)
|
||||
# else if label?(word-slice)
|
||||
# strip trailing ':' from word-slice
|
||||
# linfo: (addr label-info) = get-or-insert-slice(labels, word-slice)
|
||||
# linfo: (addr label-info) = insert-slice-or-abort(labels, word-slice)
|
||||
# linfo->segment-name = curr-segment-name
|
||||
# trace("label '", word-slice, "' is in segment '", curr-segment-name, "'.")
|
||||
# linfo->segment-offset = segment-offset
|
||||
|
@ -753,15 +753,15 @@ $compute-offsets:case-label:
|
|||
0f 84/jump-if-= $compute-offsets:case-default/disp32
|
||||
# strip trailing ':' from word-slice
|
||||
ff 1/subop/decrement 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # decrement *(edx+4)
|
||||
# linfo/edi = get-or-insert-slice(labels, word-slice, row-size=24)
|
||||
# . eax = get-or-insert-slice(labels, word-slice, row-size=24)
|
||||
# linfo/edi = insert-slice-or-abort(labels, word-slice, row-size=24)
|
||||
# . eax = insert-slice-or-abort(labels, word-slice, row-size=24)
|
||||
# . . push args
|
||||
68/push Heap/imm32
|
||||
68/push 0x18/imm32/row-size
|
||||
52/push-edx
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
|
||||
# . . call
|
||||
e8/call get-or-insert-slice/disp32
|
||||
e8/call insert-slice-or-abort/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
|
||||
# . edi = eax
|
||||
|
|
|
@ -227,7 +227,7 @@ test "$1" = 'record' || git diff --exit-code sigils
|
|||
}
|
||||
|
||||
echo calls
|
||||
cat [012]*.subx subx-params.subx calls.subx | sigils > a.sigils
|
||||
cat [012]*.subx subx-params.subx calls.subx | ./sigils > a.sigils
|
||||
bootstrap/bootstrap translate a.sigils -o calls
|
||||
test "$1" = 'record' || git diff --exit-code calls
|
||||
{
|
||||
|
@ -241,7 +241,7 @@ test "$1" = 'record' || git diff --exit-code calls
|
|||
}
|
||||
|
||||
echo braces
|
||||
cat [012]*.subx subx-params.subx braces.subx | calls | sigils > a.sigils
|
||||
cat [012]*.subx subx-params.subx braces.subx | ./calls | ./sigils > a.sigils
|
||||
bootstrap/bootstrap translate a.sigils -o braces
|
||||
test "$1" = 'record' || git diff --exit-code braces
|
||||
{
|
||||
|
@ -255,7 +255,7 @@ test "$1" = 'record' || git diff --exit-code braces
|
|||
}
|
||||
|
||||
echo mu
|
||||
cat [0-2]*.subx mu.subx | braces | calls | sigils > a.sigils
|
||||
cat [0-2]*.subx mu.subx | ./braces | ./calls | ./sigils > a.sigils
|
||||
bootstrap/bootstrap translate a.sigils -o mu
|
||||
test "$1" = 'record' || git diff --exit-code mu
|
||||
{
|
||||
|
|
BIN
linux/tests
BIN
linux/tests
Binary file not shown.
4
subx.md
4
subx.md
|
@ -138,10 +138,6 @@ Functions are called using the following syntax:
|
|||
Function arguments must be either literals (integers or strings) or a reg/mem
|
||||
operand using the syntax in the previous section.
|
||||
|
||||
A special label on Linux is `Entry`, which can be used to specify/override the
|
||||
entry point of the program. It doesn't have to be unique, and the latest
|
||||
definition will override earlier ones.
|
||||
|
||||
Another special pair of labels are the block delimiters `{` and `}`. They can
|
||||
be nested, and jump instructions can take arguments `loop` or `break` that
|
||||
jump to the enclosing `{` and `}` respectively.
|
||||
|
|
Loading…
Reference in New Issue
Block a user