4808 - clean up comments in all subx files

This commit is contained in:
Kartik Agaram 2018-11-30 16:45:15 -08:00
parent 4cb6970d9d
commit 9d27e966b5
25 changed files with 394 additions and 384 deletions

View File

@ -7,14 +7,17 @@
# main: (manual test if this is the last file loaded) # main: (manual test if this is the last file loaded)
# check-ints-equal(34, 34) # check-ints-equal(34, 34)
# . . push args
68/push "error in check-ints-equal"/imm32 68/push "error in check-ints-equal"/imm32
68/push 34/imm32 68/push 34/imm32
68/push 34/imm32 68/push 34/imm32
# . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# syscall(exit, 0) # syscall(exit, 0)
bb/copy-to-EBX 0/imm32 bb/copy-to-EBX 0/imm32
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# print msg to stderr if a != b, otherwise print "." # 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 # 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 . 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 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 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
75/jump-if-unequal $check-ints-equal:else/disp8 75/jump-if-unequal $check-ints-equal:else/disp8
# _write(2/stderr, '.') # . _write(2/stderr, '.')
# . . push args # . . push args
68/push "."/imm32 68/push "."/imm32
68/push 2/imm32/stderr 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 e8/call _write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# return # . return
eb/jump $check-ints-equal:end/disp8 eb/jump $check-ints-equal:end/disp8
# else: # otherwise print error message
$check-ints-equal:else: $check-ints-equal:else:
# _write(2/stderr, msg) # . _write(2/stderr, msg)
# . . push args # . . 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 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 51/push-ECX
@ -52,7 +55,7 @@ $check-ints-equal:else:
e8/call _write/disp32 e8/call _write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push Newline/imm32 68/push Newline/imm32
68/push 2/imm32/stderr 68/push 2/imm32/stderr

View File

@ -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. # 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 # However we still need null-prefixed strings when interacting with the Linux
@ -21,7 +21,7 @@
# main: # main:
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. 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 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 b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
@ -109,7 +109,7 @@ $kernel-string-equal:end:
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
## tests # - tests
test-compare-null-kernel-string-with-empty-array: test-compare-null-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "") # 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 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32 68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
@ -140,7 +140,7 @@ test-compare-null-kernel-string-with-non-empty-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32 68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -160,7 +160,7 @@ test-compare-kernel-string-with-equal-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
@ -180,7 +180,7 @@ test-compare-kernel-string-with-inequal-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -200,7 +200,7 @@ test-compare-kernel-string-with-empty-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -220,7 +220,7 @@ test-compare-kernel-string-with-shorter-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32 68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -240,7 +240,7 @@ test-compare-kernel-string-with-longer-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-longer-array"/imm32 68/push "F - test-compare-kernel-string-with-longer-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false

View File

@ -14,10 +14,10 @@
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 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 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
b8/copy-to-EAX 1/imm32/exit b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8

View File

@ -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 # . 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: # 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-'. 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 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 b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
@ -84,7 +85,7 @@ $string-equal:end:
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
## tests # - tests
test-compare-empty-with-empty-string: test-compare-empty-with-empty-string:
# EAX = string-equal("", "") # EAX = string-equal("", "")
@ -95,7 +96,7 @@ test-compare-empty-with-empty-string:
e8/call string-equal/disp32 e8/call string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-empty-with-empty-string"/imm32 68/push "F - test-compare-empty-with-empty-string"/imm32
68/push 1/imm32/true 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 e8/call string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-empty-with-non-empty-string"/imm32 68/push "F - test-compare-empty-with-non-empty-string"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -135,7 +136,7 @@ test-compare-equal-strings:
e8/call string-equal/disp32 e8/call string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-equal-strings"/imm32 68/push "F - test-compare-equal-strings"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
@ -155,7 +156,7 @@ test-compare-inequal-strings-equal-lengths:
e8/call string-equal/disp32 e8/call string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-inequal-strings-equal-lengths"/imm32 68/push "F - test-compare-inequal-strings-equal-lengths"/imm32
68/push 0/imm32/false 68/push 0/imm32/false

View File

@ -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 # . 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: # 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-'. 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) # 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 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 # EDX = t->length
8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX 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) # EAX = _append-3(&t->data[t->write], &t->data[t->length], line)
# push line # . . push line
56/push-ESI 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 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 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 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 53/push-EBX
# . . call # . . call
@ -107,12 +108,12 @@ trace: # t : (address trace-stream), line : string
# refresh ECX = t->write # refresh ECX = t->write
8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX 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) # EAX = _append-3(&t->data[t->write], &t->data[t->length], line)
# push line # . . push line
68/push Newline/imm32 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 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 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 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 53/push-EBX
# . . call # . . call
@ -172,7 +173,7 @@ $clear-trace-stream:end:
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
## tests # - tests
test-trace-single: test-trace-single:
# clear-trace-stream(_test-trace-stream) # clear-trace-stream(_test-trace-stream)
@ -194,7 +195,7 @@ test-trace-single:
# . . push args # . . push args
68/push "F - test-trace-single"/imm32 68/push "F - test-trace-single"/imm32
68/push 0x0a6241/imm32/Ab-newline 68/push 0x0a6241/imm32/Ab-newline
# push *_test-trace-stream.data # . . push *_test-trace-stream.data
b8/copy-to-EAX _test-trace-stream/imm32 b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# . . call # . . call
@ -232,7 +233,7 @@ test-trace-appends:
# . . push args # . . push args
68/push "F - test-trace-appends"/imm32 68/push "F - test-trace-appends"/imm32
68/push 0x0a440a43/imm32/C-newline-D-newline 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 b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# . . call # . . call
@ -262,7 +263,7 @@ test-trace-empty-line:
# . . push args # . . push args
68/push "F - test-trace-empty-line"/imm32 68/push "F - test-trace-empty-line"/imm32
68/push 0/imm32 68/push 0/imm32
# push *_test-trace-stream.data # . . push *_test-trace-stream.data
b8/copy-to-EAX _test-trace-stream/imm32 b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# . . call # . . call
@ -272,7 +273,7 @@ test-trace-empty-line:
# end # end
c3/return c3/return
## helpers # - helpers
# 3-argument variant of _append # 3-argument variant of _append
_append-3: # out : address, outend : address, s : (array byte) -> num_bytes_appended/EAX _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 # . save registers
51/push-ECX 51/push-ECX
# _append-4(out, outend, &s.data[0], &s.data[s.length]) -> num_bytes_appended/EAX # _append-4(out, outend, &s.data[0], &s.data[s.length]) -> num_bytes_appended/EAX
# push &s.data[s.length] # . . push &s.data[s.length]
# EAX = s
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none 0/r32/EAX 0x10/disp8 . # copy *(EBP+16) to EAX 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 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 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 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 8d/copy-address 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy EAX+4 to ECX
51/push-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) 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call _append-4/disp32 e8/call _append-4/disp32

View File

@ -58,12 +58,12 @@ $write:fake:
# EBX = f->length # EBX = f->length
8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 3/r32/EBX 8/disp8 . # copy *(ECX+8) to EBX 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) # 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) 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 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 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 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 53/push-EBX
# . . call # . . call
@ -149,7 +149,7 @@ test-write-single:
# . . push args # . . push args
68/push "F - test-write-single"/imm32 68/push "F - test-write-single"/imm32
68/push 0x006241/imm32/Ab 68/push 0x006241/imm32/Ab
# push *_test-stream->data # . . push *_test-stream->data
b8/copy-to-EAX _test-stream/imm32 b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# . . call # . . call
@ -187,7 +187,7 @@ test-write-appends:
# . . push args # . . push args
68/push "F - test-write-appends"/imm32 68/push "F - test-write-appends"/imm32
68/push 0x00004443/imm32/C-D 68/push 0x00004443/imm32/C-D
# push *_test-stream->data # . . push *_test-stream->data
b8/copy-to-EAX _test-stream/imm32 b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# . . call # . . call

View File

@ -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 # 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 # 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. # bytes for the return address and 4 bytes to push EBP above.
# So EBP at this point is X-16. # So EBP at this point is X-16.
# #
@ -139,12 +139,12 @@ test-stop-skips-returns-on-exit:
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
50/push-EAX 50/push-EAX
# . . call # . . call
e8/call _test-stop-1/disp32 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 # restore args
58/pop-to-EAX 58/pop-to-EAX
# check that _test-stop-1 tried to call exit(1) # check that _test-stop-1 tried to call exit(1)
@ -152,7 +152,7 @@ test-stop-skips-returns-on-exit:
# . . push args # . . push args
68/push "F - test-stop-skips-returns-on-exit"/imm32 68/push "F - test-stop-skips-returns-on-exit"/imm32
68/push 2/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) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# . . call # . . call
e8/call check-ints-equal/disp32 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call _test-stop-2/disp32 e8/call _test-stop-2/disp32
## should never get past this point # should never get past this point
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# signal test failed: check-ints-equal(1, 0, msg) # signal test failed: check-ints-equal(1, 0, msg)
@ -194,13 +194,13 @@ _test-stop-2: # ed : (address exit-descriptor)
# . prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to 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 # . . push args
68/push 1/imm32 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call stop/disp32 e8/call stop/disp32
## should never get past this point # should never get past this point
# . epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP

View File

@ -56,7 +56,7 @@ read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/EAX
# . prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to 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) 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 7d/jump-if-greater-or-equal $read:fake/disp8
# . . push args # . . push args
@ -69,7 +69,7 @@ read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/EAX
# return # return
eb/jump $read:end/disp8 eb/jump $read:end/disp8
$read:fake: $read:fake:
## otherwise, treat 'f' as a stream to scan from # otherwise, treat 'f' as a stream to scan from
# . save registers # . save registers
56/push-ESI 56/push-ESI
57/push-EDI 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 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], # EAX = _append-4(out = &s->data[s->write], outend = &s->data[s->length],
# in = &f->data[f->read], inend = &f->data[f->write]) # 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 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 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 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 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 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 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 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 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 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 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 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 50/push-EAX
@ -112,7 +112,7 @@ $read:end:
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
## helpers # - helpers
# idea: a clear-if-empty method on streams that clears only if f.read == f.write # 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. # 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 # EDX = s->length
8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 8/disp8 . # copy *(ESI+8) to EDX 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) # 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 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 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 29/subtract 3/mod/direct 2/rm32/EDX . . . 0/r32/EAX . . # subtract EAX from EDX
# syscall # . . syscall
b8/copy-to-EAX 3/imm32/read b8/copy-to-EAX 3/imm32/read
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# add the result EAX to s->write # 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 # use one less register, but doesn't increase the amount of spilling (ECX
# and EDX must be used, and EAX must be clobbered anyway). # and EDX must be used, and EAX must be clobbered anyway).
## tests # - tests
test-read-single: test-read-single:
# - write a single character into _test-stream, then read from its buffered-file
# clear-stream(_test-stream) # clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -222,7 +223,7 @@ test-read-single:
# . . push args # . . push args
68/push "F - test-read-single"/imm32 68/push "F - test-read-single"/imm32
68/push 0x006241/imm32/Ab 68/push 0x006241/imm32/Ab
# push *_test-stream-buffer->data # . . push *_test-stream-buffer->data
b8/copy-to-EAX _test-stream-buffer/imm32 b8/copy-to-EAX _test-stream-buffer/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# . . call # . . call
@ -233,7 +234,7 @@ test-read-single:
c3/return c3/return
test-read-is-stateful: 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) # clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -284,7 +285,7 @@ test-read-is-stateful:
# . . push args # . . push args
68/push "F - test-read-is-stateful"/imm32 68/push "F - test-read-is-stateful"/imm32
68/push 0x00004443/imm32/C-D 68/push 0x00004443/imm32/C-D
# push *_test-stream-buffer->data # . push *_test-stream-buffer->data
b8/copy-to-EAX _test-stream-buffer/imm32 b8/copy-to-EAX _test-stream-buffer/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# . . call # . . call
@ -295,22 +296,23 @@ test-read-is-stateful:
c3/return c3/return
test-read-returns-0-on-end-of-file: test-read-returns-0-on-end-of-file:
## read after hitting end-of-file, check that result is 0 # - read after hitting end-of-file, check that result is 0
# clear-stream(_test-stream) # setup
# . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-stream-buffer/imm32 68/push _test-stream-buffer/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -318,8 +320,8 @@ test-read-returns-0-on-end-of-file:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## first read gets to end-of-file # first read gets to end-of-file
# read(_test-stream, _test-stream-buffer) # . read(_test-stream, _test-stream-buffer)
# . . push args # . . push args
68/push _test-stream-buffer/imm32 68/push _test-stream-buffer/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -327,8 +329,8 @@ test-read-returns-0-on-end-of-file:
e8/call read/disp32 e8/call read/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## second read # second read
# read(_test-stream, _test-stream-buffer) # . read(_test-stream, _test-stream-buffer)
# . . push args # . . push args
68/push _test-stream-buffer/imm32 68/push _test-stream-buffer/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32

View File

@ -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 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 # ECX = f->read
8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 8/disp8 . # copy *(ESI+8) to ECX 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) 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 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 # . . push args
8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy ESI+4 to EAX 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy ESI+4 to EAX
50/push-EAX 50/push-EAX
@ -63,7 +64,7 @@ read-byte: # f : (address buffered-file) -> byte/EAX
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
50/push-EAX 50/push-EAX
ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI 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 b8/copy-to-EAX 0xffffffff/imm32
eb/jump $read-byte:end/disp8 eb/jump $read-byte:end/disp8
$read-byte:from-stream: $read-byte:from-stream:
# reading from stream
# AL = f->data[f->read] # AL = f->data[f->read]
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 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 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 # todo: how should write-byte look? What should it do when the output has no
# space remaining? Maybe return an error code. # space remaining? Maybe return an error code.
## tests # - tests
test-read-byte-single: test-read-byte-single:
## check that read-byte returns first byte of 'file' # - check that read-byte returns first byte of 'file'
# clear-stream(_test-stream) # setup
# . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
@ -114,7 +117,7 @@ test-read-byte-single:
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -138,19 +141,20 @@ test-read-byte-single:
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # . end
c3/return c3/return
test-read-byte-multiple: test-read-byte-multiple:
## call read-byte twice, check that second call returns second byte # - call read-byte twice, check that second call returns second byte
# clear-stream(_test-stream) # setup
# . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
@ -159,7 +163,7 @@ test-read-byte-multiple:
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -190,19 +194,20 @@ test-read-byte-multiple:
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # . end
c3/return c3/return
test-read-byte-end-of-file: test-read-byte-end-of-file:
## call read-byte on an empty 'file', check that it returns -1 # - call read-byte on an empty 'file', check that it returns -1
# clear-stream(_test-stream) # setup
# . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
@ -227,7 +232,7 @@ test-read-byte-end-of-file:
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # . end
c3/return c3/return
== data == data

View File

@ -45,19 +45,19 @@ $write-stream:fake:
# EDI = s # 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 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]) # 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 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 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 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 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 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 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 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 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 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 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 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 50/push-EAX
@ -97,13 +97,13 @@ _write-stream: # fd : int, s : (address stream) -> <void>
# EDX = s->write # EDX = s->write
8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX 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) # 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 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 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 29/subtract 3/mod/direct 2/rm32/EDX . . . 7/r32/EDI . . # subtract EDI from EDX
# syscall # . . syscall
b8/copy-to-EAX 4/imm32/write b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# . restore registers # . restore registers
@ -119,21 +119,22 @@ _write-stream: # fd : int, s : (address stream) -> <void>
c3/return c3/return
test-write-stream-single: test-write-stream-single:
# clear-stream(_test-stream) # setup
# . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-stream2/imm32 68/push _test-stream2/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push _test-stream2/imm32 68/push _test-stream2/imm32
@ -160,25 +161,26 @@ test-write-stream-single:
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # . end
c3/return c3/return
test-write-stream-appends: test-write-stream-appends:
# clear-stream(_test-stream) # setup
# . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-stream2/imm32 68/push _test-stream2/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push "C"/imm32 68/push "C"/imm32
68/push _test-stream2/imm32 68/push _test-stream2/imm32
@ -186,7 +188,8 @@ test-write-stream-appends:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push _test-stream2/imm32 68/push _test-stream2/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -194,7 +197,8 @@ test-write-stream-appends:
e8/call write-stream/disp32 e8/call write-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "D"/imm32 68/push "D"/imm32
68/push _test-stream2/imm32 68/push _test-stream2/imm32
@ -202,7 +206,7 @@ test-write-stream-appends:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push _test-stream2/imm32 68/push _test-stream2/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -221,7 +225,7 @@ test-write-stream-appends:
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # . end
c3/return c3/return
== data == data

View File

@ -33,10 +33,11 @@
# main: run tests if necessary, call 'compile' if not # main: run tests if necessary, call 'compile' if not
# . prolog # . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 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 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 7e/jump-if-lesser-or-equal $run-main/disp8
# and if (argv[1] == "test") # . argv[1] == "test"
# . . push args # . . push args
68/push "test"/imm32 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) 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 # . check result
3d/compare-EAX 1/imm32 3d/compare-EAX 1/imm32
75/jump-if-not-equal $run-main/disp8 75/jump-if-not-equal $run-main/disp8
# then return run-tests() # . run-tests()
e8/call run-tests/disp32 e8/call run-tests/disp32
#? e8/call test-get-num-reads-multiple-digits/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 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 eb/jump $main:end/disp8
$run-main: $run-main:
# allocate space for an exit-descriptor # - otherwise read a program from stdin and emit its translation to stdout
# . var ed/EAX : (address exit-descriptor) # var ed/EAX : exit-descriptor
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 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 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 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 # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push 2/imm32/stderr 68/push 2/imm32/stderr
@ -69,7 +71,7 @@ $run-main:
e8/call compile/disp32 e8/call compile/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 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 bb/copy-to-EBX 0/imm32
$main:end: $main:end:
b8/copy-to-EAX 1/imm32/exit 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 # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
# Look = get-char(in) # . Look = get-char(in)
# . . push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# . . call # . . 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 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 # num->length = 7
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 8/disp8 7/imm32 # copy to *(ECX+8) 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 # . . push args
51/push-ECX 51/push-ECX
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . 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 . . 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) 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 e8/call get-num/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# EAX = write(_test-stream, "Ab") # render 'num' into the following template on 'out':
# . . push args # bb/copy-to-EBX _num_
68/push "Ab"/imm32 # b8/copy-to-EAX 1/imm32/exit
68/push _test-stream/imm32 # cd/syscall 0x80/imm8
# . . call #
e8/call write/disp32 # . EAX = write(out, "bb/copy-to-EBX ")
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, "bb/copy-to-EBX ")
# . . push args # . . push args
68/push "bb/copy-to-EBX "/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
51/push-ECX/num 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) 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 e8/call write-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(out, Newline) # . write(out, Newline)
# . . push args # . . push args
68/push Newline/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "b8/copy-to-EAX 1/imm32/exit"/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, Newline) # . write(out, Newline)
# . . push args # . . push args
68/push Newline/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "cd/syscall 0x80/imm8"/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, Newline) # . write(out, Newline)
# . . push args # . . push args
68/push Newline/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# . . restore registers # . restore registers
59/pop-to-ECX 59/pop-to-ECX
58/pop-to-EAX 58/pop-to-EAX
# . epilog # . epilog
@ -200,7 +200,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
# ++out.write # ++out.write
# Look = get-char(in) # Look = get-char(in)
# #
# within the loop we'll try to keep things in registers: # registers:
# ESI : in # ESI : in
# EDI : out # EDI : out
# EAX : temp # EAX : temp
@ -214,14 +214,15 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
# . prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to 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 # . . push args
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
# . . call # . . call
e8/call is-digit?/disp32 e8/call is-digit?/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 3d/compare-EAX 0/imm32
75/jump-if-not-equal $get-num:main/disp8 75/jump-if-not-equal $get-num:main/disp8
# . expected(ed, err, "integer") # . expected(ed, err, "integer")
@ -234,6 +235,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
$get-num:main: $get-num:main:
# - otherwise read a digit
# . save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
@ -253,7 +255,7 @@ $get-num:main:
# if out->write >= out->length error # if out->write >= out->length error
3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX 3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX
7d/jump-if-lesser $get-num:stage2/disp8 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 # . . push args
68/push "get-num: too many digits in number"/imm32 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) 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. # This test uses exit-descriptors. Use EBP for setting up local variables.
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# - clear all streams # setup
# clear-stream(_test-stream) # . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
@ -313,22 +315,22 @@ test-get-num-reads-single-digit:
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# - initialize 'in' # initialize 'in'
# write(_test-stream, "3") # . write(_test-stream, "3")
# . . push args # . . push args
68/push "3"/imm32 68/push "3"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -336,13 +338,11 @@ test-get-num-reads-single-digit:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# - initialize exit-descriptor 'ed' # initialize exit-descriptor 'ed' for the call to 'get-num' below
# allocate on stack # . var ed/EAX : exit-descriptor
# var ed/EAX : (address exit-descriptor)
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 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 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 # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
@ -350,15 +350,15 @@ test-get-num-reads-single-digit:
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# - prime the pump # prime the pump
# get-char(_test-buffered-file) # . get-char(_test-buffered-file)
# . . push args # . . push args
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
@ -366,7 +366,7 @@ test-get-num-reads-single-digit:
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-num/disp32 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 # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# check-ints-equal(*_test-output-stream.data, '3') # check-ints-equal(*_test-output-stream.data, '3')
@ -379,7 +379,7 @@ test-get-num-reads-single-digit:
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 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 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return 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. # This test uses exit-descriptors. Use EBP for setting up local variables.
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# - clear all streams # setup
# clear-stream(_test-stream) # . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/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 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# - initialize 'in' # initialize 'in'
# write(_test-stream, "3") # . write(_test-stream, "3")
# . . push args # . . push args
68/push "3"/imm32 68/push "3"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -429,13 +429,11 @@ test-get-num-aborts-on-non-digit-in-Look:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# - initialize exit-descriptor 'ed' # initialize exit-descriptor 'ed' for the call to 'get-num' below
# allocate on stack # . var ed/EAX : (address exit-descriptor)
# var ed/EAX : (address exit-descriptor)
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 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 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 # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
@ -443,8 +441,8 @@ test-get-num-aborts-on-non-digit-in-Look:
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# - don't initialize Look # *don't* prime the pump
# - get-num(in, out, err, ed) # get-num(in, out, err, ed)
# . . push args # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 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 # registers except ESP may be clobbered at this point
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 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 that get-num tried to call exit(1)
# check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 # . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
# . . push args # . . push args
68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32
68/push 2/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) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# . . call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 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 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call stop/disp32 e8/call stop/disp32
## should never get past this point # should never get past this point
# . epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call stop/disp32 e8/call stop/disp32
## should never get past this point # should never get past this point
# . epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return 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> get-char: # f : (address buffered-file) -> <void>
# . prolog # . prolog
55/push-EBP 55/push-EBP

View File

@ -33,10 +33,11 @@
# main: run tests if necessary, call 'compile' if not # main: run tests if necessary, call 'compile' if not
# . prolog # . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 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 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 7e/jump-if-lesser-or-equal $run-main/disp8
# and if (argv[1] == "test") # . argv[1] == "test"
# . . push args # . . push args
68/push "test"/imm32 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) 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 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check result # . check result
3d/compare-EAX 1/imm32 3d/compare-EAX 1/imm32
75/jump-if-not-equal $run-main/disp8 75/jump-if-not-equal $run-main/disp8
# then return run-tests() # . run-tests()
e8/call run-tests/disp32 e8/call run-tests/disp32
#? e8/call test-get-num-reads-multiple-digits/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 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 eb/jump $main:end/disp8
$run-main: $run-main:
# allocate space for an exit-descriptor # - otherwise read a program from stdin and emit its translation to stdout
# var ed/EAX : (address exit-descriptor) # var ed/EAX : exit-descriptor
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 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 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 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 # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push 2/imm32/stderr 68/push 2/imm32/stderr
@ -69,7 +71,7 @@ $run-main:
e8/call compile/disp32 e8/call compile/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 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 bb/copy-to-EBX 0/imm32
$main:end: $main:end:
b8/copy-to-EAX 1/imm32/exit 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 # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
# Look = get-char(in) # prime the pump
# . Look = get-char(in)
# . . push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# . . call # . . 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 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 # num->length = 7
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 8/disp8 7/imm32 # copy to *(ECX+8) 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 # . . push args
51/push-ECX 51/push-ECX
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . 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 . . 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) 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 e8/call get-num/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# EAX = write(_test-stream, "Ab") # render 'num' into the following template on 'out':
# . . push args # bb/copy-to-EBX _num_
68/push "Ab"/imm32 # b8/copy-to-EAX 1/imm32/exit
68/push _test-stream/imm32 # cd/syscall 0x80/imm8
# . . call #
e8/call write/disp32 # . EAX = write(out, "bb/copy-to-EBX ")
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, "bb/copy-to-EBX ")
# . . push args # . . push args
68/push "bb/copy-to-EBX "/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
51/push-ECX/num 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) 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 e8/call write-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(out, Newline) # . write(out, Newline)
# . . push args # . . push args
68/push Newline/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "b8/copy-to-EAX 1/imm32/exit"/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, Newline) # . write(out, Newline)
# . . push args # . . push args
68/push Newline/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "cd/syscall 0x80/imm8"/imm32 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) 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 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, Newline) # . write(out, Newline)
# . . push args # . . push args
68/push Newline/imm32 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) 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 # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to 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 # . . push args
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
# . . call # . . call
e8/call is-digit?/disp32 e8/call is-digit?/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 3d/compare-EAX 0/imm32
75/jump-if-not-equal $get-num:main/disp8 75/jump-if-not-equal $get-num:main/disp8
# expected(ed, err, "integer") # . expected(ed, err, "integer")
# . . push args # . . push args
68/push "integer"/imm32 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) 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 # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
$get-num:main: $get-num:main:
# - otherwise read a digit
# . save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
@ -259,7 +262,7 @@ $get-num:loop:
# if out->write >= out->length error # if out->write >= out->length error
3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX 3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX
7d/jump-if-lesser $get-num:loop-stage2/disp8 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 # . . push args
68/push "get-num: too many digits in number"/imm32 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) 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 e8/call get-char/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
# . . call # . . call
e8/call is-digit?/disp32 e8/call is-digit?/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 3d/compare-EAX 0/imm32
0f 85/jump-if-not-equal $get-num:loop/disp32 0f 85/jump-if-not-equal $get-num:loop/disp32
$get-num:loop-end: $get-num:loop-end:
@ -308,19 +312,19 @@ $get-num:loop-end:
c3/return c3/return
test-get-num-reads-single-digit: 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. # This test uses exit-descriptors. Use EBP for setting up local variables.
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## clear all streams # clear all streams
# clear-stream(_test-stream) # . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
@ -329,22 +333,22 @@ test-get-num-reads-single-digit:
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in' # initialize 'in'
# write(_test-stream, "3") # . write(_test-stream, "3")
# . . push args # . . push args
68/push "3"/imm32 68/push "3"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -352,13 +356,11 @@ test-get-num-reads-single-digit:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed' # initialize exit-descriptor 'ed' for the call to 'get-num' below
# allocate on stack # . var ed/EAX : exit-descriptor
# var ed/EAX : (address exit-descriptor)
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 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 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 # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
@ -366,15 +368,15 @@ test-get-num-reads-single-digit:
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## prime the pump # prime the pump
# get-char(_test-buffered-file) # . get-char(_test-buffered-file)
# . . push args # . . push args
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
@ -382,7 +384,7 @@ test-get-num-reads-single-digit:
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-num/disp32 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 # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# check-ints-equal(*_test-output-stream.data, '3') # check-ints-equal(*_test-output-stream.data, '3')
@ -395,25 +397,25 @@ test-get-num-reads-single-digit:
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 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 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
test-get-num-aborts-on-non-digit-in-Look: 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. # This test uses exit-descriptors. Use EBP for setting up local variables.
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## clear all streams # clear all streams
# clear-stream(_test-stream) # . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/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 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in' # initialize 'in'
# write(_test-stream, "3") # . write(_test-stream, "3")
# . . push args # . . push args
68/push "3"/imm32 68/push "3"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -445,13 +447,11 @@ test-get-num-aborts-on-non-digit-in-Look:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed' # initialize exit-descriptor 'ed' for the call to 'get-num' below
# allocate on stack # . var ed/EAX : (address exit-descriptor)
# var ed/EAX : (address exit-descriptor)
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 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 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 # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
@ -459,8 +459,8 @@ test-get-num-aborts-on-non-digit-in-Look:
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## don't initialize Look # *don't* prime the pump
## get-num(in, out, err, ed) # get-num(in, out, err, ed)
# . . push args # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 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 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-num/disp32 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 # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 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 that get-num tried to call exit(1)
# check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 # . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
# . . push args # . . push args
68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32
68/push 2/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) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# . . call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 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 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
test-get-num-reads-multiple-digits: 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. # This test uses exit-descriptors. Use EBP for setting up local variables.
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## clear all streams # clear all streams
# clear-stream(_test-stream) # . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
@ -509,22 +509,22 @@ test-get-num-reads-multiple-digits:
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in' # initialize 'in'
# write(_test-stream, "3456 x") # . write(_test-stream, "3456 x")
# . . push args # . . push args
68/push "3456"/imm32 68/push "3456"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -532,13 +532,11 @@ test-get-num-reads-multiple-digits:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed' # initialize exit-descriptor 'ed' for the call to 'get-num' below
# allocate on stack # . var ed/EAX : (address exit-descriptor)
# var ed/EAX : (address exit-descriptor)
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 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 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 # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
@ -546,15 +544,15 @@ test-get-num-reads-multiple-digits:
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## prime the pump # prime the pump
# get-char(_test-buffered-file) # . get-char(_test-buffered-file)
# . . push args # . . push args
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
@ -562,7 +560,7 @@ test-get-num-reads-multiple-digits:
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-num/disp32 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 # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# check-ints-equal(*_test-output-stream.data, '3456') # check-ints-equal(*_test-output-stream.data, '3456')
@ -575,25 +573,25 @@ test-get-num-reads-multiple-digits:
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 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 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
test-get-num-reads-multiple-digits-followed-by-nondigit: 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. # This test uses exit-descriptors. Use EBP for setting up local variables.
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## clear all streams # clear all streams
# clear-stream(_test-stream) # . clear-stream(_test-stream)
# . . push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/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 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# . . call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in' # initialize 'in'
# write(_test-stream, "3456 x") # . write(_test-stream, "3456 x")
# . . push args # . . push args
68/push "3456 x"/imm32 68/push "3456 x"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
@ -625,13 +623,11 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
e8/call write/disp32 e8/call write/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed' # initialize exit-descriptor 'ed' for the call to 'get-num' below
# allocate on stack # . var ed/EAX : (address exit-descriptor)
# var ed/EAX : (address exit-descriptor)
81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP 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 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 # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
@ -639,15 +635,15 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## prime the pump # prime the pump
# get-char(_test-buffered-file) # . get-char(_test-buffered-file)
# . . push args # . . push args
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 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 # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 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 68/push _test-buffered-file/imm32
# . . call # . . call
e8/call get-num/disp32 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 # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# check-ints-equal(*_test-output-stream.data, '3456') # 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 e8/call check-ints-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 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 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call stop/disp32 e8/call stop/disp32
## should never get past this point # should never get past this point
# . epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call stop/disp32 e8/call stop/disp32
## should never get past this point # should never get past this point
# . epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return 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> get-char: # f : (address buffered-file) -> <void>
# . prolog # . prolog
55/push-EBP 55/push-EBP

View File

@ -22,10 +22,11 @@
# main: # main:
# . prolog # . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 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 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 7e/jump-if-lesser-or-equal $run-main/disp8
# and if (argv[1] == "test") # . argv[1] == "test"
# . . push args # . . push args
68/push "test"/imm32 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) 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 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check result # . check result
3d/compare-EAX 1/imm32 3d/compare-EAX 1/imm32
75/jump-if-not-equal $run-main/disp8 75/jump-if-not-equal $run-main/disp8
# then return run-tests() # . run-tests()
e8/call run-tests/disp32 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 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 eb/jump $main:end/disp8 # where EAX will get copied to EBX
# else EAX = factorial(5) # - otherwise return factorial(5)
$run-main: $run-main:
# . . push args # . . push args
68/push 5/imm32 68/push 5/imm32
@ -49,20 +50,19 @@ $run-main:
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
$main:end: $main:end:
# exit(EAX) # syscall(exit, EAX)
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# factorial(n) factorial: # n : int -> int/EAX
factorial:
# . prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
53/push-EBX 53/push-EBX
# initialize EAX to 1 (base case) # EAX = 1 (base case)
b8/copy-to-EAX 1/imm32 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) 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 7e/jump-if-<= $factorial:end/disp8
# EBX = n-1 # EBX = n-1

View File

@ -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. # Just return 42.
# #
# To run (from the subx directory): # To run (from the subx directory):
@ -10,8 +10,8 @@
== code == code
# syscall(exit, 42)
bb/copy-to-EBX 2a/imm32 # 42 in hex bb/copy-to-EBX 2a/imm32 # 42 in hex
# exit(EBX)
b8/copy-to-EAX 1/imm32/exit b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8

View File

@ -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): # To run (from the subx directory):
# $ subx translate examples/ex10.subx -o examples/ex10 # $ subx translate examples/ex10.subx -o examples/ex10
@ -20,15 +20,14 @@
# ... # ...
# . prolog # . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# . . call argv-equal(argv[1], argv[2]) # argv-equal(argv[1], argv[2])
# push 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) 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call argv-equal/disp32 e8/call argv-equal/disp32
# exit(EAX) # syscall(exit, EAX)
$exit:
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8

View File

@ -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. # 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 # However we still need null-prefixed strings when interacting with the Linux
@ -108,7 +108,7 @@ $kernel-string-equal:end:
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
## tests # - tests
test-compare-null-kernel-string-with-empty-array: test-compare-null-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "") # 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 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32 68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
@ -139,7 +139,7 @@ test-compare-null-kernel-string-with-non-empty-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32 68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -159,7 +159,7 @@ test-compare-kernel-string-with-equal-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
@ -179,7 +179,7 @@ test-compare-kernel-string-with-inequal-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -199,7 +199,7 @@ test-compare-kernel-string-with-empty-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -219,7 +219,7 @@ test-compare-kernel-string-with-shorter-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32 68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
@ -239,7 +239,7 @@ test-compare-kernel-string-with-longer-array:
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 # . . push args
68/push "F - test-compare-kernel-string-with-longer-array"/imm32 68/push "F - test-compare-kernel-string-with-longer-array"/imm32
68/push 0/imm32/false 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 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
## helpers # - helpers
# print msg to stderr if a != b, otherwise print "." # print msg to stderr if a != b, otherwise print "."
check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean 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 # 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 . 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 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 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
75/jump-if-unequal $check-ints-equal:else/disp8 75/jump-if-unequal $check-ints-equal:else/disp8
# print('.') # . write-stderr('.')
# . . push args # . . push args
68/push "."/imm32 68/push "."/imm32
# . . call # . . call
e8/call write-stderr/disp32 e8/call write-stderr/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# return # . return
eb/jump $check-ints-equal:end/disp8 eb/jump $check-ints-equal:end/disp8
# else: # otherwise print(msg)
$check-ints-equal:else: $check-ints-equal:else:
# copy msg into ECX # 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 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 52/push-EDX
53/push-EBX 53/push-EBX
# syscall(write, 2/stderr, (data) s+4, (size) *s) # syscall(write, 2/stderr, (data) s+4, (size) *s)
# fd = 2 (stderr) # . . fd = 2 (stderr)
bb/copy-to-EBX 2/imm32 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 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 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 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 8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX
# syscall # . . syscall
b8/copy-to-EAX 4/imm32/write b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# . restore registers # . restore registers
@ -328,7 +328,7 @@ write-stderr: # s : (address array byte) -> <void>
5a/pop-to-EDX 5a/pop-to-EDX
59/pop-to-ECX 59/pop-to-ECX
58/pop-to-EAX 58/pop-to-EAX
# end # . end
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return

View File

@ -1,4 +1,4 @@
## example showing mmap syscall # Example showing mmap syscall.
# Create a new segment using mmap, save the address, write to it. # Create a new segment using mmap, save the address, write to it.
# #
# To run (from the subx directory): # To run (from the subx directory):
@ -16,7 +16,7 @@
b8/copy-to-EAX 0x5a/imm32/mmap b8/copy-to-EAX 0x5a/imm32/mmap
cd/syscall 0x80/imm8 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 c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0x34/imm32 # copy to *EAX
# syscall(exit, EAX) # syscall(exit, EAX)

View File

@ -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): # To run (from the subx directory):
# $ subx translate examples/ex2.subx -o examples/ex2 # $ subx translate examples/ex2.subx -o examples/ex2
@ -9,9 +9,11 @@
== code == code
# EBX = 1
bb/copy-to-EBX 1/imm32 bb/copy-to-EBX 1/imm32
# increment EBX
43/inc-EBX 43/inc-EBX
# exit(EBX) # syscall(exit, EBX)
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8

View File

@ -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): # To run (from the subx directory):
# $ subx translate examples/ex3.subx -o examples/ex3 # $ subx translate examples/ex3.subx -o examples/ex3
@ -29,7 +29,7 @@ $loop:
eb/jump $loop/disp8 eb/jump $loop/disp8
$exit: $exit:
# exit(EBX) # syscall(exit, EBX)
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8

View File

@ -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): # To run (from the subx directory):
# $ subx translate examples/ex4.subx -o examples/ex4 # $ subx translate examples/ex4.subx -o examples/ex4
@ -7,24 +7,24 @@
== code == code
# syscall(read, stdin, X, 1) # syscall(read, stdin, X, 1)
# fd = 0 (stdin) # . fd = 0 (stdin)
bb/copy-to-EBX 0/imm32 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 b9/copy-to-ECX X/imm32
# size = 1 character # . size = 1 character
ba/copy-to-EDX 1/imm32 ba/copy-to-EDX 1/imm32
# syscall # . syscall
b8/copy-to-EAX 3/imm32/read b8/copy-to-EAX 3/imm32/read
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# syscall(write, stdout, X, 1) # syscall(write, stdout, X, 1)
# fd = 1 (stdout) # . fd = 1 (stdout)
bb/copy-to-EBX 1/imm32 bb/copy-to-EBX 1/imm32
# initialize X (location to read from) # . initialize X (location to read from)
b9/copy-to-ECX X/imm32 b9/copy-to-ECX X/imm32
# size = 1 character # . size = 1 character
ba/copy-to-EDX 1/imm32 ba/copy-to-EDX 1/imm32
# syscall # . syscall
b8/copy-to-EAX 4/imm32/write b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8

View File

@ -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): # To run (from the subx directory):
# $ subx translate examples/ex5.subx -o examples/ex5 # $ 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 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # subtract from ESP
# syscall(read, stdin, x, 1) # syscall(read, stdin, x, 1)
# fd = 0 (stdin) # . fd = 0 (stdin)
bb/copy-to-EBX 0/imm32 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 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 ba/copy-to-EDX 1/imm32
# syscall # . syscall
b8/copy-to-EAX 3/imm32/read b8/copy-to-EAX 3/imm32/read
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# syscall(write, stdout, x, 1) # syscall(write, stdout, x, 1)
# fd = 1 (stdout) # . fd = 1 (stdout)
bb/copy-to-EBX 1/imm32 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 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 ba/copy-to-EDX 1/imm32
# syscall # . syscall
b8/copy-to-EAX 4/imm32/write b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8

View File

@ -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): # To run (from the subx directory):
# $ subx translate examples/ex6.subx -o examples/ex6 # $ subx translate examples/ex6.subx -o examples/ex6
@ -10,14 +10,14 @@
# . op subop mod rm32 base index scale r32 # . 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 # . 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) # syscall(write, stdout, X, Size)
# fd = 1 (stdout) # . fd = 1 (stdout)
bb/copy-to-EBX 1/imm32 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 b9/copy-to-ECX X/imm32
# initialize size # . initialize Size
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 2/r32/EDX Size/disp32 . # copy *size to EDX 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 2/r32/EDX Size/disp32 . # copy *Size to EDX
# syscall # . syscall
b8/copy-to-EAX 4/imm32/write b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8

View File

@ -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 # 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 # it for reading, read a character from it, close it, delete it, and return
# the character read. # the character read.
@ -32,20 +33,20 @@
89/copy 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to *EBX 89/copy 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to *EBX
# syscall(write, Stream, "a", 1) # syscall(write, Stream, "a", 1)
# load stream # . load stream
bb/copy-to-EBX Stream/imm32 bb/copy-to-EBX Stream/imm32
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX 8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
# # .
b9/copy-to-ECX A/imm32 b9/copy-to-ECX A/imm32
ba/copy-to-EDX 1/imm32/size ba/copy-to-EDX 1/imm32/size
b8/copy-to-EAX 4/imm32/write b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# syscall(close, Stream) # syscall(close, Stream)
# load stream # . load stream
bb/copy-to-EBX Stream/imm32 bb/copy-to-EBX Stream/imm32
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX 8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
# # .
b8/copy-to-EAX 6/imm32/close b8/copy-to-EAX 6/imm32/close
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
@ -55,22 +56,22 @@
ba/copy-to-EDX 0x180/imm32/fixed-perms ba/copy-to-EDX 0x180/imm32/fixed-perms
b8/copy-to-EAX 5/imm32/open b8/copy-to-EAX 5/imm32/open
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# save Stream # . save Stream
bb/copy-to-EBX Stream/imm32 bb/copy-to-EBX Stream/imm32
89/copy 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to *EBX 89/copy 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to *EBX
# syscall(read, Stream, B, 1) # syscall(read, Stream, B, 1)
# load stream # . load stream
bb/copy-to-EBX Stream/imm32 bb/copy-to-EBX Stream/imm32
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX 8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
# # .
b9/copy-to-ECX B/imm32 b9/copy-to-ECX B/imm32
ba/copy-to-EDX 1/imm32/size ba/copy-to-EDX 1/imm32/size
b8/copy-to-EAX 3/imm32/read b8/copy-to-EAX 3/imm32/read
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# syscall(close, Stream) # syscall(close, Stream)
# load stream # . load stream
bb/copy-to-EBX Stream/imm32 bb/copy-to-EBX Stream/imm32
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX 8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
# #
@ -83,7 +84,7 @@
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# syscall(exit, b) # syscall(exit, b)
# load b # . load b
bb/copy-to-EBX B/imm32 bb/copy-to-EBX B/imm32
8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX 8b/copy 0/mod/indirect 3/rm32/EBX . . . 3/r32/EBX . . # copy *EBX to EBX
# #

View File

@ -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): # To run (from the subx directory):
# $ subx translate examples/ex8.subx -o examples/ex8 # $ subx translate examples/ex8.subx -o examples/ex8
@ -21,7 +21,7 @@
# . prolog # . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 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 # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# . . call # . . call
@ -34,13 +34,13 @@
b8/copy-to-EAX 1/imm32/exit b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
ascii-length: # (s) ascii-length: # s : (address array byte) -> n/EAX
# initialize s (EDX) # 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 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 b8/copy-to-EAX 0/imm32
$ascii-length-loop: $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 8a/copy 0/mod/* 2/rm32/EDX . . . 1/r32/ECX . . # copy byte at *EDX to lower byte of ECX
# if c == '\0' break # if c == '\0' break
81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX
@ -52,7 +52,7 @@ $ascii-length-loop:
# loop # loop
eb/jump $ascii-length-loop/disp8 eb/jump $ascii-length-loop/disp8
$ascii-length-ret: $ascii-length-ret:
# return (result in EAX) # return EAX
c3/return c3/return
# . . vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

@ -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 # Show difference between ascii codes of first letter of first arg and first
# letter of second arg. # letter of second arg.
# #
@ -23,16 +24,16 @@
# . prolog # . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# . . call ascii-difference(argv[1], argv[2]) # ascii-difference(argv[1], argv[2])
# push 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) 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) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# . . call # . . call
e8/call ascii-difference/disp32 e8/call ascii-difference/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 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 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
b8/copy-to-EAX 1/imm32/exit b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8