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:
Kartik Agaram 2018-11-30 11:10:44 -08:00
parent 6030d7e2e5
commit ee9a9237d6
26 changed files with 828 additions and 828 deletions

View File

@ -1,9 +1,9 @@
# _write: write to a file descriptor
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
# syscall(exit, 0) -- can't test _write just yet
@ -12,34 +12,34 @@
cd/syscall 0x80/imm8
_write: # fd : int, s : (address array byte) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
52/push-EDX
53/push-EBX
# 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
# 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
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 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX
# syscall
# . syscall
b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8
# restore registers
# . restore registers
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -1,9 +1,9 @@
# Rudimentary test harness
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main: (manual test if this is the last file loaded)
# check-ints-equal(34, 34)
@ -19,10 +19,10 @@
# print msg to stderr if a != b, otherwise print "."
check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
53/push-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
75/jump-if-unequal $check-ints-equal:else/disp8
# _write(2/stderr, '.')
# push args
# . . push args
68/push "."/imm32
68/push 2/imm32/stderr
# call
# . . call
e8/call _write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# return
eb/jump $check-ints-equal:end/disp8
# else:
$check-ints-equal:else:
# _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
51/push-ECX
68/push 2/imm32/stderr
# call
# . . call
e8/call _write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# _write(2/stderr, Newline)
# push args
# . . push args
68/push Newline/imm32
68/push 2/imm32/stderr
# call
# . . call
e8/call _write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# 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:
# restore registers
# . restore registers
5b/pop-to-EBX
59/pop-to-ECX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -82,4 +82,4 @@ Newline:
Num-test-failures:
00 00 00 00
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -15,9 +15,9 @@
# would cause tests to not run, rather than to fail as we'd like.)
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
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
# 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
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
52/push-EDX
53/push-EBX
@ -98,13 +98,13 @@ $kernel-string-equal:false:
b8/copy-to-EAX 0/imm32
$kernel-string-equal:end:
# restore registers
# . restore registers
5f/pop-to-EDI
5e/pop-to-ESI
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -113,141 +113,141 @@ $kernel-string-equal:end:
test-compare-null-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "")
# push args
# . . push args
68/push ""/imm32
68/push Null-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 1, msg)
# push args
# . . call check-ints-equal(EAX, 1, msg)
# . . push args
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
68/push 1/imm32/true
50/push-EAX
# call
# . . call
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
c3/return
test-compare-null-kernel-string-with-non-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "Abc")
# push args
# . . push args
68/push "Abc"/imm32
68/push Null-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0, msg)
# push args
# . . call check-ints-equal(EAX, 0, msg)
# . . push args
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-equal-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
# push args
# . . push args
68/push "Abc"/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 1, msg)
# push args
# . . call check-ints-equal(EAX, 1, msg)
# . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 1/imm32/true
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-inequal-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
# push args
# . . push args
68/push "Adc"/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0, msg)
# push args
# . . call check-ints-equal(EAX, 0, msg)
# . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Abc-kernel-string, "")
# push args
# . . push args
68/push ""/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0)
# push args
# . . call check-ints-equal(EAX, 0)
# . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-shorter-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0)
# push args
# . . call check-ints-equal(EAX, 0)
# . . push args
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-longer-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
# push args
# . . push args
68/push "Abcd"/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0)
# push args
# . . call check-ints-equal(EAX, 0)
# . . push args
68/push "F - test-compare-kernel-string-with-longer-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
@ -258,4 +258,4 @@ Null-kernel-string:
Abc-kernel-string:
41/A 62/b 63/c 00/null
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -1,17 +1,17 @@
# Create a new segment (for data) using mmap().
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main: (manual test if this is the last file loaded)
# EAX = new-segment(0x1000)
# push args
# . . push args
68/push 0x1000/imm32
# call
# . . call
e8/call new-segment/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# store to *EAX
@ -23,7 +23,7 @@
cd/syscall 0x80/imm8
new-segment: # len : int -> address
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
53/push-EBX
@ -36,7 +36,7 @@ new-segment: # len : int -> address
bb/copy-to-EBX mmap-new-segment/imm32
b8/copy-to-EAX 0x5a/imm32/mmap
cd/syscall 0x80/imm8
# epilog
# . epilog
5b/pop-to-EBX
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
@ -59,4 +59,4 @@ mmap-new-segment: # type mmap_arg_struct
# offset
00 00 00 00 # 0 since MAP_ANONYMOUS is specified
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -1,9 +1,9 @@
# Comparing 'regular' length-prefixed strings.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
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
string-equal: # s : string, benchmark : string -> EAX : boolean
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
52/push-EDX
53/push-EBX
@ -74,12 +74,12 @@ $string-equal:false:
# return false
b8/copy-to-EAX 0/imm32
$string-equal:end:
# restore registers
# . restore registers
5e/pop-to-ESI
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -88,82 +88,82 @@ $string-equal:end:
test-compare-empty-with-empty-string:
# EAX = string-equal("", "")
# push args
# . . push args
68/push ""/imm32
68/push ""/imm32
# call
# . . call
e8/call string-equal/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 1, msg)
# push args
# . . call check-ints-equal(EAX, 1, msg)
# . . push args
68/push "F - test-compare-empty-with-empty-string"/imm32
68/push 1/imm32/true
50/push-EAX
# call
# . . call
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
c3/return
test-compare-empty-with-non-empty-string: # also checks length-mismatch code path
# EAX = string-equal("", "Abc")
# push args
# . . push args
68/push "Abc"/imm32
68/push ""/imm32
# call
# . . call
e8/call string-equal/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0, msg)
# push args
# . . call check-ints-equal(EAX, 0, msg)
# . . push args
68/push "F - test-compare-empty-with-non-empty-string"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-equal-strings:
# EAX = string-equal("Abc", "Abc")
# push args
# . . push args
68/push "Abc"/imm32
68/push "Abc"/imm32
# call
# . . call
e8/call string-equal/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 1, msg)
# push args
# . . call check-ints-equal(EAX, 1, msg)
# . . push args
68/push "F - test-compare-equal-strings"/imm32
68/push 1/imm32/true
50/push-EAX
# call
# . . call
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
c3/return
test-compare-inequal-strings-equal-lengths:
# EAX = string-equal("Abc", "Adc")
# push args
# . . push args
68/push "Adc"/imm32
68/push "Abc"/imm32
# call
# . . call
e8/call string-equal/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0, msg)
# push args
# . . call check-ints-equal(EAX, 0, msg)
# . . push args
68/push "F - test-compare-inequal-strings-equal-lengths"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -38,9 +38,9 @@ _test-trace-stream:
00 00 00 00 00 00 00 00 # 8 bytes
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
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)
initialize-trace-stream:
# EAX = new-segment(0x1000)
# push args
# . . push args
68/push 0x1000/imm32/N
# call
# . . call
e8/call new-segment/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# 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.
# 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
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
52/push-EDX
@ -95,9 +95,9 @@ trace: # t : (address trace-stream), line : string
# push &t->data[t->write]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX
53/push-EBX
# call
# . . call
e8/call _append-3/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# if EAX == 0 return
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]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX
53/push-EBX
# call
# . . call
e8/call _append-3/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# t->write += EAX
01/add 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to *EDI
$trace:end:
# restore registers
# . restore registers
5f/pop-to-EDI
5e/pop-to-ESI
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
clear-trace-stream: # t : (address trace-stream)
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
# 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
eb/jump $clear-trace-stream:loop/disp8
$clear-trace-stream:end:
# restore registers
# . restore registers
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -176,98 +176,98 @@ $clear-trace-stream:end:
test-trace-single:
# clear-trace-stream(_test-trace-stream)
# push args
# . . push args
68/push _test-trace-stream/imm32
# call
# . . call
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
# trace(_test-trace-stream, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push _test-trace-stream/imm32
# call
# . . call
e8/call trace/disp32
# discard args
# . . discard args
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)
# push args
# . . push args
68/push "F - test-trace-single"/imm32
68/push 0x0a6241/imm32/Ab-newline
# push *_test-trace-stream.data
b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
test-trace-appends:
# clear-trace-stream(_test-trace-stream)
# push args
# . . push args
68/push _test-trace-stream/imm32
# call
# . . call
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
# trace(_test-trace-stream, "C")
# push args
# . . push args
68/push "C"/imm32
68/push _test-trace-stream/imm32
# call
# . . call
e8/call trace/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# trace(_test-trace-stream, "D")
# push args
# . . push args
68/push "D"/imm32
68/push _test-trace-stream/imm32
# call
# . . call
e8/call trace/disp32
# discard args
# . . discard args
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)
# push args
# . . push args
68/push "F - test-trace-appends"/imm32
68/push 0x0a440a43/imm32/C-newline-D-newline
# push *_test-trace-stream.data
b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
test-trace-empty-line:
# clear-trace-stream(_test-trace-stream)
# push args
# . . push args
68/push _test-trace-stream/imm32
# call
# . . call
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
# trace(_test-trace-stream, "")
# push args
# . . push args
68/push ""/imm32
68/push _test-trace-stream/imm32
# call
# . . call
e8/call trace/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(*_test-trace-stream.data, 0, msg)
# push args
# . . push args
68/push "F - test-trace-empty-line"/imm32
68/push 0/imm32
# push *_test-trace-stream.data
b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
@ -276,10 +276,10 @@ test-trace-empty-line:
# 3-argument variant of _append
_append-3: # out : address, outend : address, s : (array byte) -> num_bytes_appended/EAX
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
# _append-4(out, outend, &s.data[0], &s.data[s.length]) -> num_bytes_appended/EAX
# push &s.data[s.length]
@ -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)
# push out
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
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# restore registers
# . restore registers
59/pop-to-ECX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# 4-argument variant of _append
_append-4: # out : address, outend : address, in : address, inend : address -> num_bytes_appended/EAX
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
52/push-EDX
53/push-EBX
@ -345,15 +345,15 @@ $_append-4:loop:
47/increment-EDI
eb/jump $_append-4:loop/disp8
$_append-4:end:
# restore registers
# . restore registers
5f/pop-to-EDI
5e/pop-to-ESI
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -16,9 +16,9 @@
# data: (array byte) # prefixed by length as usual
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
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
# the number of bytes *not* written. Success would then be signaled by
# returning 0.)
# prolog
# . prolog
55/push-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
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
# 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 . . 8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call _write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
eb/jump $write:end/disp8
$write:fake:
# otherwise, treat 'f' as a stream to append to
# save registers
# . save registers
51/push-ECX
52/push-EDX
53/push-EBX
@ -66,27 +66,27 @@ $write:fake:
# push &f->data[f->write]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 2/index/EDX . 3/r32/EBX 0xc/disp8 . # copy ECX+EDX+12 to EBX
53/push-EBX
# call
# . . call
e8/call _append-3/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# f->write += EAX
01/add 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # add EAX to *ECX
# restore registers
# . restore registers
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
$write:end:
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
clear-stream: # f : (address stream) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
# EAX = f
@ -112,87 +112,87 @@ $clear-stream:loop:
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX
eb/jump $clear-stream:loop/disp8
$clear-stream:end:
# restore registers
# . restore registers
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-write-single:
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(EAX, 2)
# push args
# . . push args
68/push "F - test-read-single: return EAX"/imm32
68/push 2/imm32
50/push-EAX
# call
# . . call
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
# 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 0x006241/imm32/Ab
# push *_test-stream->data
b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
test-write-appends:
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "C")
# push args
# . . push args
68/push "C"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(_test-stream, "D")
# push args
# . . push args
68/push "D"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
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)
# push args
# . . push args
68/push "F - test-write-appends"/imm32
68/push 0x00004443/imm32/C-D
# push *_test-stream->data
b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
@ -209,4 +209,4 @@ _test-stream:
# data
00 00 00 00 00 00 00 00 # 8 bytes
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -33,9 +33,9 @@
# Its value is its output, computed during stop and available to the test.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
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.
# Ugly that we need to know the size of args, but so it goes.
tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
# 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
#
# However, we also need to account for the perturbance to ESP caused by the
# call to tailor-exit-descriptor. It pushes 8 bytes of args followed by 4
# . . call to tailor-exit-descriptor. It pushes 8 bytes of args followed by 4
# bytes for the return address and 4 bytes to push EBP above.
# So EBP at this point is X-16.
#
@ -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
# initialize ed->value
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # copy to *(ECX+4)
# restore registers
# . restore registers
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
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
# Size the exit-descriptor precisely for the next call below, to _test-stop-1.
# tailor-exit-descriptor(ed, 4)
# push args
# . . push args
68/push 4/imm32/nbytes-of-args-for-_test-stop-1
50/push-EAX
# call
# . . call
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
# call _test-stop-1(ed)
# push args
# . . call _test-stop-1(ed)
# . . push args
50/push-EAX
# call
# . . call
e8/call _test-stop-1/disp32
## registers except ESP may be clobbered at this point
# restore args
58/pop-to-EAX
# check that _test-stop-1 tried to call exit(1)
# 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 2/imm32
# push ed->value
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# call
# . . call
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
# epilog
# . epilog
5d/pop-to-EBP
# don't restore ESP from EBP; manually reclaim locals
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
c3/return
_test-stop-1: # ed : (address exit-descriptor)
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# _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)
# call
# . . call
e8/call _test-stop-2/disp32
## 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
# 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 0/imm32
68/push 1/imm32
# call
# . . call
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
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
_test-stop-2: # ed : (address exit-descriptor)
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# call stop(ed, 1)
# push args
# . . call stop(ed, 1)
# . . push args
68/push 1/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call stop/disp32
## should never get past this point
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -41,9 +41,9 @@
# data: (array byte) # prefixed by length as usual
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
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
read: # f : fd or (address stream), s : (address stream) -> num-bytes-read/EAX
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## if (f < 0x08000000) return _read(f, s) # f can't be a user-mode address, so treat it as a kernel file descriptor
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 0x08000000/imm32 # compare *(EBP+8)
7d/jump-if-greater-or-equal $read:fake/disp8
# push args
# . . 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 . . 8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call _read/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# return
eb/jump $read:end/disp8
$read:fake:
## otherwise, treat 'f' as a stream to scan from
# save registers
# . save registers
56/push-ESI
57/push-EDI
# ESI = f
@ -95,19 +95,19 @@ $read:fake:
8b/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy *EDI to EAX
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy EDI+EAX+12 to EAX
50/push-EAX
# call
# . . call
e8/call _append-4/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# s->write += EAX
01/add 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to *EDI
# f.read += EAX
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
5e/pop-to-ESI
$read:end:
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -119,10 +119,10 @@ $read:end:
# Maybe a better helper would be 'empty-stream?'
_read: # fd : int, s : (address stream) -> num-bytes-read/EAX
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
52/push-EDX
53/push-EBX
@ -145,12 +145,12 @@ _read: # fd : int, s : (address stream) -> num-bytes-read/EAX
cd/syscall 0x80/imm8
# add the result EAX to s->write
01/add 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # add EAX to *ESI
# restore registers
# . restore registers
5e/pop-to-ESI
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -180,54 +180,54 @@ _read: # fd : int, s : (address stream) -> num-bytes-read/EAX
test-read-single:
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-stream-buffer)
# push args
# . . push args
68/push _test-stream-buffer/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# read(_test-stream, _test-stream-buffer)
# push args
# . . push args
68/push _test-stream-buffer/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call read/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(EAX, 2)
# push args
# . . push args
68/push "F - test-read-single: return EAX"/imm32
68/push 2/imm32
50/push-EAX
# call
# . . call
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
# 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 0x006241/imm32/Ab
# push *_test-stream-buffer->data
b8/copy-to-EAX _test-stream-buffer/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
@ -235,61 +235,61 @@ test-read-single:
test-read-is-stateful:
## make two consecutive reads, check that their results are appended
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-stream-buffer)
# push args
# . . push args
68/push _test-stream-buffer/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "C")
# push args
# . . push args
68/push "C"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# read(_test-stream, _test-stream-buffer)
# push args
# . . push args
68/push _test-stream-buffer/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call read/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(_test-stream, "D")
# push args
# . . push args
68/push "D"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# read(_test-stream, _test-stream-buffer)
# push args
# . . push args
68/push _test-stream-buffer/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call read/disp32
# discard args
# . . discard args
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)
# push args
# . . push args
68/push "F - test-read-is-stateful"/imm32
68/push 0x00004443/imm32/C-D
# push *_test-stream-buffer->data
b8/copy-to-EAX _test-stream-buffer/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
@ -297,53 +297,53 @@ test-read-is-stateful:
test-read-returns-0-on-end-of-file:
## read after hitting end-of-file, check that result is 0
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-stream-buffer)
# push args
# . . push args
68/push _test-stream-buffer/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## first read gets to end-of-file
# read(_test-stream, _test-stream-buffer)
# push args
# . . push args
68/push _test-stream-buffer/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call read/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## second read
# read(_test-stream, _test-stream-buffer)
# push args
# . . push args
68/push _test-stream-buffer/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call read/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(EAX, 0)
# push args
# . . push args
68/push "F - test-read-returns-0-on-end-of-file"/imm32
68/push 0/imm32
50/push-EAX
# call
# . . call
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
# end
c3/return
@ -360,4 +360,4 @@ _test-stream-buffer:
# data
00 00 00 00 00 00 00 00 # 8 bytes
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -27,9 +27,9 @@ Stdin:
# TODO: 8 bytes is too small. We'll need to grow the buffer for efficiency.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
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.
# On EOF, return 0xffffffff.
read-byte: # f : (address buffered-file) -> byte/EAX
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
56/push-ESI
# 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)
7c/jump-if-lesser $read-byte:from-stream/disp8
# 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
50/push-EAX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# EAX = read(f->fd, stream = f+4)
# push args
# . . push args
50/push-EAX
ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI
# call
# . . call
e8/call read/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# if EAX = 0 return 0xffffffff
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
@ -83,10 +83,10 @@ $read-byte:from-stream:
# ++f->read
ff 0/subop/increment 1/mod/*+disp8 6/rm32/ESI . . . . 8/disp8 . # increment *(ESI+8)
$read-byte:end:
# restore registers
# . restore registers
5e/pop-to-ESI
59/pop-to-ECX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -99,44 +99,44 @@ $read-byte:end:
test-read-byte-single:
## check that read-byte returns first byte of 'file'
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4)
# push args
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# read-byte(_test-buffered-file)
# push args
# . . push args
68/push _test-buffered-file/imm32
# call
# . . call
e8/call read-byte/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check-ints-equal(EAX, 'A')
# push args
# . . push args
68/push "F - test-read-byte-single"/imm32
68/push 0x41/imm32
50/push-EAX
# call
# . . call
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
# end
c3/return
@ -144,51 +144,51 @@ test-read-byte-single:
test-read-byte-multiple:
## call read-byte twice, check that second call returns second byte
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4)
# push args
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# read-byte(_test-buffered-file)
# push args
# . . push args
68/push _test-buffered-file/imm32
# call
# . . call
e8/call read-byte/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# read-byte(_test-buffered-file)
# push args
# . . push args
68/push _test-buffered-file/imm32
# call
# . . call
e8/call read-byte/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check-ints-equal(EAX, 'b')
# push args
# . . push args
68/push "F - test-read-byte-multiple"/imm32
68/push 0x62/imm32
50/push-EAX
# call
# . . call
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
# end
c3/return
@ -196,36 +196,36 @@ test-read-byte-multiple:
test-read-byte-end-of-file:
## call read-byte on an empty 'file', check that it returns -1
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4)
# push args
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# read-byte(_test-buffered-file)
# push args
# . . push args
68/push _test-buffered-file/imm32
# call
# . . call
e8/call read-byte/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check-ints-equal(EAX, -1)
# push args
# . . push args
68/push "F - test-read-byte-end-of-file"/imm32
68/push -1/imm32
50/push-EAX
# call
# . . call
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
# end
c3/return
@ -244,4 +244,4 @@ _test-buffered-file:
# data
00 00 00 00 00 00 00 00 # 8 bytes
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -1,9 +1,9 @@
# write-stream: like write, but write streams rather than strings
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
# manual test
@ -20,23 +20,23 @@
cd/syscall 0x80/imm8
write-stream: # f : fd or (address stream), s : (address stream) -> <void>
# prolog
# . prolog
55/push-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
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
# 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 . . 8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call _write-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
eb/jump $write-stream:end/disp8
$write-stream:fake:
# otherwise, treat 'f' as a stream to append to
# save registers
# . save registers
50/push-EAX
56/push-ESI
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
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
# call
# . . call
e8/call _append-4/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# f->write += EAX
01/add 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # add EAX to *ESI
# s->read += EAX
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
5e/pop-to-ESI
58/pop-to-EAX
$write-stream:end:
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
_write-stream: # fd : int, s : (address stream) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
52/push-EDX
@ -106,120 +106,120 @@ _write-stream: # fd : int, s : (address stream) -> <void>
# syscall
b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8
# restore registers
# . restore registers
5f/pop-to-EDI
5e/pop-to-ESI
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
test-write-stream-single:
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-stream2)
# push args
# . . push args
68/push _test-stream2/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream2, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push _test-stream2/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write-stream(_test-stream, _test-stream2)
# push args
# . . push args
68/push _test-stream2/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write-stream/disp32
# discard args
# . . discard args
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)
# push args
# . . push args
68/push "F - test-write-stream-single"/imm32
68/push 0x006241/imm32/Ab
# push *_test-stream.data
b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
test-write-stream-appends:
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-stream2)
# push args
# . . push args
68/push _test-stream2/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream2, "C")
# push args
# . . push args
68/push "C"/imm32
68/push _test-stream2/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write-stream(_test-stream, _test-stream2)
# push args
# . . push args
68/push _test-stream2/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(_test-stream2, "D")
# push args
# . . push args
68/push "D"/imm32
68/push _test-stream2/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write-stream(_test-stream, _test-stream2)
# push args
# . . push args
68/push _test-stream2/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write-stream/disp32
# discard args
# . . discard args
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)
# push args
# . . push args
68/push "F - test-write-stream-appends"/imm32
68/push 0x00004443/imm32/C-D
# push *_test-stream.data
b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# end
c3/return
@ -236,4 +236,4 @@ _test-stream2:
# data
41 42 43 44 00 00 00 00 # 8 bytes
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -26,12 +26,12 @@
# naming conventions.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# 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
# 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
@ -77,10 +77,10 @@ $main:end:
# 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>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
# 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
# . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# restore registers
# . restore registers
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
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
# not the right interface for us. But we'll keep it just to follow Crenshaw.)
#
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# 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
75/jump-if-not-equal $get-num:main/disp8
# . expected(ed, err, "integer")
# push args
# . . push args
68/push "integer"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
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
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
$get-num:main:
# save registers
# . save registers
50/push-EAX
51/push-ECX
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
7d/jump-if-lesser $get-num:stage2/disp8
# 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
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)
# . call
# . call
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
$get-num:stage2:
# out->data[out->write] = LSB(Look)
@ -279,14 +279,14 @@ $get-num:stage2:
$get-num:loop-end:
# persist necessary variables from registers
89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI
# restore registers
# . restore registers
5f/pop-to-EDI
5e/pop-to-ESI
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
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)
expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# write(f, "Error: ")
@ -517,14 +517,14 @@ expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (ad
# . call
e8/call stop/disp32
## should never get past this point
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# write(f, "Error: "+s+"\n") then stop(ed, 1)
error: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# write(f, "Error: ")
@ -558,17 +558,17 @@ error: # ed : (address exit-descriptor), f : fd or (address stream), s : (addre
# . call
e8/call stop/disp32
## should never get past this point
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# read a byte from 'f', and store it in 'Look'
get-char: # f : (address buffered-file) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
# read-byte(f)
# . 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
# save 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
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
is-digit?: # c : int -> bool/EAX
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# EAX = false
@ -601,7 +601,7 @@ is-digit?: # c : int -> bool/EAX
# otherwise return true
b8/copy-to-EAX 1/imm32
$is-digit?:end:
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -631,4 +631,4 @@ _test-error-stream:
# data
00 00 00 00 00 00 00 00 # 8 bytes
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -26,23 +26,23 @@
# naming conventions.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# 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
# 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
7e/jump-if-lesser-or-equal $run-main/disp8
# and if (argv[1] == "test")
# push args
# . . push args
68/push "test"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call
# . . call
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
# check result
3d/compare-EAX 1/imm32
@ -60,14 +60,14 @@ $run-main:
# clear ed->target (so we really exit)
c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX
# compile(Stdin, 1/stdout, 2/stderr, ed)
# push args
# . . push args
50/push-EAX/ed
68/push 2/imm32/stderr
68/push 1/imm32/stdout
68/push Stdin/imm32
# call
# . . call
e8/call compile/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# syscall(exit, 0)
bb/copy-to-EBX 0/imm32
@ -77,18 +77,18 @@ $main:end:
# 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>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
# 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)
# call
# . . call
e8/call get-char/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# 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.
@ -99,90 +99,90 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
# num->length = 7
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 8/disp8 7/imm32 # copy to *(ECX+8)
# clear-stream(num)
# push args
# . . push args
51/push-ECX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# 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 . . 0x10/disp8 . # push *(EBP+16)
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)
# call
# . . call
e8/call get-num/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# EAX = write(_test-stream, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, "bb/copy-to-EBX ")
# push args
# . . push args
68/push "bb/copy-to-EBX "/imm32
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
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write-stream(out, num)
# push args
# . . push args
51/push-ECX/num
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(out, Newline)
# push args
# . . push args
68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, "b8/copy-to-EAX 1/imm32/exit")
# push args
# . . push args
68/push "b8/copy-to-EAX 1/imm32/exit"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, Newline)
# push args
# . . push args
68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, "cd/syscall 0x80/imm8")
# push args
# . . push args
68/push "cd/syscall 0x80/imm8"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, Newline)
# push args
# . . push args
68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# restore registers
# . restore registers
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
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
# not the right interface for us. But we'll keep it just to follow Crenshaw.)
#
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# EAX = is-digit?(Look)
# push args
# . . push args
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
# call
# . . call
e8/call is-digit?/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# if EAX == 0 error
3d/compare-EAX 0/imm32
75/jump-if-not-equal $get-num:main/disp8
# expected(ed, err, "integer")
# push args
# . . push args
68/push "integer"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
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
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
$get-num:main:
# save registers
# . save registers
50/push-EAX
51/push-ECX
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
7d/jump-if-lesser $get-num:loop-stage2/disp8
# 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
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)
# call
# . . call
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
$get-num:loop-stage2:
# out->data[out->write] = LSB(Look)
@ -276,18 +276,18 @@ $get-num:loop-stage2:
# ++out->write
41/increment-ECX
# Look = get-char(in)
# push args
# . . push args
56/push-ESI
# call
# . . call
e8/call get-char/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# EAX = is-digit?(Look)
# push args
# . . push args
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
# call
# . . call
e8/call is-digit?/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# if EAX loop
3d/compare-EAX 0/imm32
@ -295,14 +295,14 @@ $get-num:loop-stage2:
$get-num:loop-end:
# persist necessary variables from registers
89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI
# restore registers
# . restore registers
5f/pop-to-EDI
5e/pop-to-ESI
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
58/pop-to-EAX
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
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
## clear all streams
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4)
# push args
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-output-stream)
# push args
# . . push args
68/push _test-output-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-error-stream)
# push args
# . . push args
68/push _test-error-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in'
# write(_test-stream, "3")
# push args
# . . push args
68/push "3"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed'
# 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
# size the exit-descriptor for the call to get-num below
# tailor-exit-descriptor(ed, 16)
# push args
# . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed
# call
# . . call
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
## prime the pump
# get-char(_test-buffered-file)
# push args
# . . push args
68/push _test-buffered-file/imm32
# call
# . . call
e8/call get-char/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## get-num(in, out, err, ed)
# push args
# . . push args
50/push-EAX/ed
68/push _test-error-stream/imm32
68/push _test-output-stream/imm32
68/push _test-buffered-file/imm32
# call
# . . call
e8/call get-num/disp32
## 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
# check-ints-equal(*_test-output-stream.data, '3')
# push args
# . . push args
68/push "F - test-get-num-reads-single-digit"/imm32
68/push 0x33/imm32
b8/copy-to-EAX _test-output-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# reclaim locals
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
## clear all streams
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4)
# push args
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-output-stream)
# push args
# . . push args
68/push _test-output-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-error-stream)
# push args
# . . push args
68/push _test-error-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in'
# write(_test-stream, "3")
# push args
# . . push args
68/push "3"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed'
# 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
# size the exit-descriptor for the call to get-num below
# tailor-exit-descriptor(ed, 16)
# push args
# . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed
# call
# . . call
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
## don't initialize Look
## get-num(in, out, err, ed)
# push args
# . . push args
50/push-EAX/ed
68/push _test-error-stream/imm32
68/push _test-output-stream/imm32
68/push _test-buffered-file/imm32
# call
# . . call
e8/call get-num/disp32
## 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
## check that get-num tried to call exit(1)
# check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
# push args
# . . push args
68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32
68/push 2/imm32
# push ed->value
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# call
# . . call
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
# reclaim locals
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
## clear all streams
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4)
# push args
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-output-stream)
# push args
# . . push args
68/push _test-output-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-error-stream)
# push args
# . . push args
68/push _test-error-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in'
# write(_test-stream, "3456 x")
# push args
# . . push args
68/push "3456"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed'
# 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
# size the exit-descriptor for the call to get-num below
# tailor-exit-descriptor(ed, 16)
# push args
# . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed
# call
# . . call
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
## prime the pump
# get-char(_test-buffered-file)
# push args
# . . push args
68/push _test-buffered-file/imm32
# call
# . . call
e8/call get-char/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## get-num(in, out, err, ed)
# push args
# . . push args
50/push-EAX/ed
68/push _test-error-stream/imm32
68/push _test-output-stream/imm32
68/push _test-buffered-file/imm32
# call
# . . call
e8/call get-num/disp32
## 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
# check-ints-equal(*_test-output-stream.data, '3456')
# push args
# . . push args
68/push "F - test-get-num-reads-multiple-digits"/imm32
68/push 0x36353433/imm32
b8/copy-to-EAX _test-output-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# reclaim locals
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
## clear all streams
# clear-stream(_test-stream)
# push args
# . . push args
68/push _test-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4)
# push args
# . . push args
b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32
50/push-EAX
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-output-stream)
# push args
# . . push args
68/push _test-output-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-error-stream)
# push args
# . . push args
68/push _test-error-stream/imm32
# call
# . . call
e8/call clear-stream/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in'
# write(_test-stream, "3456 x")
# push args
# . . push args
68/push "3456 x"/imm32
68/push _test-stream/imm32
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed'
# 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
# size the exit-descriptor for the call to get-num below
# tailor-exit-descriptor(ed, 16)
# push args
# . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed
# call
# . . call
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
## prime the pump
# get-char(_test-buffered-file)
# push args
# . . push args
68/push _test-buffered-file/imm32
# call
# . . call
e8/call get-char/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## get-num(in, out, err, ed)
# push args
# . . push args
50/push-EAX/ed
68/push _test-error-stream/imm32
68/push _test-output-stream/imm32
68/push _test-buffered-file/imm32
# call
# . . call
e8/call get-num/disp32
## 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
# 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 0x36353433/imm32
b8/copy-to-EAX _test-output-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call
# . . call
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
# reclaim locals
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)
expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# write(f, "Error: ")
# push args
# . . push args
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)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# 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 . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(f, " expected")
# push args
# . . push args
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)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(f, Newline)
# push args
# . . push args
68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# stop(ed, 1)
# push args
# . . push args
68/push 1/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call stop/disp32
## should never get past this point
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# write(f, "Error: "+s+"\n") then stop(ed, 1)
error: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# write(f, "Error: ")
# push args
# . . push args
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)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# 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 . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(f, Newline)
# push args
# . . push args
68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call
# . . call
e8/call write/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# stop(ed, 1)
# push args
# . . push args
68/push 1/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call stop/disp32
## should never get past this point
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
# read a byte from 'f', and store it in 'Look'
get-char: # f : (address buffered-file) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
# 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)
# call
# . . call
e8/call read-byte/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# save 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
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
is-digit?: # c : int -> bool/EAX
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# EAX = false
@ -803,7 +803,7 @@ is-digit?: # c : int -> bool/EAX
# otherwise return true
b8/copy-to-EAX 1/imm32
$is-digit?:end:
# epilog
# . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
c3/return
@ -833,4 +833,4 @@ _test-error-stream:
# data
00 00 00 00 00 00 00 00 # 8 bytes
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -15,23 +15,23 @@
# When running tests the exit status doesn't mean anything. Yet.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
# prolog
# . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# 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
7e/jump-if-lesser-or-equal $run-main/disp8
# and if (argv[1] == "test")
# push args
# . . push args
68/push "test"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call
# . . call
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
# check result
3d/compare-EAX 1/imm32
@ -42,11 +42,11 @@
eb/jump $main:end/disp8 # where EAX will get copied to EBX
# else EAX = factorial(5)
$run-main:
# push args
# . . push args
68/push 5/imm32
# call
# . . call
e8/call factorial/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
$main:end:
# exit(EAX)
@ -56,7 +56,7 @@ $main:end:
# factorial(n)
factorial:
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
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
81 5/subop/subtract 3/mod/direct 3/rm32/EBX . . . . . 1/imm32 # subtract from EBX
# EAX = factorial(n-1)
# push args
# . . push args
53/push-EBX
# call
# . . call
e8/call factorial/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# 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
# TODO: check for overflow
$factorial:end:
# epilog
# . epilog
5b/pop-to-EBX
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP
@ -87,22 +87,22 @@ $factorial:end:
test-factorial:
# factorial(5)
# push args
# . . push args
68/push 5/imm32
# call
# . . call
e8/call factorial/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# check-ints-equal(EAX, 120, failure message)
# push args
# . . push args
68/push "F - test-factorial"/imm32
68/push 0x78/imm32/expected-120
50/push-EAX
# call
# . . call
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
# end
c3/return
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -15,4 +15,4 @@ bb/copy-to-EBX 2a/imm32 # 42 in hex
b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -8,9 +8,9 @@
# 0 # false
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main: return argv-equal(argv[1], argv[2])
# At the start of a SubX program:
@ -18,14 +18,14 @@
# argv[0]: *(ESP+4)
# argv[1]: *(ESP+8)
# ...
# prolog
# . prolog
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]
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# push argv[1]
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call argv-equal/disp32
# exit(EAX)
$exit:
@ -69,4 +69,4 @@ $argv-equal:false:
b8/copy-to-EAX 0/imm32
c3/return
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -15,9 +15,9 @@
# would cause tests to not run, rather than to fail as we'd like.)
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
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
# 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
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
52/push-EDX
53/push-EBX
@ -97,7 +97,7 @@ $kernel-string-equal:false:
b8/copy-to-EAX 0/imm32
$kernel-string-equal:end:
# restore registers
# . restore registers
5f/pop-to-EDI
5e/pop-to-ESI
5b/pop-to-EBX
@ -112,141 +112,141 @@ $kernel-string-equal:end:
test-compare-null-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "")
# push args
# . . push args
68/push ""/imm32
68/push Null-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 1, msg)
# push args
# . . call check-ints-equal(EAX, 1, msg)
# . . push args
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
68/push 1/imm32/true
50/push-EAX
# call
# . . call
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
c3/return
test-compare-null-kernel-string-with-non-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "Abc")
# push args
# . . push args
68/push "Abc"/imm32
68/push Null-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0, msg)
# push args
# . . call check-ints-equal(EAX, 0, msg)
# . . push args
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-equal-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
# push args
# . . push args
68/push "Abc"/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 1, msg)
# push args
# . . call check-ints-equal(EAX, 1, msg)
# . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 1/imm32/true
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-inequal-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
# push args
# . . push args
68/push "Adc"/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0, msg)
# push args
# . . call check-ints-equal(EAX, 0, msg)
# . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Abc-kernel-string, "")
# push args
# . . push args
68/push ""/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0)
# push args
# . . call check-ints-equal(EAX, 0)
# . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-shorter-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
# push args
# . . push args
68/push "Ab"/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0)
# push args
# . . call check-ints-equal(EAX, 0)
# . . push args
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
test-compare-kernel-string-with-longer-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
# push args
# . . push args
68/push "Abcd"/imm32
68/push Abc-kernel-string/imm32
# call
# . . call
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
# call check-ints-equal(EAX, 0)
# push args
# . . call check-ints-equal(EAX, 0)
# . . push args
68/push "F - test-compare-kernel-string-with-longer-array"/imm32
68/push 0/imm32/false
50/push-EAX
# call
# . . call
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
c3/return
@ -254,10 +254,10 @@ test-compare-kernel-string-with-longer-array:
# print msg to stderr if a != b, otherwise print "."
check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
51/push-ECX
53/push-EBX
# 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
75/jump-if-unequal $check-ints-equal:else/disp8
# print('.')
# push args
# . . push args
68/push "."/imm32
# call
# . . call
e8/call write-stderr/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# return
eb/jump $check-ints-equal:end/disp8
@ -280,21 +280,21 @@ $check-ints-equal:else:
# copy msg into ECX
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX
# print(ECX)
# push args
# . . push args
51/push-ECX
# call
# . . call
e8/call write-stderr/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# print newline
# push args
# . . push args
68/push Newline/imm32
# call
# . . call
e8/call write-stderr/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
$check-ints-equal:end:
# restore registers
# . restore registers
5b/pop-to-EBX
59/pop-to-ECX
# end
@ -303,10 +303,10 @@ $check-ints-equal:end:
c3/return
write-stderr: # s : (address array byte) -> <void>
# prolog
# . prolog
55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers
# . save registers
50/push-EAX
51/push-ECX
52/push-EDX
@ -323,7 +323,7 @@ write-stderr: # s : (address array byte) -> <void>
# syscall
b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8
# restore registers
# . restore registers
5b/pop-to-EBX
5a/pop-to-EDX
59/pop-to-ECX
@ -347,4 +347,4 @@ Null-kernel-string:
Abc-kernel-string:
41/A 62/b 63/c 00/null
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -7,9 +7,9 @@
# You shouldn't get a segmentation fault.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# syscall(mmap, 0x1000)
bb/copy-to-EBX Mmap-new-segment/imm32
@ -41,4 +41,4 @@ Mmap-new-segment: # type mmap_arg_struct
# offset
00 00 00 00 # 0 since MAP_ANONYMOUS is specified
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -15,4 +15,4 @@ bb/copy-to-EBX 1/imm32
b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -8,9 +8,9 @@
# 55
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# result: EBX = 0
bb/copy-to-EBX 0/imm32
@ -33,4 +33,4 @@ $exit:
b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -37,4 +37,4 @@ cd/syscall 0x80/imm8
X:
00 00 00 00 # space for read() to write to
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -5,9 +5,9 @@
# $ subx run examples/ex5
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# main:
# allocate x on the stack
@ -39,4 +39,4 @@
b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -6,9 +6,9 @@
# Hello, world!
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# syscall(write, stdout, X, size)
# fd = 1 (stdout)
@ -33,4 +33,4 @@ X: # string to print
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
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -11,9 +11,9 @@
# 97
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# syscall(creat, Filename)
bb/copy-to-EBX Filename/imm32
@ -101,4 +101,4 @@ B:
Filename:
2e 66 6f 6f 00 00 00 00
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -15,18 +15,18 @@
# Locals start from ESP-4 downwards.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# prolog
# . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# call ascii-length(argv[1])
# push args
# . . call ascii-length(argv[1])
# . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call ascii-length/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# exit(EAX)
@ -55,4 +55,4 @@ $ascii-length-ret:
# return (result in EAX)
c3/return
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0

View File

@ -17,20 +17,20 @@
# Locals start from ESP-4 downwards.
== code
# instruction effective address operand displacement immediate
# 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
# instruction effective address register displacement immediate
# . 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
# prolog
# . prolog
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]
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# push argv[1]
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call
# . . call
e8/call ascii-difference/disp32
# discard args
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# exit(EAX)
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
c3/return
# vim:nowrap:textwidth=0
# . . vim:nowrap:textwidth=0