4808 - clean up comments in all subx files
This commit is contained in:
parent
4cb6970d9d
commit
9d27e966b5
|
@ -7,14 +7,17 @@
|
|||
|
||||
# main: (manual test if this is the last file loaded)
|
||||
# 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
|
||||
b8/copy-to-EAX 1/imm32
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# print msg to stderr if a != b, otherwise print "."
|
||||
|
@ -28,10 +31,10 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
|||
# load first 2 args into EAX and EBX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 0/r32/EAX 0x8/disp8 . # copy *(EBP+8) to EAX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX
|
||||
# if EAX == b/EBX
|
||||
# if EAX == EBX success
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
|
||||
75/jump-if-unequal $check-ints-equal:else/disp8
|
||||
# _write(2/stderr, '.')
|
||||
# . _write(2/stderr, '.')
|
||||
# . . push args
|
||||
68/push "."/imm32
|
||||
68/push 2/imm32/stderr
|
||||
|
@ -39,11 +42,11 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
|||
e8/call _write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# return
|
||||
# . return
|
||||
eb/jump $check-ints-equal:end/disp8
|
||||
# else:
|
||||
# otherwise print error message
|
||||
$check-ints-equal:else:
|
||||
# _write(2/stderr, msg)
|
||||
# . _write(2/stderr, msg)
|
||||
# . . push args
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX
|
||||
51/push-ECX
|
||||
|
@ -52,7 +55,7 @@ $check-ints-equal:else:
|
|||
e8/call _write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# _write(2/stderr, Newline)
|
||||
# . _write(2/stderr, Newline)
|
||||
# . . push args
|
||||
68/push Newline/imm32
|
||||
68/push 2/imm32/stderr
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Checking null-terminated ascii strings.
|
||||
# Checking null-terminated ascii strings.
|
||||
#
|
||||
# By default we create strings with a 4-byte length prefix rather than a null suffix.
|
||||
# However we still need null-prefixed strings when interacting with the Linux
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
# main:
|
||||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
# exit(Num-test-failures)
|
||||
# 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
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
@ -109,7 +109,7 @@ $kernel-string-equal:end:
|
|||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
## tests
|
||||
# - tests
|
||||
|
||||
test-compare-null-kernel-string-with-empty-array:
|
||||
# EAX = kernel-string-equal(Null-kernel-string, "")
|
||||
|
@ -120,7 +120,7 @@ test-compare-null-kernel-string-with-empty-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 1, msg)
|
||||
# check-ints-equal(EAX, 1, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
|
||||
68/push 1/imm32/true
|
||||
|
@ -140,7 +140,7 @@ test-compare-null-kernel-string-with-non-empty-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0, msg)
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -160,7 +160,7 @@ test-compare-kernel-string-with-equal-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 1, msg)
|
||||
# check-ints-equal(EAX, 1, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 1/imm32/true
|
||||
|
@ -180,7 +180,7 @@ test-compare-kernel-string-with-inequal-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0, msg)
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -200,7 +200,7 @@ test-compare-kernel-string-with-empty-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0)
|
||||
# check-ints-equal(EAX, 0)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -220,7 +220,7 @@ test-compare-kernel-string-with-shorter-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0)
|
||||
# check-ints-equal(EAX, 0)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -240,7 +240,7 @@ test-compare-kernel-string-with-longer-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0)
|
||||
# check-ints-equal(EAX, 0)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-longer-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
|
||||
# store to *EAX
|
||||
# write to *EAX to check that we have access to the newly-allocated segment
|
||||
c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0x34/imm32 # copy to *EAX
|
||||
|
||||
# exit(EAX)
|
||||
# syscall(exit, EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
# . 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
|
||||
|
||||
# main:
|
||||
# run-tests()
|
||||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
# exit(Num-test-failures)
|
||||
# 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
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
@ -84,7 +85,7 @@ $string-equal:end:
|
|||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
## tests
|
||||
# - tests
|
||||
|
||||
test-compare-empty-with-empty-string:
|
||||
# EAX = string-equal("", "")
|
||||
|
@ -95,7 +96,7 @@ test-compare-empty-with-empty-string:
|
|||
e8/call string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 1, msg)
|
||||
# check-ints-equal(EAX, 1, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-empty-with-empty-string"/imm32
|
||||
68/push 1/imm32/true
|
||||
|
@ -115,7 +116,7 @@ test-compare-empty-with-non-empty-string: # also checks length-mismatch code pa
|
|||
e8/call string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0, msg)
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-empty-with-non-empty-string"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -135,7 +136,7 @@ test-compare-equal-strings:
|
|||
e8/call string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 1, msg)
|
||||
# check-ints-equal(EAX, 1, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-equal-strings"/imm32
|
||||
68/push 1/imm32/true
|
||||
|
@ -155,7 +156,7 @@ test-compare-inequal-strings-equal-lengths:
|
|||
e8/call string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0, msg)
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-inequal-strings-equal-lengths"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
|
|
@ -43,6 +43,7 @@ _test-trace-stream:
|
|||
# . 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
|
||||
|
||||
# main:
|
||||
# run-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
|
||||
|
@ -87,12 +88,12 @@ trace: # t : (address trace-stream), line : string
|
|||
# EDX = t->length
|
||||
8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX
|
||||
# EAX = _append-3(&t->data[t->write], &t->data[t->length], line)
|
||||
# push line
|
||||
# . . push line
|
||||
56/push-ESI
|
||||
# push &t->data[t->length]
|
||||
# . . push &t->data[t->length]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 2/index/EDX . 3/r32/EBX 0xc/disp8 . # copy EDI+EDX+12 to EBX
|
||||
53/push-EBX
|
||||
# push &t->data[t->write]
|
||||
# . . push &t->data[t->write]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX
|
||||
53/push-EBX
|
||||
# . . call
|
||||
|
@ -107,12 +108,12 @@ trace: # t : (address trace-stream), line : string
|
|||
# refresh ECX = t->write
|
||||
8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX
|
||||
# EAX = _append-3(&t->data[t->write], &t->data[t->length], line)
|
||||
# push line
|
||||
# . . push line
|
||||
68/push Newline/imm32
|
||||
# push &t->data[t->length]
|
||||
# . . push &t->data[t->length]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 2/index/EDX . 3/r32/EBX 0xc/disp8 . # copy EDI+EDX+12 to EBX
|
||||
53/push-EBX
|
||||
# push &t->data[t->write]
|
||||
# . . push &t->data[t->write]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX
|
||||
53/push-EBX
|
||||
# . . call
|
||||
|
@ -172,7 +173,7 @@ $clear-trace-stream:end:
|
|||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
## tests
|
||||
# - tests
|
||||
|
||||
test-trace-single:
|
||||
# clear-trace-stream(_test-trace-stream)
|
||||
|
@ -194,7 +195,7 @@ test-trace-single:
|
|||
# . . push args
|
||||
68/push "F - test-trace-single"/imm32
|
||||
68/push 0x0a6241/imm32/Ab-newline
|
||||
# push *_test-trace-stream.data
|
||||
# . . push *_test-trace-stream.data
|
||||
b8/copy-to-EAX _test-trace-stream/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
|
||||
# . . call
|
||||
|
@ -232,7 +233,7 @@ test-trace-appends:
|
|||
# . . push args
|
||||
68/push "F - test-trace-appends"/imm32
|
||||
68/push 0x0a440a43/imm32/C-newline-D-newline
|
||||
# push *_test-trace-stream.data
|
||||
# . . push *_test-trace-stream.data
|
||||
b8/copy-to-EAX _test-trace-stream/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
|
||||
# . . call
|
||||
|
@ -262,7 +263,7 @@ test-trace-empty-line:
|
|||
# . . push args
|
||||
68/push "F - test-trace-empty-line"/imm32
|
||||
68/push 0/imm32
|
||||
# push *_test-trace-stream.data
|
||||
# . . push *_test-trace-stream.data
|
||||
b8/copy-to-EAX _test-trace-stream/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
|
||||
# . . call
|
||||
|
@ -272,7 +273,7 @@ test-trace-empty-line:
|
|||
# end
|
||||
c3/return
|
||||
|
||||
## helpers
|
||||
# - helpers
|
||||
|
||||
# 3-argument variant of _append
|
||||
_append-3: # out : address, outend : address, s : (array byte) -> num_bytes_appended/EAX
|
||||
|
@ -282,20 +283,17 @@ _append-3: # out : address, outend : address, s : (array byte) -> num_bytes_app
|
|||
# . save registers
|
||||
51/push-ECX
|
||||
# _append-4(out, outend, &s.data[0], &s.data[s.length]) -> num_bytes_appended/EAX
|
||||
# push &s.data[s.length]
|
||||
# EAX = s
|
||||
# . . push &s.data[s.length]
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none 0/r32/EAX 0x10/disp8 . # copy *(EBP+16) to EAX
|
||||
# ECX = s.length
|
||||
8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX
|
||||
# ECX = &s.data[s.length]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX
|
||||
51/push-ECX
|
||||
# push &s.data[0]
|
||||
# . . push &s.data[0]
|
||||
8d/copy-address 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy EAX+4 to ECX
|
||||
51/push-ECX
|
||||
# push outend
|
||||
# . . push outend
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
# push out
|
||||
# . . push out
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call _append-4/disp32
|
||||
|
|
|
@ -58,12 +58,12 @@ $write:fake:
|
|||
# EBX = f->length
|
||||
8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 3/r32/EBX 8/disp8 . # copy *(ECX+8) to EBX
|
||||
# EAX = _append-3(&f->data[f->write], &f->data[f->length], s)
|
||||
# push s
|
||||
# . . push s
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
# push &f->data[f->length]
|
||||
# . . push &f->data[f->length]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 3/index/EBX . 3/r32/EBX 0xc/disp8 . # copy ECX+EBX+12 to EBX
|
||||
53/push-EBX
|
||||
# push &f->data[f->write]
|
||||
# . . push &f->data[f->write]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 2/index/EDX . 3/r32/EBX 0xc/disp8 . # copy ECX+EDX+12 to EBX
|
||||
53/push-EBX
|
||||
# . . call
|
||||
|
@ -149,7 +149,7 @@ test-write-single:
|
|||
# . . push args
|
||||
68/push "F - test-write-single"/imm32
|
||||
68/push 0x006241/imm32/Ab
|
||||
# push *_test-stream->data
|
||||
# . . push *_test-stream->data
|
||||
b8/copy-to-EAX _test-stream/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
|
||||
# . . call
|
||||
|
@ -187,7 +187,7 @@ test-write-appends:
|
|||
# . . push args
|
||||
68/push "F - test-write-appends"/imm32
|
||||
68/push 0x00004443/imm32/C-D
|
||||
# push *_test-stream->data
|
||||
# . . push *_test-stream->data
|
||||
b8/copy-to-EAX _test-stream/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
|
||||
# . . call
|
||||
|
|
|
@ -65,7 +65,7 @@ tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void
|
|||
# That's the value we need to return: X-nbytes-4
|
||||
#
|
||||
# However, we also need to account for the perturbance to ESP caused by the
|
||||
# . . call to tailor-exit-descriptor. It pushes 8 bytes of args followed by 4
|
||||
# call to tailor-exit-descriptor. It pushes 8 bytes of args followed by 4
|
||||
# bytes for the return address and 4 bytes to push EBP above.
|
||||
# So EBP at this point is X-16.
|
||||
#
|
||||
|
@ -139,12 +139,12 @@ test-stop-skips-returns-on-exit:
|
|||
e8/call tailor-exit-descriptor/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call _test-stop-1(ed)
|
||||
# . _test-stop-1(ed)
|
||||
# . . push args
|
||||
50/push-EAX
|
||||
# . . call
|
||||
e8/call _test-stop-1/disp32
|
||||
## registers except ESP may be clobbered at this point
|
||||
# registers except ESP may be clobbered at this point
|
||||
# restore args
|
||||
58/pop-to-EAX
|
||||
# check that _test-stop-1 tried to call exit(1)
|
||||
|
@ -152,7 +152,7 @@ test-stop-skips-returns-on-exit:
|
|||
# . . push args
|
||||
68/push "F - test-stop-skips-returns-on-exit"/imm32
|
||||
68/push 2/imm32
|
||||
# push ed->value
|
||||
# . . push ed->value
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
|
||||
# . . call
|
||||
e8/call check-ints-equal/disp32
|
||||
|
@ -173,7 +173,7 @@ _test-stop-1: # ed : (address exit-descriptor)
|
|||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call _test-stop-2/disp32
|
||||
## should never get past this point
|
||||
# should never get past this point
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# signal test failed: check-ints-equal(1, 0, msg)
|
||||
|
@ -194,13 +194,13 @@ _test-stop-2: # ed : (address exit-descriptor)
|
|||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# . . call stop(ed, 1)
|
||||
# . stop(ed, 1)
|
||||
# . . push args
|
||||
68/push 1/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call stop/disp32
|
||||
## should never get past this point
|
||||
# should never get past this point
|
||||
# . epilog
|
||||
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
|
||||
5d/pop-to-EBP
|
||||
|
|
|
@ -56,7 +56,7 @@ read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/EAX
|
|||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
## if (f < 0x08000000) return _read(f, s) # f can't be a user-mode address, so treat it as a kernel file descriptor
|
||||
# if (f < 0x08000000) return _read(f, s) # f can't be a user-mode address, so treat it as a kernel file descriptor
|
||||
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 0x08000000/imm32 # compare *(EBP+8)
|
||||
7d/jump-if-greater-or-equal $read:fake/disp8
|
||||
# . . push args
|
||||
|
@ -69,7 +69,7 @@ read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/EAX
|
|||
# return
|
||||
eb/jump $read:end/disp8
|
||||
$read:fake:
|
||||
## otherwise, treat 'f' as a stream to scan from
|
||||
# otherwise, treat 'f' as a stream to scan from
|
||||
# . save registers
|
||||
56/push-ESI
|
||||
57/push-EDI
|
||||
|
@ -79,19 +79,19 @@ $read:fake:
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to ESI
|
||||
# EAX = _append-4(out = &s->data[s->write], outend = &s->data[s->length],
|
||||
# in = &f->data[f->read], inend = &f->data[f->write])
|
||||
# push &f->data[f->write]
|
||||
# . . push &f->data[f->write]
|
||||
8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX
|
||||
50/push-EAX
|
||||
# push &f->data[f->read]
|
||||
# . . push &f->data[f->read]
|
||||
8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX
|
||||
50/push-EAX
|
||||
# push &s->data[s->length]
|
||||
# . . push &s->data[s->length]
|
||||
8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 8/disp8 . # copy *(EDI+8) to EAX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy EDI+EAX+12 to EAX
|
||||
50/push-EAX
|
||||
# push &s->data[s->write]
|
||||
# . . push &s->data[s->write]
|
||||
8b/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy *EDI to EAX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy EDI+EAX+12 to EAX
|
||||
50/push-EAX
|
||||
|
@ -112,7 +112,7 @@ $read:end:
|
|||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
## helpers
|
||||
# - helpers
|
||||
|
||||
# idea: a clear-if-empty method on streams that clears only if f.read == f.write
|
||||
# Unclear how I'd use it, though. Callers seem to need the check anyway.
|
||||
|
@ -134,13 +134,13 @@ _read: # fd : int, s : (address stream) -> num-bytes-read/EAX
|
|||
# EDX = s->length
|
||||
8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 8/disp8 . # copy *(ESI+8) to EDX
|
||||
# syscall(read, fd, &s->data[s->write], s->length - s->write)
|
||||
# fd : EBX
|
||||
# . . fd : EBX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 3/r32/EBX 8/disp8 . # copy *(EBP+8) to EBX
|
||||
# data : ECX = &s->data[s->write]
|
||||
# . . data : ECX = &s->data[s->write]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 1/r32/ECX 0xc/disp8 . # copy ESI+EAX+12 to ECX
|
||||
# size : EDX = s->length - s->write
|
||||
# . . size : EDX = s->length - s->write
|
||||
29/subtract 3/mod/direct 2/rm32/EDX . . . 0/r32/EAX . . # subtract EAX from EDX
|
||||
# syscall
|
||||
# . . syscall
|
||||
b8/copy-to-EAX 3/imm32/read
|
||||
cd/syscall 0x80/imm8
|
||||
# add the result EAX to s->write
|
||||
|
@ -176,9 +176,10 @@ _read: # fd : int, s : (address stream) -> num-bytes-read/EAX
|
|||
# use one less register, but doesn't increase the amount of spilling (ECX
|
||||
# and EDX must be used, and EAX must be clobbered anyway).
|
||||
|
||||
## tests
|
||||
# - tests
|
||||
|
||||
test-read-single:
|
||||
# - write a single character into _test-stream, then read from its buffered-file
|
||||
# clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-stream/imm32
|
||||
|
@ -222,7 +223,7 @@ test-read-single:
|
|||
# . . push args
|
||||
68/push "F - test-read-single"/imm32
|
||||
68/push 0x006241/imm32/Ab
|
||||
# push *_test-stream-buffer->data
|
||||
# . . push *_test-stream-buffer->data
|
||||
b8/copy-to-EAX _test-stream-buffer/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
|
||||
# . . call
|
||||
|
@ -233,7 +234,7 @@ test-read-single:
|
|||
c3/return
|
||||
|
||||
test-read-is-stateful:
|
||||
## make two consecutive reads, check that their results are appended
|
||||
# - make two consecutive reads, check that their results are appended
|
||||
# clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-stream/imm32
|
||||
|
@ -284,7 +285,7 @@ test-read-is-stateful:
|
|||
# . . push args
|
||||
68/push "F - test-read-is-stateful"/imm32
|
||||
68/push 0x00004443/imm32/C-D
|
||||
# push *_test-stream-buffer->data
|
||||
# . push *_test-stream-buffer->data
|
||||
b8/copy-to-EAX _test-stream-buffer/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
|
||||
# . . call
|
||||
|
@ -295,22 +296,23 @@ test-read-is-stateful:
|
|||
c3/return
|
||||
|
||||
test-read-returns-0-on-end-of-file:
|
||||
## read after hitting end-of-file, check that result is 0
|
||||
# clear-stream(_test-stream)
|
||||
# - read after hitting end-of-file, check that result is 0
|
||||
# setup
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-stream-buffer)
|
||||
# . clear-stream(_test-stream-buffer)
|
||||
# . . push args
|
||||
68/push _test-stream-buffer/imm32
|
||||
# . . call
|
||||
e8/call clear-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# write(_test-stream, "Ab")
|
||||
# . write(_test-stream, "Ab")
|
||||
# . . push args
|
||||
68/push "Ab"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -318,8 +320,8 @@ test-read-returns-0-on-end-of-file:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## first read gets to end-of-file
|
||||
# read(_test-stream, _test-stream-buffer)
|
||||
# first read gets to end-of-file
|
||||
# . read(_test-stream, _test-stream-buffer)
|
||||
# . . push args
|
||||
68/push _test-stream-buffer/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -327,8 +329,8 @@ test-read-returns-0-on-end-of-file:
|
|||
e8/call read/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## second read
|
||||
# read(_test-stream, _test-stream-buffer)
|
||||
# second read
|
||||
# . read(_test-stream, _test-stream-buffer)
|
||||
# . . push args
|
||||
68/push _test-stream-buffer/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
|
|
@ -52,10 +52,11 @@ read-byte: # f : (address buffered-file) -> byte/EAX
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI
|
||||
# ECX = f->read
|
||||
8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 8/disp8 . # copy *(ESI+8) to ECX
|
||||
## if (f->read < f->write) read byte from stream
|
||||
# if (f->read < f->write) read byte from stream
|
||||
3b/compare 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # compare ECX with *(ESI+4)
|
||||
7c/jump-if-lesser $read-byte:from-stream/disp8
|
||||
# clear-stream(stream = f+4)
|
||||
# otherwise first populate stream from file
|
||||
# . clear-stream(stream = f+4)
|
||||
# . . push args
|
||||
8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy ESI+4 to EAX
|
||||
50/push-EAX
|
||||
|
@ -63,7 +64,7 @@ read-byte: # f : (address buffered-file) -> byte/EAX
|
|||
e8/call clear-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# EAX = read(f->fd, stream = f+4)
|
||||
# . EAX = read(f->fd, stream = f+4)
|
||||
# . . push args
|
||||
50/push-EAX
|
||||
ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI
|
||||
|
@ -77,6 +78,7 @@ read-byte: # f : (address buffered-file) -> byte/EAX
|
|||
b8/copy-to-EAX 0xffffffff/imm32
|
||||
eb/jump $read-byte:end/disp8
|
||||
$read-byte:from-stream:
|
||||
# reading from stream
|
||||
# AL = f->data[f->read]
|
||||
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX
|
||||
8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/AL 0x10/disp8 . # copy *(ESI+ECX+16) to AL
|
||||
|
@ -94,18 +96,19 @@ $read-byte:end:
|
|||
# todo: how should write-byte look? What should it do when the output has no
|
||||
# space remaining? Maybe return an error code.
|
||||
|
||||
## tests
|
||||
# - tests
|
||||
|
||||
test-read-byte-single:
|
||||
## check that read-byte returns first byte of 'file'
|
||||
# clear-stream(_test-stream)
|
||||
# - check that read-byte returns first byte of 'file'
|
||||
# setup
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -114,7 +117,7 @@ test-read-byte-single:
|
|||
e8/call clear-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# write(_test-stream, "Ab")
|
||||
# . write(_test-stream, "Ab")
|
||||
# . . push args
|
||||
68/push "Ab"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -138,19 +141,20 @@ test-read-byte-single:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# end
|
||||
# . end
|
||||
c3/return
|
||||
|
||||
test-read-byte-multiple:
|
||||
## call read-byte twice, check that second call returns second byte
|
||||
# clear-stream(_test-stream)
|
||||
# - call read-byte twice, check that second call returns second byte
|
||||
# setup
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -159,7 +163,7 @@ test-read-byte-multiple:
|
|||
e8/call clear-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# write(_test-stream, "Ab")
|
||||
# . write(_test-stream, "Ab")
|
||||
# . . push args
|
||||
68/push "Ab"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -190,19 +194,20 @@ test-read-byte-multiple:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# end
|
||||
# . end
|
||||
c3/return
|
||||
|
||||
test-read-byte-end-of-file:
|
||||
## call read-byte on an empty 'file', check that it returns -1
|
||||
# clear-stream(_test-stream)
|
||||
# - call read-byte on an empty 'file', check that it returns -1
|
||||
# setup
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -227,7 +232,7 @@ test-read-byte-end-of-file:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# end
|
||||
# . end
|
||||
c3/return
|
||||
|
||||
== data
|
||||
|
|
|
@ -45,19 +45,19 @@ $write-stream:fake:
|
|||
# EDI = s
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI
|
||||
# EAX = _append-4(&f->data[f->write], &f->data[f->length], &s->data[s->read], &s->data[s->write])
|
||||
# push &s->data[s->write]
|
||||
# . . push &s->data[s->write]
|
||||
8b/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy *EDI to EAX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy EDI+EAX+12 to EAX
|
||||
50/push-EAX
|
||||
# push &s->data[s->read]
|
||||
# . . push &s->data[s->read]
|
||||
8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy *(EDI+4) to EAX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy EDI+EAX+12 to EAX
|
||||
50/push-EAX
|
||||
# push &f->data[f->length]
|
||||
# . . push &f->data[f->length]
|
||||
8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 8/disp8 . # copy *(ESI+8) to EAX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX
|
||||
50/push-EAX
|
||||
# push &f->data[f->write]
|
||||
# . . push &f->data[f->write]
|
||||
8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX
|
||||
50/push-EAX
|
||||
|
@ -97,13 +97,13 @@ _write-stream: # fd : int, s : (address stream) -> <void>
|
|||
# EDX = s->write
|
||||
8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX
|
||||
# syscall(write, fd, &s->data[s->read], s->write-s->read)
|
||||
# fd : EBX
|
||||
# . . fd : EBX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 3/r32/EBX 8/disp8 . # copy *(EBP+8) to EBX
|
||||
# data : ECX = &s->data[s->read]
|
||||
# . . data : ECX = &s->data[s->read]
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 7/index/EDI . 1/r32/ECX 0xc/disp8 . # copy ESI+EDI+12 to ECX
|
||||
# size : EDX = s->write - s->read
|
||||
# . . size : EDX = s->write - s->read
|
||||
29/subtract 3/mod/direct 2/rm32/EDX . . . 7/r32/EDI . . # subtract EDI from EDX
|
||||
# syscall
|
||||
# . . syscall
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
# . restore registers
|
||||
|
@ -119,21 +119,22 @@ _write-stream: # fd : int, s : (address stream) -> <void>
|
|||
c3/return
|
||||
|
||||
test-write-stream-single:
|
||||
# clear-stream(_test-stream)
|
||||
# setup
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-stream2)
|
||||
# . clear-stream(_test-stream2)
|
||||
# . . push args
|
||||
68/push _test-stream2/imm32
|
||||
# . . call
|
||||
e8/call clear-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# write(_test-stream2, "Ab")
|
||||
# . write(_test-stream2, "Ab")
|
||||
# . . push args
|
||||
68/push "Ab"/imm32
|
||||
68/push _test-stream2/imm32
|
||||
|
@ -160,25 +161,26 @@ test-write-stream-single:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# end
|
||||
# . end
|
||||
c3/return
|
||||
|
||||
test-write-stream-appends:
|
||||
# clear-stream(_test-stream)
|
||||
# setup
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-stream2)
|
||||
# . clear-stream(_test-stream2)
|
||||
# . . push args
|
||||
68/push _test-stream2/imm32
|
||||
# . . call
|
||||
e8/call clear-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# write(_test-stream2, "C")
|
||||
# . write(_test-stream2, "C")
|
||||
# . . push args
|
||||
68/push "C"/imm32
|
||||
68/push _test-stream2/imm32
|
||||
|
@ -186,7 +188,8 @@ test-write-stream-appends:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# write-stream(_test-stream, _test-stream2)
|
||||
# first write
|
||||
# . write-stream(_test-stream, _test-stream2)
|
||||
# . . push args
|
||||
68/push _test-stream2/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -194,7 +197,8 @@ test-write-stream-appends:
|
|||
e8/call write-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# write(_test-stream2, "D")
|
||||
# second write
|
||||
# . write(_test-stream2, "D")
|
||||
# . . push args
|
||||
68/push "D"/imm32
|
||||
68/push _test-stream2/imm32
|
||||
|
@ -202,7 +206,7 @@ test-write-stream-appends:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# write-stream(_test-stream, _test-stream2)
|
||||
# . write-stream(_test-stream, _test-stream2)
|
||||
# . . push args
|
||||
68/push _test-stream2/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -221,7 +225,7 @@ test-write-stream-appends:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# end
|
||||
# . end
|
||||
c3/return
|
||||
|
||||
== data
|
||||
|
|
|
@ -33,10 +33,11 @@
|
|||
# main: run tests if necessary, call 'compile' if not
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# if (argc > 1)
|
||||
# - if argc > 1 and argv[1] == "test" then return run_tests()
|
||||
# . argc > 1
|
||||
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
# and if (argv[1] == "test")
|
||||
# . argv[1] == "test"
|
||||
# . . push args
|
||||
68/push "test"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
|
@ -47,19 +48,20 @@
|
|||
# . check result
|
||||
3d/compare-EAX 1/imm32
|
||||
75/jump-if-not-equal $run-main/disp8
|
||||
# then return run-tests()
|
||||
# . run-tests()
|
||||
e8/call run-tests/disp32
|
||||
#? e8/call test-get-num-reads-multiple-digits/disp32
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX
|
||||
eb/jump $main:end/disp8
|
||||
$run-main:
|
||||
# allocate space for an exit-descriptor
|
||||
# . var ed/EAX : (address exit-descriptor)
|
||||
# - otherwise read a program from stdin and emit its translation to stdout
|
||||
# var ed/EAX : exit-descriptor
|
||||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
|
||||
# . clear ed->target (so we really exit)
|
||||
# configure ed to really exit()
|
||||
# . ed->target = 0
|
||||
c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX
|
||||
# compile(Stdin, 1/stdout, 2/stderr, ed)
|
||||
# return compile(Stdin, 1/stdout, 2/stderr, ed)
|
||||
# . . push args
|
||||
50/push-EAX/ed
|
||||
68/push 2/imm32/stderr
|
||||
|
@ -69,7 +71,7 @@ $run-main:
|
|||
e8/call compile/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# syscall(exit, 0)
|
||||
# . syscall(exit, 0)
|
||||
bb/copy-to-EBX 0/imm32
|
||||
$main:end:
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
|
@ -83,7 +85,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
# . save registers
|
||||
50/push-EAX
|
||||
51/push-ECX
|
||||
# Look = get-char(in)
|
||||
# . Look = get-char(in)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
|
@ -98,14 +100,15 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX . . # copy ESP to ECX
|
||||
# num->length = 7
|
||||
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 8/disp8 7/imm32 # copy to *(ECX+8)
|
||||
# clear-stream(num)
|
||||
# read a digit from 'in' into 'num'
|
||||
# . clear-stream(num)
|
||||
# . . push args
|
||||
51/push-ECX
|
||||
# . . call
|
||||
e8/call clear-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# get-num(in, num, err, ed)
|
||||
# . get-num(in, num, err, ed)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20)
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
|
||||
|
@ -115,15 +118,12 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call get-num/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# EAX = write(_test-stream, "Ab")
|
||||
# . . push args
|
||||
68/push "Ab"/imm32
|
||||
68/push _test-stream/imm32
|
||||
# . . call
|
||||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, "bb/copy-to-EBX ")
|
||||
# render 'num' into the following template on 'out':
|
||||
# bb/copy-to-EBX _num_
|
||||
# b8/copy-to-EAX 1/imm32/exit
|
||||
# cd/syscall 0x80/imm8
|
||||
#
|
||||
# . EAX = write(out, "bb/copy-to-EBX ")
|
||||
# . . push args
|
||||
68/push "bb/copy-to-EBX "/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -131,7 +131,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# write-stream(out, num)
|
||||
# . write-stream(out, num)
|
||||
# . . push args
|
||||
51/push-ECX/num
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -139,7 +139,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# write(out, Newline)
|
||||
# . write(out, Newline)
|
||||
# . . push args
|
||||
68/push Newline/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -147,7 +147,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, "b8/copy-to-EAX 1/imm32/exit")
|
||||
# . write(out, "b8/copy-to-EAX 1/imm32/exit")
|
||||
# . . push args
|
||||
68/push "b8/copy-to-EAX 1/imm32/exit"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -155,7 +155,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, Newline)
|
||||
# . write(out, Newline)
|
||||
# . . push args
|
||||
68/push Newline/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -163,7 +163,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, "cd/syscall 0x80/imm8")
|
||||
# . write(out, "cd/syscall 0x80/imm8")
|
||||
# . . push args
|
||||
68/push "cd/syscall 0x80/imm8"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -171,7 +171,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, Newline)
|
||||
# . write(out, Newline)
|
||||
# . . push args
|
||||
68/push Newline/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -179,7 +179,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . restore registers
|
||||
# . restore registers
|
||||
59/pop-to-ECX
|
||||
58/pop-to-EAX
|
||||
# . epilog
|
||||
|
@ -200,7 +200,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
# ++out.write
|
||||
# Look = get-char(in)
|
||||
#
|
||||
# within the loop we'll try to keep things in registers:
|
||||
# registers:
|
||||
# ESI : in
|
||||
# EDI : out
|
||||
# EAX : temp
|
||||
|
@ -214,14 +214,15 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# EAX = is-digit?(Look)
|
||||
# - if is-digit?(Look) expected(ed, err, "integer")
|
||||
# . EAX = is-digit?(Look)
|
||||
# . . push args
|
||||
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
|
||||
# . . call
|
||||
e8/call is-digit?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# if EAX == 0 error
|
||||
# . if EAX == 0
|
||||
3d/compare-EAX 0/imm32
|
||||
75/jump-if-not-equal $get-num:main/disp8
|
||||
# . expected(ed, err, "integer")
|
||||
|
@ -234,6 +235,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
$get-num:main:
|
||||
# - otherwise read a digit
|
||||
# . save registers
|
||||
50/push-EAX
|
||||
51/push-ECX
|
||||
|
@ -253,7 +255,7 @@ $get-num:main:
|
|||
# if out->write >= out->length error
|
||||
3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX
|
||||
7d/jump-if-lesser $get-num:stage2/disp8
|
||||
# error(ed, err, "get-num: too many digits in number") # TODO: show full number
|
||||
# . error(ed, err, msg) # TODO: show full number
|
||||
# . . push args
|
||||
68/push "get-num: too many digits in number"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
|
||||
|
@ -296,15 +298,15 @@ test-get-num-reads-single-digit:
|
|||
# This test uses exit-descriptors. Use EBP for setting up local variables.
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - clear all streams
|
||||
# clear-stream(_test-stream)
|
||||
# setup
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -313,22 +315,22 @@ test-get-num-reads-single-digit:
|
|||
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-stream)
|
||||
# . 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-error-stream)
|
||||
# . clear-stream(_test-error-stream)
|
||||
# . . push args
|
||||
68/push _test-error-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
|
||||
# - initialize 'in'
|
||||
# write(_test-stream, "3")
|
||||
# initialize 'in'
|
||||
# . write(_test-stream, "3")
|
||||
# . . push args
|
||||
68/push "3"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -336,13 +338,11 @@ test-get-num-reads-single-digit:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# - initialize exit-descriptor 'ed'
|
||||
# allocate on stack
|
||||
# var ed/EAX : (address exit-descriptor)
|
||||
# initialize exit-descriptor 'ed' for the call to 'get-num' below
|
||||
# . var ed/EAX : exit-descriptor
|
||||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
|
||||
# size the exit-descriptor for the call to get-num below
|
||||
# tailor-exit-descriptor(ed, 16)
|
||||
# . tailor-exit-descriptor(ed, 16)
|
||||
# . . push args
|
||||
68/push 0x10/imm32/nbytes-of-args-for-get-num
|
||||
50/push-EAX/ed
|
||||
|
@ -350,15 +350,15 @@ test-get-num-reads-single-digit:
|
|||
e8/call tailor-exit-descriptor/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# - prime the pump
|
||||
# get-char(_test-buffered-file)
|
||||
# prime the pump
|
||||
# . get-char(_test-buffered-file)
|
||||
# . . push args
|
||||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-char/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
## get-num(in, out, err, ed)
|
||||
# get-num(in, out, err, ed)
|
||||
# . . push args
|
||||
50/push-EAX/ed
|
||||
68/push _test-error-stream/imm32
|
||||
|
@ -366,7 +366,7 @@ test-get-num-reads-single-digit:
|
|||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-num/disp32
|
||||
## registers except ESP may be clobbered at this point
|
||||
# registers except ESP may be clobbered at this point
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# check-ints-equal(*_test-output-stream.data, '3')
|
||||
|
@ -379,7 +379,7 @@ test-get-num-reads-single-digit:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# reclaim locals
|
||||
# . reclaim locals
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
@ -389,15 +389,15 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
# This test uses exit-descriptors. Use EBP for setting up local variables.
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - clear all streams
|
||||
# clear-stream(_test-stream)
|
||||
# setup
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -406,22 +406,22 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
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-stream)
|
||||
# . 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-error-stream)
|
||||
# . clear-stream(_test-error-stream)
|
||||
# . . push args
|
||||
68/push _test-error-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
|
||||
# - initialize 'in'
|
||||
# write(_test-stream, "3")
|
||||
# initialize 'in'
|
||||
# . write(_test-stream, "3")
|
||||
# . . push args
|
||||
68/push "3"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -429,13 +429,11 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# - initialize exit-descriptor 'ed'
|
||||
# allocate on stack
|
||||
# var ed/EAX : (address exit-descriptor)
|
||||
# initialize exit-descriptor 'ed' for the call to 'get-num' below
|
||||
# . var ed/EAX : (address exit-descriptor)
|
||||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
|
||||
# size the exit-descriptor for the call to get-num below
|
||||
# tailor-exit-descriptor(ed, 16)
|
||||
# . tailor-exit-descriptor(ed, 16)
|
||||
# . . push args
|
||||
68/push 0x10/imm32/nbytes-of-args-for-get-num
|
||||
50/push-EAX/ed
|
||||
|
@ -443,8 +441,8 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
e8/call tailor-exit-descriptor/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# - don't initialize Look
|
||||
# - get-num(in, out, err, ed)
|
||||
# *don't* prime the pump
|
||||
# get-num(in, out, err, ed)
|
||||
# . . push args
|
||||
50/push-EAX/ed
|
||||
68/push _test-error-stream/imm32
|
||||
|
@ -455,18 +453,18 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
# registers except ESP may be clobbered at this point
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# - check that get-num tried to call exit(1)
|
||||
# check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
|
||||
# check that get-num tried to call exit(1)
|
||||
# . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
|
||||
# . . push args
|
||||
68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32
|
||||
68/push 2/imm32
|
||||
# . push ed->value
|
||||
# . . push ed->value
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
|
||||
# . . call
|
||||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# reclaim locals
|
||||
# . reclaim locals
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
@ -516,7 +514,7 @@ expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (ad
|
|||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call stop/disp32
|
||||
## should never get past this point
|
||||
# should never get past this point
|
||||
# . epilog
|
||||
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
|
||||
5d/pop-to-EBP
|
||||
|
@ -557,13 +555,13 @@ error: # ed : (address exit-descriptor), f : fd or (address stream), s : (addre
|
|||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call stop/disp32
|
||||
## should never get past this point
|
||||
# should never get past this point
|
||||
# . epilog
|
||||
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
# read a byte from 'f', and store it in 'Look'
|
||||
# read a byte from 'f', and save it in 'Look'
|
||||
get-char: # f : (address buffered-file) -> <void>
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
|
|
|
@ -33,10 +33,11 @@
|
|||
# main: run tests if necessary, call 'compile' if not
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# if (argc > 1)
|
||||
# - if argc > 1 and argv[1] == "test" then return run_tests()
|
||||
# . argc > 1
|
||||
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
# and if (argv[1] == "test")
|
||||
# . argv[1] == "test"
|
||||
# . . push args
|
||||
68/push "test"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
|
@ -44,22 +45,23 @@
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check result
|
||||
# . check result
|
||||
3d/compare-EAX 1/imm32
|
||||
75/jump-if-not-equal $run-main/disp8
|
||||
# then return run-tests()
|
||||
# . run-tests()
|
||||
e8/call run-tests/disp32
|
||||
#? e8/call test-get-num-reads-multiple-digits/disp32
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX
|
||||
eb/jump $main:end/disp8
|
||||
$run-main:
|
||||
# allocate space for an exit-descriptor
|
||||
# var ed/EAX : (address exit-descriptor)
|
||||
# - otherwise read a program from stdin and emit its translation to stdout
|
||||
# var ed/EAX : exit-descriptor
|
||||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
|
||||
# clear ed->target (so we really exit)
|
||||
# configure ed to really exit()
|
||||
# . ed->target = 0
|
||||
c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX
|
||||
# compile(Stdin, 1/stdout, 2/stderr, ed)
|
||||
# return compile(Stdin, 1/stdout, 2/stderr, ed)
|
||||
# . . push args
|
||||
50/push-EAX/ed
|
||||
68/push 2/imm32/stderr
|
||||
|
@ -69,7 +71,7 @@ $run-main:
|
|||
e8/call compile/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# syscall(exit, 0)
|
||||
# . syscall(exit, 0)
|
||||
bb/copy-to-EBX 0/imm32
|
||||
$main:end:
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
|
@ -83,7 +85,8 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
# . save registers
|
||||
50/push-EAX
|
||||
51/push-ECX
|
||||
# Look = get-char(in)
|
||||
# prime the pump
|
||||
# . Look = get-char(in)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
|
@ -98,14 +101,15 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX . . # copy ESP to ECX
|
||||
# num->length = 7
|
||||
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 8/disp8 7/imm32 # copy to *(ECX+8)
|
||||
# clear-stream(num)
|
||||
# read a digit from 'in' into 'num'
|
||||
# . clear-stream(num)
|
||||
# . . push args
|
||||
51/push-ECX
|
||||
# . . call
|
||||
e8/call clear-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# get-num(in, num, err, ed)
|
||||
# . get-num(in, num, err, ed)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20)
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
|
||||
|
@ -115,15 +119,12 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call get-num/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# EAX = write(_test-stream, "Ab")
|
||||
# . . push args
|
||||
68/push "Ab"/imm32
|
||||
68/push _test-stream/imm32
|
||||
# . . call
|
||||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, "bb/copy-to-EBX ")
|
||||
# render 'num' into the following template on 'out':
|
||||
# bb/copy-to-EBX _num_
|
||||
# b8/copy-to-EAX 1/imm32/exit
|
||||
# cd/syscall 0x80/imm8
|
||||
#
|
||||
# . EAX = write(out, "bb/copy-to-EBX ")
|
||||
# . . push args
|
||||
68/push "bb/copy-to-EBX "/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -131,7 +132,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# write-stream(out, num)
|
||||
# . write-stream(out, num)
|
||||
# . . push args
|
||||
51/push-ECX/num
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -139,7 +140,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write-stream/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# write(out, Newline)
|
||||
# . write(out, Newline)
|
||||
# . . push args
|
||||
68/push Newline/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -147,7 +148,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, "b8/copy-to-EAX 1/imm32/exit")
|
||||
# . write(out, "b8/copy-to-EAX 1/imm32/exit")
|
||||
# . . push args
|
||||
68/push "b8/copy-to-EAX 1/imm32/exit"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -155,7 +156,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, Newline)
|
||||
# . write(out, Newline)
|
||||
# . . push args
|
||||
68/push Newline/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -163,7 +164,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, "cd/syscall 0x80/imm8")
|
||||
# . write(out, "cd/syscall 0x80/imm8")
|
||||
# . . push args
|
||||
68/push "cd/syscall 0x80/imm8"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -171,7 +172,7 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# EAX = write(out, Newline)
|
||||
# . write(out, Newline)
|
||||
# . . push args
|
||||
68/push Newline/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -219,17 +220,18 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# EAX = is-digit?(Look)
|
||||
# - if is-digit?(Look) expected(ed, err, "integer")
|
||||
# . EAX = is-digit?(Look)
|
||||
# . . push args
|
||||
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
|
||||
# . . call
|
||||
e8/call is-digit?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# if EAX == 0 error
|
||||
# . if EAX == 0
|
||||
3d/compare-EAX 0/imm32
|
||||
75/jump-if-not-equal $get-num:main/disp8
|
||||
# expected(ed, err, "integer")
|
||||
# . expected(ed, err, "integer")
|
||||
# . . push args
|
||||
68/push "integer"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
|
||||
|
@ -239,6 +241,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
$get-num:main:
|
||||
# - otherwise read a digit
|
||||
# . save registers
|
||||
50/push-EAX
|
||||
51/push-ECX
|
||||
|
@ -259,7 +262,7 @@ $get-num:loop:
|
|||
# if out->write >= out->length error
|
||||
3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX
|
||||
7d/jump-if-lesser $get-num:loop-stage2/disp8
|
||||
# error(ed, err, "get-num: too many digits in number") # TODO: show full number
|
||||
# . error(ed, err, msg) # TODO: show full number
|
||||
# . . push args
|
||||
68/push "get-num: too many digits in number"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
|
||||
|
@ -282,14 +285,15 @@ $get-num:loop-stage2:
|
|||
e8/call get-char/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# EAX = is-digit?(Look)
|
||||
# if is-digit?(Look) loop
|
||||
# . EAX = is-digit?(Look)
|
||||
# . . push args
|
||||
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
|
||||
# . . call
|
||||
e8/call is-digit?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# if EAX loop
|
||||
# . if EAX loop
|
||||
3d/compare-EAX 0/imm32
|
||||
0f 85/jump-if-not-equal $get-num:loop/disp32
|
||||
$get-num:loop-end:
|
||||
|
@ -308,19 +312,19 @@ $get-num:loop-end:
|
|||
c3/return
|
||||
|
||||
test-get-num-reads-single-digit:
|
||||
## check that get-num returns first character if it's a digit
|
||||
# - check that get-num returns first character if it's a digit
|
||||
# This test uses exit-descriptors. Use EBP for setting up local variables.
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
## clear all streams
|
||||
# clear-stream(_test-stream)
|
||||
# clear all streams
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -329,22 +333,22 @@ test-get-num-reads-single-digit:
|
|||
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-stream)
|
||||
# . 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-error-stream)
|
||||
# . clear-stream(_test-error-stream)
|
||||
# . . push args
|
||||
68/push _test-error-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
|
||||
## initialize 'in'
|
||||
# write(_test-stream, "3")
|
||||
# initialize 'in'
|
||||
# . write(_test-stream, "3")
|
||||
# . . push args
|
||||
68/push "3"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -352,13 +356,11 @@ test-get-num-reads-single-digit:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## initialize exit-descriptor 'ed'
|
||||
# allocate on stack
|
||||
# var ed/EAX : (address exit-descriptor)
|
||||
# initialize exit-descriptor 'ed' for the call to 'get-num' below
|
||||
# . var ed/EAX : exit-descriptor
|
||||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
|
||||
# size the exit-descriptor for the call to get-num below
|
||||
# tailor-exit-descriptor(ed, 16)
|
||||
# . tailor-exit-descriptor(ed, 16)
|
||||
# . . push args
|
||||
68/push 0x10/imm32/nbytes-of-args-for-get-num
|
||||
50/push-EAX/ed
|
||||
|
@ -366,15 +368,15 @@ test-get-num-reads-single-digit:
|
|||
e8/call tailor-exit-descriptor/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## prime the pump
|
||||
# get-char(_test-buffered-file)
|
||||
# prime the pump
|
||||
# . get-char(_test-buffered-file)
|
||||
# . . push args
|
||||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-char/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
## get-num(in, out, err, ed)
|
||||
# get-num(in, out, err, ed)
|
||||
# . . push args
|
||||
50/push-EAX/ed
|
||||
68/push _test-error-stream/imm32
|
||||
|
@ -382,7 +384,7 @@ test-get-num-reads-single-digit:
|
|||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-num/disp32
|
||||
## registers except ESP may be clobbered at this point
|
||||
# registers except ESP may be clobbered at this point
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# check-ints-equal(*_test-output-stream.data, '3')
|
||||
|
@ -395,25 +397,25 @@ test-get-num-reads-single-digit:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# reclaim locals
|
||||
# . reclaim locals
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
test-get-num-aborts-on-non-digit-in-Look:
|
||||
## check that get-num returns first character if it's a digit
|
||||
# - check that get-num returns first character if it's a digit
|
||||
# This test uses exit-descriptors. Use EBP for setting up local variables.
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
## clear all streams
|
||||
# clear-stream(_test-stream)
|
||||
# clear all streams
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -422,22 +424,22 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
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-stream)
|
||||
# . 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-error-stream)
|
||||
# . clear-stream(_test-error-stream)
|
||||
# . . push args
|
||||
68/push _test-error-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
|
||||
## initialize 'in'
|
||||
# write(_test-stream, "3")
|
||||
# initialize 'in'
|
||||
# . write(_test-stream, "3")
|
||||
# . . push args
|
||||
68/push "3"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -445,13 +447,11 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## initialize exit-descriptor 'ed'
|
||||
# allocate on stack
|
||||
# var ed/EAX : (address exit-descriptor)
|
||||
# initialize exit-descriptor 'ed' for the call to 'get-num' below
|
||||
# . var ed/EAX : (address exit-descriptor)
|
||||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
|
||||
# size the exit-descriptor for the call to get-num below
|
||||
# tailor-exit-descriptor(ed, 16)
|
||||
# . tailor-exit-descriptor(ed, 16)
|
||||
# . . push args
|
||||
68/push 0x10/imm32/nbytes-of-args-for-get-num
|
||||
50/push-EAX/ed
|
||||
|
@ -459,8 +459,8 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
e8/call tailor-exit-descriptor/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## don't initialize Look
|
||||
## get-num(in, out, err, ed)
|
||||
# *don't* prime the pump
|
||||
# get-num(in, out, err, ed)
|
||||
# . . push args
|
||||
50/push-EAX/ed
|
||||
68/push _test-error-stream/imm32
|
||||
|
@ -468,39 +468,39 @@ test-get-num-aborts-on-non-digit-in-Look:
|
|||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-num/disp32
|
||||
## registers except ESP may be clobbered at this point
|
||||
# registers except ESP may be clobbered at this point
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
## check that get-num tried to call exit(1)
|
||||
# check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
|
||||
# check that get-num tried to call exit(1)
|
||||
# . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
|
||||
# . . push args
|
||||
68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32
|
||||
68/push 2/imm32
|
||||
# push ed->value
|
||||
# . . push ed->value
|
||||
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
|
||||
# . . call
|
||||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# reclaim locals
|
||||
# . reclaim locals
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
test-get-num-reads-multiple-digits:
|
||||
## check that get-num returns all initial digits until it encounters a non-digit
|
||||
# - check that get-num returns all initial digits until it encounters a non-digit
|
||||
# This test uses exit-descriptors. Use EBP for setting up local variables.
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
## clear all streams
|
||||
# clear-stream(_test-stream)
|
||||
# clear all streams
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -509,22 +509,22 @@ test-get-num-reads-multiple-digits:
|
|||
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-stream)
|
||||
# . 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-error-stream)
|
||||
# . clear-stream(_test-error-stream)
|
||||
# . . push args
|
||||
68/push _test-error-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
|
||||
## initialize 'in'
|
||||
# write(_test-stream, "3456 x")
|
||||
# initialize 'in'
|
||||
# . write(_test-stream, "3456 x")
|
||||
# . . push args
|
||||
68/push "3456"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -532,13 +532,11 @@ test-get-num-reads-multiple-digits:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## initialize exit-descriptor 'ed'
|
||||
# allocate on stack
|
||||
# var ed/EAX : (address exit-descriptor)
|
||||
# initialize exit-descriptor 'ed' for the call to 'get-num' below
|
||||
# . var ed/EAX : (address exit-descriptor)
|
||||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
|
||||
# size the exit-descriptor for the call to get-num below
|
||||
# tailor-exit-descriptor(ed, 16)
|
||||
# . tailor-exit-descriptor(ed, 16)
|
||||
# . . push args
|
||||
68/push 0x10/imm32/nbytes-of-args-for-get-num
|
||||
50/push-EAX/ed
|
||||
|
@ -546,15 +544,15 @@ test-get-num-reads-multiple-digits:
|
|||
e8/call tailor-exit-descriptor/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## prime the pump
|
||||
# get-char(_test-buffered-file)
|
||||
# prime the pump
|
||||
# . get-char(_test-buffered-file)
|
||||
# . . push args
|
||||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-char/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
## get-num(in, out, err, ed)
|
||||
# get-num(in, out, err, ed)
|
||||
# . . push args
|
||||
50/push-EAX/ed
|
||||
68/push _test-error-stream/imm32
|
||||
|
@ -562,7 +560,7 @@ test-get-num-reads-multiple-digits:
|
|||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-num/disp32
|
||||
## registers except ESP may be clobbered at this point
|
||||
# registers except ESP may be clobbered at this point
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# check-ints-equal(*_test-output-stream.data, '3456')
|
||||
|
@ -575,25 +573,25 @@ test-get-num-reads-multiple-digits:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# reclaim locals
|
||||
# . reclaim locals
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
test-get-num-reads-multiple-digits-followed-by-nondigit:
|
||||
## check that get-num returns all initial digits until it encounters a non-digit
|
||||
# - check that get-num returns all initial digits until it encounters a non-digit
|
||||
# This test uses exit-descriptors. Use EBP for setting up local variables.
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
## clear all streams
|
||||
# clear-stream(_test-stream)
|
||||
# clear all streams
|
||||
# . clear-stream(_test-stream)
|
||||
# . . push args
|
||||
68/push _test-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-buffered-file+4)
|
||||
# . clear-stream(_test-buffered-file+4)
|
||||
# . . push args
|
||||
b8/copy-to-EAX _test-buffered-file/imm32
|
||||
05/add-to-EAX 4/imm32
|
||||
|
@ -602,22 +600,22 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
|
|||
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-stream)
|
||||
# . 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-error-stream)
|
||||
# . clear-stream(_test-error-stream)
|
||||
# . . push args
|
||||
68/push _test-error-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
|
||||
## initialize 'in'
|
||||
# write(_test-stream, "3456 x")
|
||||
# initialize 'in'
|
||||
# . write(_test-stream, "3456 x")
|
||||
# . . push args
|
||||
68/push "3456 x"/imm32
|
||||
68/push _test-stream/imm32
|
||||
|
@ -625,13 +623,11 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
|
|||
e8/call write/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## initialize exit-descriptor 'ed'
|
||||
# allocate on stack
|
||||
# var ed/EAX : (address exit-descriptor)
|
||||
# initialize exit-descriptor 'ed' for the call to 'get-num' below
|
||||
# . var ed/EAX : (address exit-descriptor)
|
||||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP
|
||||
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
|
||||
# size the exit-descriptor for the call to get-num below
|
||||
# tailor-exit-descriptor(ed, 16)
|
||||
# . tailor-exit-descriptor(ed, 16)
|
||||
# . . push args
|
||||
68/push 0x10/imm32/nbytes-of-args-for-get-num
|
||||
50/push-EAX/ed
|
||||
|
@ -639,15 +635,15 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
|
|||
e8/call tailor-exit-descriptor/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
## prime the pump
|
||||
# get-char(_test-buffered-file)
|
||||
# prime the pump
|
||||
# . get-char(_test-buffered-file)
|
||||
# . . push args
|
||||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-char/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
## get-num(in, out, err, ed)
|
||||
# get-num(in, out, err, ed)
|
||||
# . . push args
|
||||
50/push-EAX/ed
|
||||
68/push _test-error-stream/imm32
|
||||
|
@ -655,7 +651,7 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
|
|||
68/push _test-buffered-file/imm32
|
||||
# . . call
|
||||
e8/call get-num/disp32
|
||||
## registers except ESP may be clobbered at this point
|
||||
# registers except ESP may be clobbered at this point
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# check-ints-equal(*_test-output-stream.data, '3456')
|
||||
|
@ -668,7 +664,7 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
|
|||
e8/call check-ints-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# reclaim locals
|
||||
# . reclaim locals
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
@ -718,7 +714,7 @@ expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (ad
|
|||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call stop/disp32
|
||||
## should never get past this point
|
||||
# should never get past this point
|
||||
# . epilog
|
||||
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
|
||||
5d/pop-to-EBP
|
||||
|
@ -759,13 +755,13 @@ error: # ed : (address exit-descriptor), f : fd or (address stream), s : (addre
|
|||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call stop/disp32
|
||||
## should never get past this point
|
||||
# should never get past this point
|
||||
# . epilog
|
||||
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
# read a byte from 'f', and store it in 'Look'
|
||||
# read a byte from 'f', and save it in 'Look'
|
||||
get-char: # f : (address buffered-file) -> <void>
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
|
|
|
@ -22,10 +22,11 @@
|
|||
# main:
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# if (argc > 1)
|
||||
# - if argc > 1 and argv[1] == "test" then return run_tests()
|
||||
# . argc > 1
|
||||
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
# and if (argv[1] == "test")
|
||||
# . argv[1] == "test"
|
||||
# . . push args
|
||||
68/push "test"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
|
@ -33,14 +34,14 @@
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check result
|
||||
# . check result
|
||||
3d/compare-EAX 1/imm32
|
||||
75/jump-if-not-equal $run-main/disp8
|
||||
# then return run-tests()
|
||||
# . run-tests()
|
||||
e8/call run-tests/disp32
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Num-test-failures/disp32 # copy *Num-test-failures to EAX
|
||||
eb/jump $main:end/disp8 # where EAX will get copied to EBX
|
||||
# else EAX = factorial(5)
|
||||
# - otherwise return factorial(5)
|
||||
$run-main:
|
||||
# . . push args
|
||||
68/push 5/imm32
|
||||
|
@ -49,20 +50,19 @@ $run-main:
|
|||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
$main:end:
|
||||
# exit(EAX)
|
||||
# syscall(exit, EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# factorial(n)
|
||||
factorial:
|
||||
factorial: # n : int -> int/EAX
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
53/push-EBX
|
||||
# initialize EAX to 1 (base case)
|
||||
# EAX = 1 (base case)
|
||||
b8/copy-to-EAX 1/imm32
|
||||
# if (n <= 1) jump exit
|
||||
# if (n <= 1) return
|
||||
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 1/imm32 # compare *(EBP+8)
|
||||
7e/jump-if-<= $factorial:end/disp8
|
||||
# EBX = n-1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## first program: same as https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
|
||||
# First program: same as https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
|
||||
# Just return 42.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
|
@ -10,8 +10,8 @@
|
|||
|
||||
== code
|
||||
|
||||
# syscall(exit, 42)
|
||||
bb/copy-to-EBX 2a/imm32 # 42 in hex
|
||||
# exit(EBX)
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## String comparison: return 1 iff the two args passed in at the commandline are equal.
|
||||
# String comparison: return 1 iff the two args passed in at the commandline are equal.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
# $ subx translate examples/ex10.subx -o examples/ex10
|
||||
|
@ -20,15 +20,14 @@
|
|||
# ...
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# . . call argv-equal(argv[1], argv[2])
|
||||
# push argv[2]
|
||||
# argv-equal(argv[1], argv[2])
|
||||
# . . push argv[2]
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
# push argv[1]
|
||||
# . . push argv[1]
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call argv-equal/disp32
|
||||
# exit(EAX)
|
||||
$exit:
|
||||
# syscall(exit, EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Null-terminated vs length-prefixed ascii strings.
|
||||
# Null-terminated vs length-prefixed ascii strings.
|
||||
#
|
||||
# By default we create strings with a 4-byte length prefix rather than a null suffix.
|
||||
# However we still need null-prefixed strings when interacting with the Linux
|
||||
|
@ -108,7 +108,7 @@ $kernel-string-equal:end:
|
|||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
## tests
|
||||
# - tests
|
||||
|
||||
test-compare-null-kernel-string-with-empty-array:
|
||||
# EAX = kernel-string-equal(Null-kernel-string, "")
|
||||
|
@ -119,7 +119,7 @@ test-compare-null-kernel-string-with-empty-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 1, msg)
|
||||
# check-ints-equal(EAX, 1, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
|
||||
68/push 1/imm32/true
|
||||
|
@ -139,7 +139,7 @@ test-compare-null-kernel-string-with-non-empty-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0, msg)
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -159,7 +159,7 @@ test-compare-kernel-string-with-equal-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 1, msg)
|
||||
# check-ints-equal(EAX, 1, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 1/imm32/true
|
||||
|
@ -179,7 +179,7 @@ test-compare-kernel-string-with-inequal-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0, msg)
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -199,7 +199,7 @@ test-compare-kernel-string-with-empty-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0)
|
||||
# check-ints-equal(EAX, 0)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -219,7 +219,7 @@ test-compare-kernel-string-with-shorter-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0)
|
||||
# check-ints-equal(EAX, 0)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -239,7 +239,7 @@ test-compare-kernel-string-with-longer-array:
|
|||
e8/call kernel-string-equal/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# . . call check-ints-equal(EAX, 0)
|
||||
# check-ints-equal(EAX, 0)
|
||||
# . . push args
|
||||
68/push "F - test-compare-kernel-string-with-longer-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
|
@ -250,7 +250,7 @@ test-compare-kernel-string-with-longer-array:
|
|||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
c3/return
|
||||
|
||||
## helpers
|
||||
# - helpers
|
||||
|
||||
# print msg to stderr if a != b, otherwise print "."
|
||||
check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
||||
|
@ -263,19 +263,19 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
|||
# load args into EAX, EBX and ECX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 0/r32/EAX 0x8/disp8 . # copy *(EBP+8) to EAX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX
|
||||
# if EAX == b/EBX
|
||||
# if EAX == b/EBX print('.') and return
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
|
||||
75/jump-if-unequal $check-ints-equal:else/disp8
|
||||
# print('.')
|
||||
# . write-stderr('.')
|
||||
# . . push args
|
||||
68/push "."/imm32
|
||||
# . . call
|
||||
e8/call write-stderr/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# return
|
||||
# . return
|
||||
eb/jump $check-ints-equal:end/disp8
|
||||
# else:
|
||||
# otherwise print(msg)
|
||||
$check-ints-equal:else:
|
||||
# copy msg into ECX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX
|
||||
|
@ -312,15 +312,15 @@ write-stderr: # s : (address array byte) -> <void>
|
|||
52/push-EDX
|
||||
53/push-EBX
|
||||
# syscall(write, 2/stderr, (data) s+4, (size) *s)
|
||||
# fd = 2 (stderr)
|
||||
# . . fd = 2 (stderr)
|
||||
bb/copy-to-EBX 2/imm32
|
||||
# x = s+4
|
||||
# . . x = s+4
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX
|
||||
81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add to ECX
|
||||
# size = *s
|
||||
# . . size = *s
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 2/r32/EDX 8/disp8 . # copy *(EBP+8) to EDX
|
||||
8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX
|
||||
# syscall
|
||||
# . . syscall
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
# . restore registers
|
||||
|
@ -328,7 +328,7 @@ write-stderr: # s : (address array byte) -> <void>
|
|||
5a/pop-to-EDX
|
||||
59/pop-to-ECX
|
||||
58/pop-to-EAX
|
||||
# end
|
||||
# . end
|
||||
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## example showing mmap syscall
|
||||
# Example showing mmap syscall.
|
||||
# Create a new segment using mmap, save the address, write to it.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
|
@ -16,7 +16,7 @@
|
|||
b8/copy-to-EAX 0x5a/imm32/mmap
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# store to *EAX
|
||||
# write to *EAX to check that we have access to the newly-allocated segment
|
||||
c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0x34/imm32 # copy to *EAX
|
||||
|
||||
# syscall(exit, EAX)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## add 1 and 1, and return the result in the exit code
|
||||
# Add 1 and 1, and return the result in the exit code.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
# $ subx translate examples/ex2.subx -o examples/ex2
|
||||
|
@ -9,9 +9,11 @@
|
|||
|
||||
== code
|
||||
|
||||
# EBX = 1
|
||||
bb/copy-to-EBX 1/imm32
|
||||
# increment EBX
|
||||
43/inc-EBX
|
||||
# exit(EBX)
|
||||
# syscall(exit, EBX)
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## add the first 10 numbers, and return the result in the exit code
|
||||
# Add the first 10 numbers, and return the result in the exit code.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
# $ subx translate examples/ex3.subx -o examples/ex3
|
||||
|
@ -29,7 +29,7 @@ $loop:
|
|||
eb/jump $loop/disp8
|
||||
|
||||
$exit:
|
||||
# exit(EBX)
|
||||
# syscall(exit, EBX)
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## read a character from stdin, save it to a global, write it to stdout
|
||||
# Read a character from stdin, save it to a global, write it to stdout.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
# $ subx translate examples/ex4.subx -o examples/ex4
|
||||
|
@ -7,24 +7,24 @@
|
|||
== code
|
||||
|
||||
# syscall(read, stdin, X, 1)
|
||||
# fd = 0 (stdin)
|
||||
# . fd = 0 (stdin)
|
||||
bb/copy-to-EBX 0/imm32
|
||||
# initialize X (location to write result to)
|
||||
# . data = X (location to write result to)
|
||||
b9/copy-to-ECX X/imm32
|
||||
# size = 1 character
|
||||
# . size = 1 character
|
||||
ba/copy-to-EDX 1/imm32
|
||||
# syscall
|
||||
# . syscall
|
||||
b8/copy-to-EAX 3/imm32/read
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# syscall(write, stdout, X, 1)
|
||||
# fd = 1 (stdout)
|
||||
# . fd = 1 (stdout)
|
||||
bb/copy-to-EBX 1/imm32
|
||||
# initialize X (location to read from)
|
||||
# . initialize X (location to read from)
|
||||
b9/copy-to-ECX X/imm32
|
||||
# size = 1 character
|
||||
# . size = 1 character
|
||||
ba/copy-to-EDX 1/imm32
|
||||
# syscall
|
||||
# . syscall
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## read a character from stdin, save it to a local on the stack, write it to stdout
|
||||
# Read a character from stdin, save it to a local on the stack, write it to stdout.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
# $ subx translate examples/ex5.subx -o examples/ex5
|
||||
|
@ -14,24 +14,24 @@
|
|||
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # subtract from ESP
|
||||
|
||||
# syscall(read, stdin, x, 1)
|
||||
# fd = 0 (stdin)
|
||||
# . fd = 0 (stdin)
|
||||
bb/copy-to-EBX 0/imm32
|
||||
# initialize x (location to write result to)
|
||||
# . data = x (location to write result to)
|
||||
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
|
||||
# size = 1 character
|
||||
# . size = 1 character
|
||||
ba/copy-to-EDX 1/imm32
|
||||
# syscall
|
||||
# . syscall
|
||||
b8/copy-to-EAX 3/imm32/read
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# syscall(write, stdout, x, 1)
|
||||
# fd = 1 (stdout)
|
||||
# . fd = 1 (stdout)
|
||||
bb/copy-to-EBX 1/imm32
|
||||
# initialize x (location to read from)
|
||||
# . data = x (location to read from)
|
||||
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
|
||||
# size = 1 character
|
||||
# . size = 1 character
|
||||
ba/copy-to-EDX 1/imm32
|
||||
# syscall
|
||||
# . syscall
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## print out a (global variable) string to stdout
|
||||
# Print out a (global variable) string to stdout.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
# $ subx translate examples/ex6.subx -o examples/ex6
|
||||
|
@ -10,14 +10,14 @@
|
|||
# . 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
|
||||
|
||||
# syscall(write, stdout, X, size)
|
||||
# fd = 1 (stdout)
|
||||
# syscall(write, stdout, X, Size)
|
||||
# . fd = 1 (stdout)
|
||||
bb/copy-to-EBX 1/imm32
|
||||
# initialize X (location to write result to)
|
||||
# . initialize X (location to write result to)
|
||||
b9/copy-to-ECX X/imm32
|
||||
# initialize size
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 2/r32/EDX Size/disp32 . # copy *size to EDX
|
||||
# syscall
|
||||
# . initialize Size
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 2/r32/EDX Size/disp32 . # copy *Size to EDX
|
||||
# . syscall
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
## example showing file syscalls
|
||||
# Example showing file syscalls.
|
||||
#
|
||||
# Create a file, open it for writing, write a character to it, close it, open
|
||||
# it for reading, read a character from it, close it, delete it, and return
|
||||
# the character read.
|
||||
|
@ -32,20 +33,20 @@
|
|||
89/copy 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to *EBX
|
||||
|
||||
# syscall(write, Stream, "a", 1)
|
||||
# load stream
|
||||
# . load stream
|
||||
bb/copy-to-EBX Stream/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
|
||||
#
|
||||
# .
|
||||
b9/copy-to-ECX A/imm32
|
||||
ba/copy-to-EDX 1/imm32/size
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# syscall(close, Stream)
|
||||
# load stream
|
||||
# . load stream
|
||||
bb/copy-to-EBX Stream/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
|
||||
#
|
||||
# .
|
||||
b8/copy-to-EAX 6/imm32/close
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
|
@ -55,22 +56,22 @@
|
|||
ba/copy-to-EDX 0x180/imm32/fixed-perms
|
||||
b8/copy-to-EAX 5/imm32/open
|
||||
cd/syscall 0x80/imm8
|
||||
# save Stream
|
||||
# . save Stream
|
||||
bb/copy-to-EBX Stream/imm32
|
||||
89/copy 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to *EBX
|
||||
|
||||
# syscall(read, Stream, B, 1)
|
||||
# load stream
|
||||
# . load stream
|
||||
bb/copy-to-EBX Stream/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
|
||||
#
|
||||
# .
|
||||
b9/copy-to-ECX B/imm32
|
||||
ba/copy-to-EDX 1/imm32/size
|
||||
b8/copy-to-EAX 3/imm32/read
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# syscall(close, Stream)
|
||||
# load stream
|
||||
# . load stream
|
||||
bb/copy-to-EBX Stream/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
|
||||
#
|
||||
|
@ -83,7 +84,7 @@
|
|||
cd/syscall 0x80/imm8
|
||||
|
||||
# syscall(exit, b)
|
||||
# load b
|
||||
# . load b
|
||||
bb/copy-to-EBX B/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
|
||||
#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Example reading commandline arguments: compute length of first arg.
|
||||
# Example reading commandline arguments: compute length of first arg.
|
||||
#
|
||||
# To run (from the subx directory):
|
||||
# $ subx translate examples/ex8.subx -o examples/ex8
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# . . call ascii-length(argv[1])
|
||||
# EAX = ascii-length(argv[1])
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
|
@ -34,13 +34,13 @@
|
|||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
ascii-length: # (s)
|
||||
# initialize s (EDX)
|
||||
ascii-length: # s : (address array byte) -> n/EAX
|
||||
# EDX = s
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 2/r32/EDX 4/disp8 . # copy *(ESP+4) to EDX
|
||||
# var result = 0 (EAX)
|
||||
# var result/EAX = 0
|
||||
b8/copy-to-EAX 0/imm32
|
||||
$ascii-length-loop:
|
||||
# var c = *s (ECX)
|
||||
# var c/ECX = *s
|
||||
8a/copy 0/mod/* 2/rm32/EDX . . . 1/r32/ECX . . # copy byte at *EDX to lower byte of ECX
|
||||
# if c == '\0' break
|
||||
81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX
|
||||
|
@ -52,7 +52,7 @@ $ascii-length-loop:
|
|||
# loop
|
||||
eb/jump $ascii-length-loop/disp8
|
||||
$ascii-length-ret:
|
||||
# return (result in EAX)
|
||||
# return EAX
|
||||
c3/return
|
||||
|
||||
# . . vim:nowrap:textwidth=0
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
## Example showing arg order on the stack.
|
||||
# Example showing arg order on the stack.
|
||||
#
|
||||
# Show difference between ascii codes of first letter of first arg and first
|
||||
# letter of second arg.
|
||||
#
|
||||
|
@ -23,16 +24,16 @@
|
|||
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# . . call ascii-difference(argv[1], argv[2])
|
||||
# push argv[2]
|
||||
# ascii-difference(argv[1], argv[2])
|
||||
# . . push argv[2]
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
# push argv[1]
|
||||
# . . push argv[1]
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
# . . call
|
||||
e8/call ascii-difference/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# exit(EAX)
|
||||
# syscall(exit, EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
|
Loading…
Reference in New Issue