4802
Some automated commenting cleanup. Still needs more careful manual scanning. sed -i 's/^# 1-3/# . 1-3/' *.subx */*.subx sed -i 's/^# op/# . op/' *.subx */*.subx sed -i 's/# vim/# . . vim/' *.subx */*.subx sed -i 's/^ # push args/ # . . push args/' *.subx */*.subx sed -i 's/^ # discard args/ # . . discard args/' *.subx */*.subx sed -i 's/^ # call/ # . . call/' *.subx */*.subx sed -i 's/^ # prolog/ # . prolog/' *.subx */*.subx sed -i 's/^ # epilog/ # . epilog/' *.subx */*.subx sed -i 's/^ # save registers/ # . save registers/' *.subx */*.subx sed -i 's/^ # restore registers/ # . restore registers/' *.subx */*.subx sed -i 's/ operand / register /' *.subx */*.subx
This commit is contained in:
parent
6030d7e2e5
commit
ee9a9237d6
|
@ -1,9 +1,9 @@
|
||||||
# _write: write to a file descriptor
|
# _write: write to a file descriptor
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# main:
|
# main:
|
||||||
# syscall(exit, 0) -- can't test _write just yet
|
# syscall(exit, 0) -- can't test _write just yet
|
||||||
|
@ -12,34 +12,34 @@
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
_write: # fd : int, s : (address array byte) -> <void>
|
_write: # fd : int, s : (address array byte) -> <void>
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
# syscall(write, fd, (data) s+4, (size) *s)
|
# syscall(write, fd, (data) s+4, (size) *s)
|
||||||
# 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+4
|
# . data : ECX = s+4
|
||||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0xc/disp8 . # copy *(EBP+12) to ECX
|
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0xc/disp8 . # copy *(EBP+12) 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 : EDX = *s
|
# . size : EDX = *s
|
||||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX
|
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) 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
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# Rudimentary test harness
|
# Rudimentary test harness
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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)
|
||||||
|
@ -19,10 +19,10 @@
|
||||||
|
|
||||||
# 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
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
# load first 2 args into EAX and EBX
|
# load first 2 args into EAX and EBX
|
||||||
|
@ -32,41 +32,41 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
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:
|
# else:
|
||||||
$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
|
||||||
68/push 2/imm32/stderr
|
68/push 2/imm32/stderr
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# increment Num-test-failures
|
# increment Num-test-failures
|
||||||
ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures
|
ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures
|
||||||
$check-ints-equal:end:
|
$check-ints-equal:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
# 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
|
||||||
|
@ -82,4 +82,4 @@ Newline:
|
||||||
Num-test-failures:
|
Num-test-failures:
|
||||||
00 00 00 00
|
00 00 00 00
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
# would cause tests to not run, rather than to fail as we'd like.)
|
# would cause tests to not run, rather than to fail as we'd like.)
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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-'.
|
||||||
|
@ -29,10 +29,10 @@
|
||||||
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
||||||
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
|
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
|
||||||
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
|
@ -98,13 +98,13 @@ $kernel-string-equal:false:
|
||||||
b8/copy-to-EAX 0/imm32
|
b8/copy-to-EAX 0/imm32
|
||||||
|
|
||||||
$kernel-string-equal:end:
|
$kernel-string-equal:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
# 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
|
||||||
|
@ -113,141 +113,141 @@ $kernel-string-equal:end:
|
||||||
|
|
||||||
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, "")
|
||||||
# push args
|
# . . push args
|
||||||
68/push ""/imm32
|
68/push ""/imm32
|
||||||
68/push Null-kernel-string/imm32
|
68/push Null-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-null-kernel-string-with-non-empty-array:
|
test-compare-null-kernel-string-with-non-empty-array:
|
||||||
# EAX = kernel-string-equal(Null-kernel-string, "Abc")
|
# EAX = kernel-string-equal(Null-kernel-string, "Abc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Abc"/imm32
|
68/push "Abc"/imm32
|
||||||
68/push Null-kernel-string/imm32
|
68/push Null-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-equal-array:
|
test-compare-kernel-string-with-equal-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
|
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Abc"/imm32
|
68/push "Abc"/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-inequal-array:
|
test-compare-kernel-string-with-inequal-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
|
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Adc"/imm32
|
68/push "Adc"/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-empty-array:
|
test-compare-kernel-string-with-empty-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "")
|
# EAX = kernel-string-equal(Abc-kernel-string, "")
|
||||||
# push args
|
# . . push args
|
||||||
68/push ""/imm32
|
68/push ""/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-shorter-array:
|
test-compare-kernel-string-with-shorter-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
|
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Ab"/imm32
|
68/push "Ab"/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-longer-array:
|
test-compare-kernel-string-with-longer-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
|
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Abcd"/imm32
|
68/push "Abcd"/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
|
@ -258,4 +258,4 @@ Null-kernel-string:
|
||||||
Abc-kernel-string:
|
Abc-kernel-string:
|
||||||
41/A 62/b 63/c 00/null
|
41/A 62/b 63/c 00/null
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
# Create a new segment (for data) using mmap().
|
# Create a new segment (for data) using mmap().
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# main: (manual test if this is the last file loaded)
|
# main: (manual test if this is the last file loaded)
|
||||||
# EAX = new-segment(0x1000)
|
# EAX = new-segment(0x1000)
|
||||||
# push args
|
# . . push args
|
||||||
68/push 0x1000/imm32
|
68/push 0x1000/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call new-segment/disp32
|
e8/call new-segment/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
|
||||||
|
|
||||||
# store to *EAX
|
# store to *EAX
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
new-segment: # len : int -> address
|
new-segment: # len : int -> address
|
||||||
# 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
|
||||||
|
@ -36,7 +36,7 @@ new-segment: # len : int -> address
|
||||||
bb/copy-to-EBX mmap-new-segment/imm32
|
bb/copy-to-EBX mmap-new-segment/imm32
|
||||||
b8/copy-to-EAX 0x5a/imm32/mmap
|
b8/copy-to-EAX 0x5a/imm32/mmap
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
# epilog
|
# . epilog
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
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
|
||||||
|
@ -59,4 +59,4 @@ mmap-new-segment: # type mmap_arg_struct
|
||||||
# offset
|
# offset
|
||||||
00 00 00 00 # 0 since MAP_ANONYMOUS is specified
|
00 00 00 00 # 0 since MAP_ANONYMOUS is specified
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# Comparing 'regular' length-prefixed strings.
|
# Comparing 'regular' length-prefixed strings.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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-'.
|
||||||
|
@ -13,10 +13,10 @@
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
string-equal: # s : string, benchmark : string -> EAX : boolean
|
string-equal: # s : string, benchmark : string -> EAX : boolean
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
|
@ -74,12 +74,12 @@ $string-equal:false:
|
||||||
# return false
|
# return false
|
||||||
b8/copy-to-EAX 0/imm32
|
b8/copy-to-EAX 0/imm32
|
||||||
$string-equal:end:
|
$string-equal:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
# 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
|
||||||
|
@ -88,82 +88,82 @@ $string-equal:end:
|
||||||
|
|
||||||
test-compare-empty-with-empty-string:
|
test-compare-empty-with-empty-string:
|
||||||
# EAX = string-equal("", "")
|
# EAX = string-equal("", "")
|
||||||
# push args
|
# . . push args
|
||||||
68/push ""/imm32
|
68/push ""/imm32
|
||||||
68/push ""/imm32
|
68/push ""/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-empty-with-non-empty-string: # also checks length-mismatch code path
|
test-compare-empty-with-non-empty-string: # also checks length-mismatch code path
|
||||||
# EAX = string-equal("", "Abc")
|
# EAX = string-equal("", "Abc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Abc"/imm32
|
68/push "Abc"/imm32
|
||||||
68/push ""/imm32
|
68/push ""/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-equal-strings:
|
test-compare-equal-strings:
|
||||||
# EAX = string-equal("Abc", "Abc")
|
# EAX = string-equal("Abc", "Abc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Abc"/imm32
|
68/push "Abc"/imm32
|
||||||
68/push "Abc"/imm32
|
68/push "Abc"/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-inequal-strings-equal-lengths:
|
test-compare-inequal-strings-equal-lengths:
|
||||||
# EAX = string-equal("Abc", "Adc")
|
# EAX = string-equal("Abc", "Adc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Adc"/imm32
|
68/push "Adc"/imm32
|
||||||
68/push "Abc"/imm32
|
68/push "Abc"/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -38,9 +38,9 @@ _test-trace-stream:
|
||||||
00 00 00 00 00 00 00 00 # 8 bytes
|
00 00 00 00 00 00 00 00 # 8 bytes
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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-'.
|
||||||
|
@ -53,11 +53,11 @@ _test-trace-stream:
|
||||||
# The Trace-stream segment will consist of variable-length lines separated by newlines (0x0a)
|
# The Trace-stream segment will consist of variable-length lines separated by newlines (0x0a)
|
||||||
initialize-trace-stream:
|
initialize-trace-stream:
|
||||||
# EAX = new-segment(0x1000)
|
# EAX = new-segment(0x1000)
|
||||||
# push args
|
# . . push args
|
||||||
68/push 0x1000/imm32/N
|
68/push 0x1000/imm32/N
|
||||||
# call
|
# . . call
|
||||||
e8/call new-segment/disp32
|
e8/call new-segment/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
|
||||||
# copy EAX to *Trace-stream
|
# copy EAX to *Trace-stream
|
||||||
89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Trace-stream/disp32 # copy EAX to *Trace-stream
|
89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Trace-stream/disp32 # copy EAX to *Trace-stream
|
||||||
|
@ -68,10 +68,10 @@ initialize-trace-stream:
|
||||||
# Append a string to the given trace stream.
|
# Append a string to the given trace stream.
|
||||||
# Silently give up if it's already full. Or truncate the string if there isn't enough room.
|
# Silently give up if it's already full. Or truncate the string if there isn't enough room.
|
||||||
trace: # t : (address trace-stream), line : string
|
trace: # t : (address trace-stream), line : string
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
|
@ -95,9 +95,9 @@ trace: # t : (address trace-stream), line : string
|
||||||
# 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
|
||||||
e8/call _append-3/disp32
|
e8/call _append-3/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
|
||||||
# if EAX == 0 return
|
# if EAX == 0 return
|
||||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EDX
|
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EDX
|
||||||
|
@ -115,30 +115,30 @@ trace: # t : (address trace-stream), line : string
|
||||||
# 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
|
||||||
e8/call _append-3/disp32
|
e8/call _append-3/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
|
||||||
# t->write += EAX
|
# t->write += EAX
|
||||||
01/add 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to *EDI
|
01/add 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to *EDI
|
||||||
$trace:end:
|
$trace:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
|
||||||
clear-trace-stream: # t : (address trace-stream)
|
clear-trace-stream: # t : (address trace-stream)
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
# EAX = t
|
# EAX = t
|
||||||
|
@ -164,10 +164,10 @@ $clear-trace-stream:loop:
|
||||||
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX
|
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX
|
||||||
eb/jump $clear-trace-stream:loop/disp8
|
eb/jump $clear-trace-stream:loop/disp8
|
||||||
$clear-trace-stream:end:
|
$clear-trace-stream:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
@ -176,98 +176,98 @@ $clear-trace-stream:end:
|
||||||
|
|
||||||
test-trace-single:
|
test-trace-single:
|
||||||
# clear-trace-stream(_test-trace-stream)
|
# clear-trace-stream(_test-trace-stream)
|
||||||
# push args
|
# . . push args
|
||||||
68/push _test-trace-stream/imm32
|
68/push _test-trace-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call clear-trace-stream/disp32
|
e8/call clear-trace-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
|
||||||
# trace(_test-trace-stream, "Ab")
|
# trace(_test-trace-stream, "Ab")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Ab"/imm32
|
68/push "Ab"/imm32
|
||||||
68/push _test-trace-stream/imm32
|
68/push _test-trace-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call trace/disp32
|
e8/call trace/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-ints-equal(*_test-trace-stream.data, 41/A 62/b 0a/newline 00, msg)
|
# check-ints-equal(*_test-trace-stream.data, 41/A 62/b 0a/newline 00, msg)
|
||||||
# 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
|
||||||
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-trace-appends:
|
test-trace-appends:
|
||||||
# clear-trace-stream(_test-trace-stream)
|
# clear-trace-stream(_test-trace-stream)
|
||||||
# push args
|
# . . push args
|
||||||
68/push _test-trace-stream/imm32
|
68/push _test-trace-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call clear-trace-stream/disp32
|
e8/call clear-trace-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
|
||||||
# trace(_test-trace-stream, "C")
|
# trace(_test-trace-stream, "C")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "C"/imm32
|
68/push "C"/imm32
|
||||||
68/push _test-trace-stream/imm32
|
68/push _test-trace-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call trace/disp32
|
e8/call trace/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
|
||||||
# trace(_test-trace-stream, "D")
|
# trace(_test-trace-stream, "D")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "D"/imm32
|
68/push "D"/imm32
|
||||||
68/push _test-trace-stream/imm32
|
68/push _test-trace-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call trace/disp32
|
e8/call trace/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-ints-equal(*_test-trace-stream.data, 43/C 0a/newline 44/D 0a/newline, msg)
|
# check-ints-equal(*_test-trace-stream.data, 43/C 0a/newline 44/D 0a/newline, msg)
|
||||||
# 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
|
||||||
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-trace-empty-line:
|
test-trace-empty-line:
|
||||||
# clear-trace-stream(_test-trace-stream)
|
# clear-trace-stream(_test-trace-stream)
|
||||||
# push args
|
# . . push args
|
||||||
68/push _test-trace-stream/imm32
|
68/push _test-trace-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call clear-trace-stream/disp32
|
e8/call clear-trace-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
|
||||||
# trace(_test-trace-stream, "")
|
# trace(_test-trace-stream, "")
|
||||||
# push args
|
# . . push args
|
||||||
68/push ""/imm32
|
68/push ""/imm32
|
||||||
68/push _test-trace-stream/imm32
|
68/push _test-trace-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call trace/disp32
|
e8/call trace/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-ints-equal(*_test-trace-stream.data, 0, msg)
|
# check-ints-equal(*_test-trace-stream.data, 0, msg)
|
||||||
# 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
|
||||||
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
|
||||||
|
@ -276,10 +276,10 @@ test-trace-empty-line:
|
||||||
|
|
||||||
# 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
|
||||||
# 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
|
||||||
# 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]
|
||||||
|
@ -297,23 +297,23 @@ _append-3: # out : address, outend : address, s : (array byte) -> num_bytes_app
|
||||||
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
|
||||||
# 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
|
||||||
# restore registers
|
# . restore registers
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
# 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
|
||||||
|
|
||||||
# 4-argument variant of _append
|
# 4-argument variant of _append
|
||||||
_append-4: # out : address, outend : address, in : address, inend : address -> num_bytes_appended/EAX
|
_append-4: # out : address, outend : address, in : address, inend : address -> num_bytes_appended/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
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
|
@ -345,15 +345,15 @@ $_append-4:loop:
|
||||||
47/increment-EDI
|
47/increment-EDI
|
||||||
eb/jump $_append-4:loop/disp8
|
eb/jump $_append-4:loop/disp8
|
||||||
$_append-4:end:
|
$_append-4:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
# 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
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
# data: (array byte) # prefixed by length as usual
|
# data: (array byte) # prefixed by length as usual
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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-'.
|
||||||
|
@ -31,23 +31,23 @@ write: # f : fd or (address stream), s : (address array byte) -> bytes_written/
|
||||||
# (If we ever leave the Linux kernel behind, it may be better to return
|
# (If we ever leave the Linux kernel behind, it may be better to return
|
||||||
# the number of bytes *not* written. Success would then be signaled by
|
# the number of bytes *not* written. Success would then be signaled by
|
||||||
# returning 0.)
|
# returning 0.)
|
||||||
# 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) _write(f, s), return # f can't be a user-mode address, so treat it as a kernel file descriptor
|
# if (f < 0x08000000) _write(f, s), return # 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 $write:fake/disp8
|
7d/jump-if-greater-or-equal $write:fake/disp8
|
||||||
# push args
|
# . . push args
|
||||||
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)
|
||||||
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 _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
|
||||||
eb/jump $write:end/disp8
|
eb/jump $write:end/disp8
|
||||||
$write:fake:
|
$write:fake:
|
||||||
# otherwise, treat 'f' as a stream to append to
|
# otherwise, treat 'f' as a stream to append to
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
|
@ -66,27 +66,27 @@ $write:fake:
|
||||||
# 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
|
||||||
e8/call _append-3/disp32
|
e8/call _append-3/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
|
||||||
# f->write += EAX
|
# f->write += EAX
|
||||||
01/add 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # add EAX to *ECX
|
01/add 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # add EAX to *ECX
|
||||||
# restore registers
|
# . restore registers
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
$write:end:
|
$write:end:
|
||||||
# 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
|
||||||
|
|
||||||
clear-stream: # f : (address stream) -> <void>
|
clear-stream: # f : (address stream) -> <void>
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
# EAX = f
|
# EAX = f
|
||||||
|
@ -112,87 +112,87 @@ $clear-stream:loop:
|
||||||
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX
|
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX
|
||||||
eb/jump $clear-stream:loop/disp8
|
eb/jump $clear-stream:loop/disp8
|
||||||
$clear-stream:end:
|
$clear-stream:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
|
||||||
test-write-single:
|
test-write-single:
|
||||||
# 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
|
||||||
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# check-ints-equal(EAX, 2)
|
# check-ints-equal(EAX, 2)
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-read-single: return EAX"/imm32
|
68/push "F - test-read-single: return EAX"/imm32
|
||||||
68/push 2/imm32
|
68/push 2/imm32
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# check-ints-equal(*_test-stream->data, 41/A 62/b 00 00, msg)
|
# check-ints-equal(*_test-stream->data, 41/A 62/b 00 00, msg)
|
||||||
# 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
|
||||||
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-appends:
|
test-write-appends:
|
||||||
# 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
|
||||||
# write(_test-stream, "C")
|
# write(_test-stream, "C")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "C"/imm32
|
68/push "C"/imm32
|
||||||
68/push _test-stream/imm32
|
68/push _test-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
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(_test-stream, "D")
|
# write(_test-stream, "D")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "D"/imm32
|
68/push "D"/imm32
|
||||||
68/push _test-stream/imm32
|
68/push _test-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# check-ints-equal(*_test-stream->data, 43/C 44/D 00 00, msg)
|
# check-ints-equal(*_test-stream->data, 43/C 44/D 00 00, msg)
|
||||||
# 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
|
||||||
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
|
||||||
|
@ -209,4 +209,4 @@ _test-stream:
|
||||||
# data
|
# data
|
||||||
00 00 00 00 00 00 00 00 # 8 bytes
|
00 00 00 00 00 00 00 00 # 8 bytes
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -33,9 +33,9 @@
|
||||||
# Its value is its output, computed during stop and available to the test.
|
# Its value is its output, computed during stop and available to the test.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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-'.
|
||||||
|
@ -49,10 +49,10 @@
|
||||||
# the stack.
|
# the stack.
|
||||||
# Ugly that we need to know the size of args, but so it goes.
|
# Ugly that we need to know the size of args, but so it goes.
|
||||||
tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void>
|
tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void>
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
# EAX = nbytes
|
# EAX = nbytes
|
||||||
|
@ -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.
|
||||||
#
|
#
|
||||||
|
@ -87,10 +87,10 @@ tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void
|
||||||
89/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to *ECX
|
89/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to *ECX
|
||||||
# initialize ed->value
|
# initialize ed->value
|
||||||
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # copy to *(ECX+4)
|
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # copy to *(ECX+4)
|
||||||
# restore registers
|
# . restore registers
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
@ -132,78 +132,78 @@ test-stop-skips-returns-on-exit:
|
||||||
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 precisely for the next call below, to _test-stop-1.
|
# Size the exit-descriptor precisely for the next call below, to _test-stop-1.
|
||||||
# tailor-exit-descriptor(ed, 4)
|
# tailor-exit-descriptor(ed, 4)
|
||||||
# push args
|
# . . push args
|
||||||
68/push 4/imm32/nbytes-of-args-for-_test-stop-1
|
68/push 4/imm32/nbytes-of-args-for-_test-stop-1
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call _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)
|
||||||
# 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-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
|
||||||
# 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
|
||||||
# epilog
|
# . epilog
|
||||||
5d/pop-to-EBP
|
5d/pop-to-EBP
|
||||||
# don't restore ESP from EBP; manually reclaim locals
|
# don't restore ESP from EBP; manually 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
_test-stop-1: # ed : (address exit-descriptor)
|
_test-stop-1: # 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
|
||||||
# _test-stop-2(ed)
|
# _test-stop-2(ed)
|
||||||
# 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
|
||||||
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)
|
||||||
# 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 0/imm32
|
68/push 0/imm32
|
||||||
68/push 1/imm32
|
68/push 1/imm32
|
||||||
# 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
|
||||||
# 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
|
||||||
|
|
||||||
_test-stop-2: # ed : (address exit-descriptor)
|
_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)
|
# . . call 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -41,9 +41,9 @@
|
||||||
# data: (array byte) # prefixed by length as usual
|
# data: (array byte) # prefixed by length as usual
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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-'.
|
||||||
|
@ -53,24 +53,24 @@
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/EAX
|
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
|
||||||
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)
|
||||||
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 _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
|
||||||
# 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
|
||||||
# ESI = f
|
# ESI = f
|
||||||
|
@ -95,19 +95,19 @@ $read:fake:
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
e8/call _append-4/disp32
|
e8/call _append-4/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
|
||||||
# s->write += EAX
|
# s->write += EAX
|
||||||
01/add 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to *EDI
|
01/add 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to *EDI
|
||||||
# f.read += EAX
|
# f.read += EAX
|
||||||
01/add 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # add EAX to *(ESI+4)
|
01/add 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # add EAX to *(ESI+4)
|
||||||
# restore registers
|
# . restore registers
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
$read:end:
|
$read:end:
|
||||||
# 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
|
||||||
|
@ -119,10 +119,10 @@ $read:end:
|
||||||
# Maybe a better helper would be 'empty-stream?'
|
# Maybe a better helper would be 'empty-stream?'
|
||||||
|
|
||||||
_read: # fd : int, s : (address stream) -> num-bytes-read/EAX
|
_read: # fd : int, 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
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
|
@ -145,12 +145,12 @@ _read: # fd : int, s : (address stream) -> num-bytes-read/EAX
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
# add the result EAX to s->write
|
# add the result EAX to s->write
|
||||||
01/add 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # add EAX to *ESI
|
01/add 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # add EAX to *ESI
|
||||||
# restore registers
|
# . restore registers
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
# 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
|
||||||
|
@ -180,54 +180,54 @@ _read: # fd : int, s : (address stream) -> num-bytes-read/EAX
|
||||||
|
|
||||||
test-read-single:
|
test-read-single:
|
||||||
# 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-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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# check-ints-equal(EAX, 2)
|
# check-ints-equal(EAX, 2)
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-read-single: return EAX"/imm32
|
68/push "F - test-read-single: return EAX"/imm32
|
||||||
68/push 2/imm32
|
68/push 2/imm32
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# check-ints-equal(*_test-stream-buffer->data, 41/A 62/b 00 00, msg)
|
# check-ints-equal(*_test-stream-buffer->data, 41/A 62/b 00 00, msg)
|
||||||
# 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
|
||||||
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
|
||||||
|
@ -235,61 +235,61 @@ test-read-single:
|
||||||
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
|
||||||
# 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, "C")
|
# write(_test-stream, "C")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "C"/imm32
|
68/push "C"/imm32
|
||||||
68/push _test-stream/imm32
|
68/push _test-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# write(_test-stream, "D")
|
# write(_test-stream, "D")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "D"/imm32
|
68/push "D"/imm32
|
||||||
68/push _test-stream/imm32
|
68/push _test-stream/imm32
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# check-ints-equal(*_test-stream-buffer->data, 43/C 44/D 00 00, msg)
|
# check-ints-equal(*_test-stream-buffer->data, 43/C 44/D 00 00, msg)
|
||||||
# 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
|
||||||
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
|
||||||
|
@ -297,53 +297,53 @@ test-read-is-stateful:
|
||||||
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)
|
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# check-ints-equal(EAX, 0)
|
# check-ints-equal(EAX, 0)
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-read-returns-0-on-end-of-file"/imm32
|
68/push "F - test-read-returns-0-on-end-of-file"/imm32
|
||||||
68/push 0/imm32
|
68/push 0/imm32
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# end
|
# end
|
||||||
c3/return
|
c3/return
|
||||||
|
@ -360,4 +360,4 @@ _test-stream-buffer:
|
||||||
# data
|
# data
|
||||||
00 00 00 00 00 00 00 00 # 8 bytes
|
00 00 00 00 00 00 00 00 # 8 bytes
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -27,9 +27,9 @@ Stdin:
|
||||||
# TODO: 8 bytes is too small. We'll need to grow the buffer for efficiency.
|
# TODO: 8 bytes is too small. We'll need to grow the buffer for efficiency.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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-'.
|
||||||
|
@ -42,10 +42,10 @@ Stdin:
|
||||||
# return next byte value in EAX, with top 3 bytes cleared.
|
# return next byte value in EAX, with top 3 bytes cleared.
|
||||||
# On EOF, return 0xffffffff.
|
# On EOF, return 0xffffffff.
|
||||||
read-byte: # f : (address buffered-file) -> byte/EAX
|
read-byte: # f : (address buffered-file) -> byte/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
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
56/push-ESI
|
56/push-ESI
|
||||||
# ESI = f
|
# ESI = f
|
||||||
|
@ -56,20 +56,20 @@ read-byte: # f : (address buffered-file) -> byte/EAX
|
||||||
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)
|
# 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
|
||||||
# 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
|
||||||
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# if EAX = 0 return 0xffffffff
|
# if EAX = 0 return 0xffffffff
|
||||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
|
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
|
||||||
|
@ -83,10 +83,10 @@ $read-byte:from-stream:
|
||||||
# ++f->read
|
# ++f->read
|
||||||
ff 0/subop/increment 1/mod/*+disp8 6/rm32/ESI . . . . 8/disp8 . # increment *(ESI+8)
|
ff 0/subop/increment 1/mod/*+disp8 6/rm32/ESI . . . . 8/disp8 . # increment *(ESI+8)
|
||||||
$read-byte:end:
|
$read-byte:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
# 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
|
||||||
|
@ -99,44 +99,44 @@ $read-byte:end:
|
||||||
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)
|
# 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# read-byte(_test-buffered-file)
|
# read-byte(_test-buffered-file)
|
||||||
# push args
|
# . . push args
|
||||||
68/push _test-buffered-file/imm32
|
68/push _test-buffered-file/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call read-byte/disp32
|
e8/call read-byte/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
|
||||||
# check-ints-equal(EAX, 'A')
|
# check-ints-equal(EAX, 'A')
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-read-byte-single"/imm32
|
68/push "F - test-read-byte-single"/imm32
|
||||||
68/push 0x41/imm32
|
68/push 0x41/imm32
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# end
|
# end
|
||||||
c3/return
|
c3/return
|
||||||
|
@ -144,51 +144,51 @@ test-read-byte-single:
|
||||||
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)
|
# 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# read-byte(_test-buffered-file)
|
# read-byte(_test-buffered-file)
|
||||||
# push args
|
# . . push args
|
||||||
68/push _test-buffered-file/imm32
|
68/push _test-buffered-file/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call read-byte/disp32
|
e8/call read-byte/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
|
||||||
# read-byte(_test-buffered-file)
|
# read-byte(_test-buffered-file)
|
||||||
# push args
|
# . . push args
|
||||||
68/push _test-buffered-file/imm32
|
68/push _test-buffered-file/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call read-byte/disp32
|
e8/call read-byte/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
|
||||||
# check-ints-equal(EAX, 'b')
|
# check-ints-equal(EAX, 'b')
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-read-byte-multiple"/imm32
|
68/push "F - test-read-byte-multiple"/imm32
|
||||||
68/push 0x62/imm32
|
68/push 0x62/imm32
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# end
|
# end
|
||||||
c3/return
|
c3/return
|
||||||
|
@ -196,36 +196,36 @@ test-read-byte-multiple:
|
||||||
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)
|
# 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# read-byte(_test-buffered-file)
|
# read-byte(_test-buffered-file)
|
||||||
# push args
|
# . . push args
|
||||||
68/push _test-buffered-file/imm32
|
68/push _test-buffered-file/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call read-byte/disp32
|
e8/call read-byte/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
|
||||||
# check-ints-equal(EAX, -1)
|
# check-ints-equal(EAX, -1)
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-read-byte-end-of-file"/imm32
|
68/push "F - test-read-byte-end-of-file"/imm32
|
||||||
68/push -1/imm32
|
68/push -1/imm32
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# end
|
# end
|
||||||
c3/return
|
c3/return
|
||||||
|
@ -244,4 +244,4 @@ _test-buffered-file:
|
||||||
# data
|
# data
|
||||||
00 00 00 00 00 00 00 00 # 8 bytes
|
00 00 00 00 00 00 00 00 # 8 bytes
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# write-stream: like write, but write streams rather than strings
|
# write-stream: like write, but write streams rather than strings
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# main:
|
# main:
|
||||||
# manual test
|
# manual test
|
||||||
|
@ -20,23 +20,23 @@
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
write-stream: # f : fd or (address stream), s : (address stream) -> <void>
|
write-stream: # f : fd or (address stream), s : (address stream) -> <void>
|
||||||
# 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) _write-stream(f, s), return # f can't be a user-mode address, so treat it as a kernel file descriptor
|
# if (f < 0x08000000) _write-stream(f, s), return # 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 $write-stream:fake/disp8
|
7d/jump-if-greater-or-equal $write-stream:fake/disp8
|
||||||
# push args
|
# . . push args
|
||||||
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)
|
||||||
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 _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
|
||||||
eb/jump $write-stream:end/disp8
|
eb/jump $write-stream:end/disp8
|
||||||
$write-stream:fake:
|
$write-stream:fake:
|
||||||
# otherwise, treat 'f' as a stream to append to
|
# otherwise, treat 'f' as a stream to append to
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
56/push-ESI
|
56/push-ESI
|
||||||
57/push-EDI
|
57/push-EDI
|
||||||
|
@ -61,29 +61,29 @@ $write-stream:fake:
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
e8/call _append-4/disp32
|
e8/call _append-4/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
|
||||||
# f->write += EAX
|
# f->write += EAX
|
||||||
01/add 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # add EAX to *ESI
|
01/add 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # add EAX to *ESI
|
||||||
# s->read += EAX
|
# s->read += EAX
|
||||||
01/add 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # add EAX to *(EDI+4)
|
01/add 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # add EAX to *(EDI+4)
|
||||||
# restore registers
|
# . restore registers
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
$write-stream:end:
|
$write-stream:end:
|
||||||
# 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
|
||||||
|
|
||||||
_write-stream: # fd : int, s : (address stream) -> <void>
|
_write-stream: # fd : int, s : (address stream) -> <void>
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
|
@ -106,120 +106,120 @@ _write-stream: # fd : int, s : (address stream) -> <void>
|
||||||
# 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
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
|
||||||
test-write-stream-single:
|
test-write-stream-single:
|
||||||
# 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-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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# check-ints-equal(*_test-stream.data, 41/A 62/b 00 00, msg)
|
# check-ints-equal(*_test-stream.data, 41/A 62/b 00 00, msg)
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-write-stream-single"/imm32
|
68/push "F - test-write-stream-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
|
||||||
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)
|
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
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")
|
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# check-ints-equal(*_test-stream.data, 43/C 44/D 00 00, msg)
|
# check-ints-equal(*_test-stream.data, 43/C 44/D 00 00, msg)
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-write-stream-appends"/imm32
|
68/push "F - test-write-stream-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
|
||||||
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
|
||||||
|
@ -236,4 +236,4 @@ _test-stream2:
|
||||||
# data
|
# data
|
||||||
41 42 43 44 00 00 00 00 # 8 bytes
|
41 42 43 44 00 00 00 00 # 8 bytes
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -26,12 +26,12 @@
|
||||||
# naming conventions.
|
# naming conventions.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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)
|
||||||
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
|
||||||
|
@ -77,10 +77,10 @@ $main:end:
|
||||||
|
|
||||||
# the main entry point
|
# the main entry point
|
||||||
compile: # in : fd or (address stream), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
|
compile: # in : fd or (address stream), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
# Look = get-char(in)
|
# Look = get-char(in)
|
||||||
|
@ -179,10 +179,10 @@ 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
|
||||||
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
|
||||||
|
@ -211,7 +211,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
||||||
# get-char in each iteration of the loop. (Thereby demonstrating that it's
|
# get-char in each iteration of the loop. (Thereby demonstrating that it's
|
||||||
# not the right interface for us. But we'll keep it just to follow Crenshaw.)
|
# not the right interface for us. But we'll keep it just to follow Crenshaw.)
|
||||||
#
|
#
|
||||||
# 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)
|
# EAX = is-digit?(Look)
|
||||||
|
@ -225,16 +225,16 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
||||||
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)
|
||||||
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)
|
||||||
# call
|
# . . call
|
||||||
e8/call expected/disp32 # never returns
|
e8/call expected/disp32 # never returns
|
||||||
# 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:
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
|
@ -254,13 +254,13 @@ $get-num:main:
|
||||||
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, "get-num: too many digits in number") # 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)
|
||||||
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)
|
||||||
# . call
|
# . call
|
||||||
e8/call error/disp32 # never returns
|
e8/call error/disp32 # never returns
|
||||||
# . 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:stage2:
|
$get-num:stage2:
|
||||||
# out->data[out->write] = LSB(Look)
|
# out->data[out->write] = LSB(Look)
|
||||||
|
@ -279,14 +279,14 @@ $get-num:stage2:
|
||||||
$get-num:loop-end:
|
$get-num:loop-end:
|
||||||
# persist necessary variables from registers
|
# persist necessary variables from registers
|
||||||
89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI
|
89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI
|
||||||
# restore registers
|
# . restore registers
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
@ -475,7 +475,7 @@ test-get-num-aborts-on-non-digit-in-Look:
|
||||||
|
|
||||||
# write(f, "Error: "+s+" expected\n") then stop(ed, 1)
|
# write(f, "Error: "+s+" expected\n") then stop(ed, 1)
|
||||||
expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
|
expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
|
||||||
# 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
|
||||||
# write(f, "Error: ")
|
# write(f, "Error: ")
|
||||||
|
@ -517,14 +517,14 @@ expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (ad
|
||||||
# . 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
|
||||||
|
|
||||||
# write(f, "Error: "+s+"\n") then stop(ed, 1)
|
# write(f, "Error: "+s+"\n") then stop(ed, 1)
|
||||||
error: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
|
error: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
|
||||||
# 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
|
||||||
# write(f, "Error: ")
|
# write(f, "Error: ")
|
||||||
|
@ -558,17 +558,17 @@ error: # ed : (address exit-descriptor), f : fd or (address stream), s : (addre
|
||||||
# . 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 store 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
|
||||||
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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# read-byte(f)
|
# read-byte(f)
|
||||||
# . push args
|
# . push args
|
||||||
|
@ -579,15 +579,15 @@ get-char: # f : (address buffered-file) -> <void>
|
||||||
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
|
||||||
# save EAX to Look
|
# save EAX to Look
|
||||||
89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look
|
89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look
|
||||||
# restore registers
|
# . restore registers
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
|
||||||
is-digit?: # c : int -> bool/EAX
|
is-digit?: # c : int -> bool/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
|
||||||
# EAX = false
|
# EAX = false
|
||||||
|
@ -601,7 +601,7 @@ is-digit?: # c : int -> bool/EAX
|
||||||
# otherwise return true
|
# otherwise return true
|
||||||
b8/copy-to-EAX 1/imm32
|
b8/copy-to-EAX 1/imm32
|
||||||
$is-digit?:end:
|
$is-digit?:end:
|
||||||
# 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
|
||||||
|
@ -631,4 +631,4 @@ _test-error-stream:
|
||||||
# data
|
# data
|
||||||
00 00 00 00 00 00 00 00 # 8 bytes
|
00 00 00 00 00 00 00 00 # 8 bytes
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -26,23 +26,23 @@
|
||||||
# naming conventions.
|
# naming conventions.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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)
|
||||||
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")
|
# and if (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)
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
|
@ -60,14 +60,14 @@ $run-main:
|
||||||
# clear ed->target (so we really exit)
|
# clear ed->target (so we really exit)
|
||||||
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)
|
# 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
|
||||||
68/push 1/imm32/stdout
|
68/push 1/imm32/stdout
|
||||||
68/push Stdin/imm32
|
68/push Stdin/imm32
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
|
@ -77,18 +77,18 @@ $main:end:
|
||||||
|
|
||||||
# the main entry point
|
# the main entry point
|
||||||
compile: # in : fd or (address stream), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
|
compile: # in : fd or (address stream), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
|
||||||
# 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
|
||||||
# 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
|
||||||
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
|
||||||
# var num/ECX : (address stream) on the stack
|
# var num/ECX : (address stream) on the stack
|
||||||
# Numbers can be 32 bits or 8 hex bytes long. One of them will be in 'Look', so we need space for 7 bytes.
|
# Numbers can be 32 bits or 8 hex bytes long. One of them will be in 'Look', so we need space for 7 bytes.
|
||||||
|
@ -99,90 +99,90 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
|
||||||
# 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)
|
# 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)
|
||||||
51/push-ECX/num
|
51/push-ECX/num
|
||||||
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 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")
|
# EAX = 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
|
||||||
# call
|
# . . call
|
||||||
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, "bb/copy-to-EBX ")
|
# 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)
|
||||||
# call
|
# . . call
|
||||||
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)
|
||||||
# call
|
# . . call
|
||||||
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)
|
||||||
# call
|
# . . call
|
||||||
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")
|
# EAX = 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)
|
||||||
# call
|
# . . call
|
||||||
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)
|
# EAX = 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)
|
||||||
# call
|
# . . call
|
||||||
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")
|
# EAX = 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)
|
||||||
# call
|
# . . call
|
||||||
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)
|
# EAX = 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)
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
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
|
||||||
|
@ -216,30 +216,30 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
||||||
# get-char in each iteration of the loop. (Thereby demonstrating that it's
|
# get-char in each iteration of the loop. (Thereby demonstrating that it's
|
||||||
# not the right interface for us. But we'll keep it just to follow Crenshaw.)
|
# not the right interface for us. But we'll keep it just to follow Crenshaw.)
|
||||||
#
|
#
|
||||||
# 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)
|
# 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 error
|
||||||
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)
|
||||||
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)
|
||||||
# call
|
# . . call
|
||||||
e8/call expected/disp32 # never returns
|
e8/call expected/disp32 # never returns
|
||||||
# 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:
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
|
@ -260,13 +260,13 @@ $get-num:loop:
|
||||||
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, "get-num: too many digits in number") # 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)
|
||||||
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)
|
||||||
# call
|
# . . call
|
||||||
e8/call error/disp32 # never returns
|
e8/call error/disp32 # never returns
|
||||||
# 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:loop-stage2:
|
$get-num:loop-stage2:
|
||||||
# out->data[out->write] = LSB(Look)
|
# out->data[out->write] = LSB(Look)
|
||||||
|
@ -276,18 +276,18 @@ $get-num:loop-stage2:
|
||||||
# ++out->write
|
# ++out->write
|
||||||
41/increment-ECX
|
41/increment-ECX
|
||||||
# Look = get-char(in)
|
# Look = get-char(in)
|
||||||
# push args
|
# . . push args
|
||||||
56/push-ESI
|
56/push-ESI
|
||||||
# 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
|
||||||
# EAX = is-digit?(Look)
|
# 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
|
||||||
|
@ -295,14 +295,14 @@ $get-num:loop-stage2:
|
||||||
$get-num:loop-end:
|
$get-num:loop-end:
|
||||||
# persist necessary variables from registers
|
# persist necessary variables from registers
|
||||||
89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI
|
89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI
|
||||||
# restore registers
|
# . restore registers
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
@ -314,43 +314,43 @@ test-get-num-reads-single-digit:
|
||||||
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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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-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
|
||||||
# call
|
# . . call
|
||||||
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'
|
||||||
# allocate on stack
|
# allocate on stack
|
||||||
|
@ -359,41 +359,41 @@ test-get-num-reads-single-digit:
|
||||||
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
|
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
68/push _test-output-stream/imm32
|
68/push _test-output-stream/imm32
|
||||||
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')
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-get-num-reads-single-digit"/imm32
|
68/push "F - test-get-num-reads-single-digit"/imm32
|
||||||
68/push 0x33/imm32
|
68/push 0x33/imm32
|
||||||
b8/copy-to-EAX _test-output-stream/imm32
|
b8/copy-to-EAX _test-output-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
|
||||||
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
|
||||||
|
@ -407,43 +407,43 @@ test-get-num-aborts-on-non-digit-in-Look:
|
||||||
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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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-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
|
||||||
# call
|
# . . call
|
||||||
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'
|
||||||
# allocate on stack
|
# allocate on stack
|
||||||
|
@ -452,35 +452,35 @@ test-get-num-aborts-on-non-digit-in-Look:
|
||||||
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
|
# 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
|
||||||
# call
|
# . . call
|
||||||
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 initialize Look
|
||||||
## 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
|
||||||
68/push _test-output-stream/imm32
|
68/push _test-output-stream/imm32
|
||||||
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
|
||||||
|
@ -494,43 +494,43 @@ test-get-num-reads-multiple-digits:
|
||||||
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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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-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
|
||||||
# call
|
# . . call
|
||||||
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'
|
||||||
# allocate on stack
|
# allocate on stack
|
||||||
|
@ -539,41 +539,41 @@ test-get-num-reads-multiple-digits:
|
||||||
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
|
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
68/push _test-output-stream/imm32
|
68/push _test-output-stream/imm32
|
||||||
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')
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-get-num-reads-multiple-digits"/imm32
|
68/push "F - test-get-num-reads-multiple-digits"/imm32
|
||||||
68/push 0x36353433/imm32
|
68/push 0x36353433/imm32
|
||||||
b8/copy-to-EAX _test-output-stream/imm32
|
b8/copy-to-EAX _test-output-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
|
||||||
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
|
||||||
|
@ -587,43 +587,43 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
|
||||||
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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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-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
|
||||||
# call
|
# . . call
|
||||||
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'
|
||||||
# allocate on stack
|
# allocate on stack
|
||||||
|
@ -632,41 +632,41 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
|
||||||
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
|
# 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
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
68/push _test-output-stream/imm32
|
68/push _test-output-stream/imm32
|
||||||
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')
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32
|
68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32
|
||||||
68/push 0x36353433/imm32
|
68/push 0x36353433/imm32
|
||||||
b8/copy-to-EAX _test-output-stream/imm32
|
b8/copy-to-EAX _test-output-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
|
||||||
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
|
||||||
|
@ -677,119 +677,119 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
|
||||||
|
|
||||||
# write(f, "Error: "+s+" expected\n") then stop(ed, 1)
|
# write(f, "Error: "+s+" expected\n") then stop(ed, 1)
|
||||||
expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
|
expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
|
||||||
# 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
|
||||||
# write(f, "Error: ")
|
# write(f, "Error: ")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Error: "/imm32
|
68/push "Error: "/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)
|
||||||
# call
|
# . . call
|
||||||
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(f, s)
|
# write(f, s)
|
||||||
# push args
|
# . . push args
|
||||||
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)
|
||||||
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)
|
||||||
# call
|
# . . call
|
||||||
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(f, " expected")
|
# write(f, " expected")
|
||||||
# push args
|
# . . push args
|
||||||
68/push " expected"/imm32
|
68/push " expected"/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)
|
||||||
# call
|
# . . call
|
||||||
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(f, Newline)
|
# write(f, 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)
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
# write(f, "Error: "+s+"\n") then stop(ed, 1)
|
# write(f, "Error: "+s+"\n") then stop(ed, 1)
|
||||||
error: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
|
error: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
|
||||||
# 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
|
||||||
# write(f, "Error: ")
|
# write(f, "Error: ")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Error: "/imm32
|
68/push "Error: "/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)
|
||||||
# call
|
# . . call
|
||||||
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(f, s)
|
# write(f, s)
|
||||||
# push args
|
# . . push args
|
||||||
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)
|
||||||
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)
|
||||||
# call
|
# . . call
|
||||||
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(f, Newline)
|
# write(f, 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)
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
# read a byte from 'f', and store it in 'Look'
|
# read a byte from 'f', and store 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
|
||||||
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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# read-byte(f)
|
# read-byte(f)
|
||||||
# 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
|
||||||
e8/call read-byte/disp32
|
e8/call read-byte/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
|
||||||
# save EAX to Look
|
# save EAX to Look
|
||||||
89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look
|
89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look
|
||||||
# restore registers
|
# . restore registers
|
||||||
58/pop-to-EAX
|
58/pop-to-EAX
|
||||||
# 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
|
||||||
|
|
||||||
is-digit?: # c : int -> bool/EAX
|
is-digit?: # c : int -> bool/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
|
||||||
# EAX = false
|
# EAX = false
|
||||||
|
@ -803,7 +803,7 @@ is-digit?: # c : int -> bool/EAX
|
||||||
# otherwise return true
|
# otherwise return true
|
||||||
b8/copy-to-EAX 1/imm32
|
b8/copy-to-EAX 1/imm32
|
||||||
$is-digit?:end:
|
$is-digit?:end:
|
||||||
# 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
|
||||||
|
@ -833,4 +833,4 @@ _test-error-stream:
|
||||||
# data
|
# data
|
||||||
00 00 00 00 00 00 00 00 # 8 bytes
|
00 00 00 00 00 00 00 00 # 8 bytes
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -15,23 +15,23 @@
|
||||||
# When running tests the exit status doesn't mean anything. Yet.
|
# When running tests the exit status doesn't mean anything. Yet.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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)
|
||||||
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")
|
# and if (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)
|
||||||
# call
|
# . . call
|
||||||
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
|
||||||
|
@ -42,11 +42,11 @@
|
||||||
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)
|
# else EAX = factorial(5)
|
||||||
$run-main:
|
$run-main:
|
||||||
# push args
|
# . . push args
|
||||||
68/push 5/imm32
|
68/push 5/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call factorial/disp32
|
e8/call factorial/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
|
||||||
$main:end:
|
$main:end:
|
||||||
# exit(EAX)
|
# exit(EAX)
|
||||||
|
@ -56,7 +56,7 @@ $main:end:
|
||||||
|
|
||||||
# factorial(n)
|
# factorial(n)
|
||||||
factorial:
|
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
|
||||||
|
@ -69,17 +69,17 @@ factorial:
|
||||||
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
|
||||||
81 5/subop/subtract 3/mod/direct 3/rm32/EBX . . . . . 1/imm32 # subtract from EBX
|
81 5/subop/subtract 3/mod/direct 3/rm32/EBX . . . . . 1/imm32 # subtract from EBX
|
||||||
# EAX = factorial(n-1)
|
# EAX = factorial(n-1)
|
||||||
# push args
|
# . . push args
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
# call
|
# . . call
|
||||||
e8/call factorial/disp32
|
e8/call factorial/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 n * factorial(n-1)
|
# return n * factorial(n-1)
|
||||||
f7 4/subop/multiply 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none 8/disp8 . # multiply *(EBP+8) into EAX
|
f7 4/subop/multiply 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none 8/disp8 . # multiply *(EBP+8) into EAX
|
||||||
# TODO: check for overflow
|
# TODO: check for overflow
|
||||||
$factorial:end:
|
$factorial:end:
|
||||||
# epilog
|
# . epilog
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
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
|
||||||
|
@ -87,22 +87,22 @@ $factorial:end:
|
||||||
|
|
||||||
test-factorial:
|
test-factorial:
|
||||||
# factorial(5)
|
# factorial(5)
|
||||||
# push args
|
# . . push args
|
||||||
68/push 5/imm32
|
68/push 5/imm32
|
||||||
# call
|
# . . call
|
||||||
e8/call factorial/disp32
|
e8/call factorial/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
|
||||||
# check-ints-equal(EAX, 120, failure message)
|
# check-ints-equal(EAX, 120, failure message)
|
||||||
# push args
|
# . . push args
|
||||||
68/push "F - test-factorial"/imm32
|
68/push "F - test-factorial"/imm32
|
||||||
68/push 0x78/imm32/expected-120
|
68/push 0x78/imm32/expected-120
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
# end
|
# end
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -15,4 +15,4 @@ bb/copy-to-EBX 2a/imm32 # 42 in hex
|
||||||
b8/copy-to-EAX 1/imm32/exit
|
b8/copy-to-EAX 1/imm32/exit
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
# 0 # false
|
# 0 # false
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# main: return argv-equal(argv[1], argv[2])
|
# main: return argv-equal(argv[1], argv[2])
|
||||||
# At the start of a SubX program:
|
# At the start of a SubX program:
|
||||||
|
@ -18,14 +18,14 @@
|
||||||
# argv[0]: *(ESP+4)
|
# argv[0]: *(ESP+4)
|
||||||
# argv[1]: *(ESP+8)
|
# argv[1]: *(ESP+8)
|
||||||
# ...
|
# ...
|
||||||
# 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])
|
# . . call 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)
|
# exit(EAX)
|
||||||
$exit:
|
$exit:
|
||||||
|
@ -69,4 +69,4 @@ $argv-equal:false:
|
||||||
b8/copy-to-EAX 0/imm32
|
b8/copy-to-EAX 0/imm32
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
# would cause tests to not run, rather than to fail as we'd like.)
|
# would cause tests to not run, rather than to fail as we'd like.)
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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-'.
|
||||||
|
@ -29,10 +29,10 @@
|
||||||
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
||||||
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
|
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
|
||||||
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
|
@ -97,7 +97,7 @@ $kernel-string-equal:false:
|
||||||
b8/copy-to-EAX 0/imm32
|
b8/copy-to-EAX 0/imm32
|
||||||
|
|
||||||
$kernel-string-equal:end:
|
$kernel-string-equal:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
5f/pop-to-EDI
|
5f/pop-to-EDI
|
||||||
5e/pop-to-ESI
|
5e/pop-to-ESI
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
|
@ -112,141 +112,141 @@ $kernel-string-equal:end:
|
||||||
|
|
||||||
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, "")
|
||||||
# push args
|
# . . push args
|
||||||
68/push ""/imm32
|
68/push ""/imm32
|
||||||
68/push Null-kernel-string/imm32
|
68/push Null-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-null-kernel-string-with-non-empty-array:
|
test-compare-null-kernel-string-with-non-empty-array:
|
||||||
# EAX = kernel-string-equal(Null-kernel-string, "Abc")
|
# EAX = kernel-string-equal(Null-kernel-string, "Abc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Abc"/imm32
|
68/push "Abc"/imm32
|
||||||
68/push Null-kernel-string/imm32
|
68/push Null-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-equal-array:
|
test-compare-kernel-string-with-equal-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
|
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Abc"/imm32
|
68/push "Abc"/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-inequal-array:
|
test-compare-kernel-string-with-inequal-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
|
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Adc"/imm32
|
68/push "Adc"/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-empty-array:
|
test-compare-kernel-string-with-empty-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "")
|
# EAX = kernel-string-equal(Abc-kernel-string, "")
|
||||||
# push args
|
# . . push args
|
||||||
68/push ""/imm32
|
68/push ""/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-shorter-array:
|
test-compare-kernel-string-with-shorter-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
|
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Ab"/imm32
|
68/push "Ab"/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
test-compare-kernel-string-with-longer-array:
|
test-compare-kernel-string-with-longer-array:
|
||||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
|
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
|
||||||
# push args
|
# . . push args
|
||||||
68/push "Abcd"/imm32
|
68/push "Abcd"/imm32
|
||||||
68/push Abc-kernel-string/imm32
|
68/push Abc-kernel-string/imm32
|
||||||
# call
|
# . . call
|
||||||
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)
|
# . . call 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
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
# 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
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
|
@ -254,10 +254,10 @@ test-compare-kernel-string-with-longer-array:
|
||||||
|
|
||||||
# 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
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
53/push-EBX
|
53/push-EBX
|
||||||
# load args into EAX, EBX and ECX
|
# load args into EAX, EBX and ECX
|
||||||
|
@ -267,11 +267,11 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
||||||
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('.')
|
# print('.')
|
||||||
# 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
|
||||||
|
@ -280,21 +280,21 @@ $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
|
||||||
# print(ECX)
|
# print(ECX)
|
||||||
# push args
|
# . . push args
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
# 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
|
||||||
# print newline
|
# print newline
|
||||||
# push args
|
# . . push args
|
||||||
68/push Newline/imm32
|
68/push Newline/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
|
||||||
$check-ints-equal:end:
|
$check-ints-equal:end:
|
||||||
# restore registers
|
# . restore registers
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
# end
|
# end
|
||||||
|
@ -303,10 +303,10 @@ $check-ints-equal:end:
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
write-stderr: # s : (address array byte) -> <void>
|
write-stderr: # s : (address array byte) -> <void>
|
||||||
# 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
|
||||||
# save registers
|
# . save registers
|
||||||
50/push-EAX
|
50/push-EAX
|
||||||
51/push-ECX
|
51/push-ECX
|
||||||
52/push-EDX
|
52/push-EDX
|
||||||
|
@ -323,7 +323,7 @@ write-stderr: # s : (address array byte) -> <void>
|
||||||
# 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
|
||||||
5b/pop-to-EBX
|
5b/pop-to-EBX
|
||||||
5a/pop-to-EDX
|
5a/pop-to-EDX
|
||||||
59/pop-to-ECX
|
59/pop-to-ECX
|
||||||
|
@ -347,4 +347,4 @@ Null-kernel-string:
|
||||||
Abc-kernel-string:
|
Abc-kernel-string:
|
||||||
41/A 62/b 63/c 00/null
|
41/A 62/b 63/c 00/null
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
# You shouldn't get a segmentation fault.
|
# You shouldn't get a segmentation fault.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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(mmap, 0x1000)
|
# syscall(mmap, 0x1000)
|
||||||
bb/copy-to-EBX Mmap-new-segment/imm32
|
bb/copy-to-EBX Mmap-new-segment/imm32
|
||||||
|
@ -41,4 +41,4 @@ Mmap-new-segment: # type mmap_arg_struct
|
||||||
# offset
|
# offset
|
||||||
00 00 00 00 # 0 since MAP_ANONYMOUS is specified
|
00 00 00 00 # 0 since MAP_ANONYMOUS is specified
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -15,4 +15,4 @@ bb/copy-to-EBX 1/imm32
|
||||||
b8/copy-to-EAX 1/imm32
|
b8/copy-to-EAX 1/imm32
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
# 55
|
# 55
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# result: EBX = 0
|
# result: EBX = 0
|
||||||
bb/copy-to-EBX 0/imm32
|
bb/copy-to-EBX 0/imm32
|
||||||
|
@ -33,4 +33,4 @@ $exit:
|
||||||
b8/copy-to-EAX 1/imm32
|
b8/copy-to-EAX 1/imm32
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -37,4 +37,4 @@ cd/syscall 0x80/imm8
|
||||||
X:
|
X:
|
||||||
00 00 00 00 # space for read() to write to
|
00 00 00 00 # space for read() to write to
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
# $ subx run examples/ex5
|
# $ subx run examples/ex5
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# main:
|
# main:
|
||||||
# allocate x on the stack
|
# allocate x on the stack
|
||||||
|
@ -39,4 +39,4 @@
|
||||||
b8/copy-to-EAX 1/imm32/exit
|
b8/copy-to-EAX 1/imm32/exit
|
||||||
cd/syscall 0x80/imm8
|
cd/syscall 0x80/imm8
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
# Hello, world!
|
# Hello, world!
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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)
|
||||||
|
@ -33,4 +33,4 @@ X: # string to print
|
||||||
48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a 00
|
48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a 00
|
||||||
# H e l l o , ␣ w o r l d ! newline null
|
# H e l l o , ␣ w o r l d ! newline null
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
# 97
|
# 97
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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(creat, Filename)
|
# syscall(creat, Filename)
|
||||||
bb/copy-to-EBX Filename/imm32
|
bb/copy-to-EBX Filename/imm32
|
||||||
|
@ -101,4 +101,4 @@ B:
|
||||||
Filename:
|
Filename:
|
||||||
2e 66 6f 6f 00 00 00 00
|
2e 66 6f 6f 00 00 00 00
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -15,18 +15,18 @@
|
||||||
# Locals start from ESP-4 downwards.
|
# Locals start from ESP-4 downwards.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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])
|
# . . call 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
|
||||||
e8/call ascii-length/disp32
|
e8/call ascii-length/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
|
||||||
|
|
||||||
# exit(EAX)
|
# exit(EAX)
|
||||||
|
@ -55,4 +55,4 @@ $ascii-length-ret:
|
||||||
# return (result in EAX)
|
# return (result in EAX)
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
|
@ -17,20 +17,20 @@
|
||||||
# Locals start from ESP-4 downwards.
|
# Locals start from ESP-4 downwards.
|
||||||
|
|
||||||
== code
|
== code
|
||||||
# instruction effective address operand displacement immediate
|
# instruction effective address register displacement immediate
|
||||||
# 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
|
||||||
|
|
||||||
# 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])
|
# . . call 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)
|
# 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
|
||||||
|
@ -48,4 +48,4 @@ ascii-difference: # (s1, s2) : null-terminated ascii strings
|
||||||
29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX
|
29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
# vim:nowrap:textwidth=0
|
# . . vim:nowrap:textwidth=0
|
||||||
|
|
Loading…
Reference in New Issue