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

View File

@ -1,9 +1,9 @@
# Rudimentary test harness # Rudimentary test harness
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: (manual test if this is the last file loaded) # main: (manual test if this is the last file loaded)
# check-ints-equal(34, 34) # check-ints-equal(34, 34)
@ -19,10 +19,10 @@
# print msg to stderr if a != b, otherwise print "." # print msg to stderr if a != b, otherwise print "."
check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
51/push-ECX 51/push-ECX
53/push-EBX 53/push-EBX
# load first 2 args into EAX and EBX # load first 2 args into EAX and EBX
@ -32,41 +32,41 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
75/jump-if-unequal $check-ints-equal:else/disp8 75/jump-if-unequal $check-ints-equal:else/disp8
# _write(2/stderr, '.') # _write(2/stderr, '.')
# push args # . . push args
68/push "."/imm32 68/push "."/imm32
68/push 2/imm32/stderr 68/push 2/imm32/stderr
# call # . . call
e8/call _write/disp32 e8/call _write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# return # return
eb/jump $check-ints-equal:end/disp8 eb/jump $check-ints-equal:end/disp8
# else: # else:
$check-ints-equal:else: $check-ints-equal:else:
# _write(2/stderr, msg) # _write(2/stderr, msg)
# push args # . . push args
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX
51/push-ECX 51/push-ECX
68/push 2/imm32/stderr 68/push 2/imm32/stderr
# call # . . call
e8/call _write/disp32 e8/call _write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# _write(2/stderr, Newline) # _write(2/stderr, Newline)
# push args # . . push args
68/push Newline/imm32 68/push Newline/imm32
68/push 2/imm32/stderr 68/push 2/imm32/stderr
# call # . . call
e8/call _write/disp32 e8/call _write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# increment Num-test-failures # increment Num-test-failures
ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures
$check-ints-equal:end: $check-ints-equal:end:
# restore registers # . restore registers
5b/pop-to-EBX 5b/pop-to-EBX
59/pop-to-ECX 59/pop-to-ECX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
@ -82,4 +82,4 @@ Newline:
Num-test-failures: Num-test-failures:
00 00 00 00 00 00 00 00
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

@ -15,9 +15,9 @@
# would cause tests to not run, rather than to fail as we'd like.) # would cause tests to not run, rather than to fail as we'd like.)
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: # main:
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
@ -29,10 +29,10 @@
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
51/push-ECX 51/push-ECX
52/push-EDX 52/push-EDX
53/push-EBX 53/push-EBX
@ -98,13 +98,13 @@ $kernel-string-equal:false:
b8/copy-to-EAX 0/imm32 b8/copy-to-EAX 0/imm32
$kernel-string-equal:end: $kernel-string-equal:end:
# restore registers # . restore registers
5f/pop-to-EDI 5f/pop-to-EDI
5e/pop-to-ESI 5e/pop-to-ESI
5b/pop-to-EBX 5b/pop-to-EBX
5a/pop-to-EDX 5a/pop-to-EDX
59/pop-to-ECX 59/pop-to-ECX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
@ -113,141 +113,141 @@ $kernel-string-equal:end:
test-compare-null-kernel-string-with-empty-array: test-compare-null-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "") # EAX = kernel-string-equal(Null-kernel-string, "")
# push args # . . push args
68/push ""/imm32 68/push ""/imm32
68/push Null-kernel-string/imm32 68/push Null-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 1, msg) # . . call check-ints-equal(EAX, 1, msg)
# push args # . . push args
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32 68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-null-kernel-string-with-non-empty-array: test-compare-null-kernel-string-with-non-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "Abc") # EAX = kernel-string-equal(Null-kernel-string, "Abc")
# push args # . . push args
68/push "Abc"/imm32 68/push "Abc"/imm32
68/push Null-kernel-string/imm32 68/push Null-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0, msg) # . . call check-ints-equal(EAX, 0, msg)
# push args # . . push args
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32 68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-equal-array: test-compare-kernel-string-with-equal-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Abc") # EAX = kernel-string-equal(Abc-kernel-string, "Abc")
# push args # . . push args
68/push "Abc"/imm32 68/push "Abc"/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 1, msg) # . . call check-ints-equal(EAX, 1, msg)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-inequal-array: test-compare-kernel-string-with-inequal-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Adc") # EAX = kernel-string-equal(Abc-kernel-string, "Adc")
# push args # . . push args
68/push "Adc"/imm32 68/push "Adc"/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0, msg) # . . call check-ints-equal(EAX, 0, msg)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-empty-array: test-compare-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Abc-kernel-string, "") # EAX = kernel-string-equal(Abc-kernel-string, "")
# push args # . . push args
68/push ""/imm32 68/push ""/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0) # . . call check-ints-equal(EAX, 0)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-shorter-array: test-compare-kernel-string-with-shorter-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Ab") # EAX = kernel-string-equal(Abc-kernel-string, "Ab")
# push args # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0) # . . call check-ints-equal(EAX, 0)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32 68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-longer-array: test-compare-kernel-string-with-longer-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd") # EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
# push args # . . push args
68/push "Abcd"/imm32 68/push "Abcd"/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0) # . . call check-ints-equal(EAX, 0)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-longer-array"/imm32 68/push "F - test-compare-kernel-string-with-longer-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
@ -258,4 +258,4 @@ Null-kernel-string:
Abc-kernel-string: Abc-kernel-string:
41/A 62/b 63/c 00/null 41/A 62/b 63/c 00/null
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

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

View File

@ -1,9 +1,9 @@
# Comparing 'regular' length-prefixed strings. # Comparing 'regular' length-prefixed strings.
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: # main:
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
@ -13,10 +13,10 @@
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
string-equal: # s : string, benchmark : string -> EAX : boolean string-equal: # s : string, benchmark : string -> EAX : boolean
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
51/push-ECX 51/push-ECX
52/push-EDX 52/push-EDX
53/push-EBX 53/push-EBX
@ -74,12 +74,12 @@ $string-equal:false:
# return false # return false
b8/copy-to-EAX 0/imm32 b8/copy-to-EAX 0/imm32
$string-equal:end: $string-equal:end:
# restore registers # . restore registers
5e/pop-to-ESI 5e/pop-to-ESI
5b/pop-to-EBX 5b/pop-to-EBX
5a/pop-to-EDX 5a/pop-to-EDX
59/pop-to-ECX 59/pop-to-ECX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
@ -88,82 +88,82 @@ $string-equal:end:
test-compare-empty-with-empty-string: test-compare-empty-with-empty-string:
# EAX = string-equal("", "") # EAX = string-equal("", "")
# push args # . . push args
68/push ""/imm32 68/push ""/imm32
68/push ""/imm32 68/push ""/imm32
# call # . . call
e8/call string-equal/disp32 e8/call string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 1, msg) # . . call check-ints-equal(EAX, 1, msg)
# push args # . . push args
68/push "F - test-compare-empty-with-empty-string"/imm32 68/push "F - test-compare-empty-with-empty-string"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-empty-with-non-empty-string: # also checks length-mismatch code path test-compare-empty-with-non-empty-string: # also checks length-mismatch code path
# EAX = string-equal("", "Abc") # EAX = string-equal("", "Abc")
# push args # . . push args
68/push "Abc"/imm32 68/push "Abc"/imm32
68/push ""/imm32 68/push ""/imm32
# call # . . call
e8/call string-equal/disp32 e8/call string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0, msg) # . . call check-ints-equal(EAX, 0, msg)
# push args # . . push args
68/push "F - test-compare-empty-with-non-empty-string"/imm32 68/push "F - test-compare-empty-with-non-empty-string"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-equal-strings: test-compare-equal-strings:
# EAX = string-equal("Abc", "Abc") # EAX = string-equal("Abc", "Abc")
# push args # . . push args
68/push "Abc"/imm32 68/push "Abc"/imm32
68/push "Abc"/imm32 68/push "Abc"/imm32
# call # . . call
e8/call string-equal/disp32 e8/call string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 1, msg) # . . call check-ints-equal(EAX, 1, msg)
# push args # . . push args
68/push "F - test-compare-equal-strings"/imm32 68/push "F - test-compare-equal-strings"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-inequal-strings-equal-lengths: test-compare-inequal-strings-equal-lengths:
# EAX = string-equal("Abc", "Adc") # EAX = string-equal("Abc", "Adc")
# push args # . . push args
68/push "Adc"/imm32 68/push "Adc"/imm32
68/push "Abc"/imm32 68/push "Abc"/imm32
# call # . . call
e8/call string-equal/disp32 e8/call string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0, msg) # . . call check-ints-equal(EAX, 0, msg)
# push args # . . push args
68/push "F - test-compare-inequal-strings-equal-lengths"/imm32 68/push "F - test-compare-inequal-strings-equal-lengths"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

@ -38,9 +38,9 @@ _test-trace-stream:
00 00 00 00 00 00 00 00 # 8 bytes 00 00 00 00 00 00 00 00 # 8 bytes
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: # main:
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
@ -53,11 +53,11 @@ _test-trace-stream:
# The Trace-stream segment will consist of variable-length lines separated by newlines (0x0a) # The Trace-stream segment will consist of variable-length lines separated by newlines (0x0a)
initialize-trace-stream: initialize-trace-stream:
# EAX = new-segment(0x1000) # EAX = new-segment(0x1000)
# push args # . . push args
68/push 0x1000/imm32/N 68/push 0x1000/imm32/N
# call # . . call
e8/call new-segment/disp32 e8/call new-segment/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# copy EAX to *Trace-stream # copy EAX to *Trace-stream
89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Trace-stream/disp32 # copy EAX to *Trace-stream 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Trace-stream/disp32 # copy EAX to *Trace-stream
@ -68,10 +68,10 @@ initialize-trace-stream:
# Append a string to the given trace stream. # Append a string to the given trace stream.
# Silently give up if it's already full. Or truncate the string if there isn't enough room. # Silently give up if it's already full. Or truncate the string if there isn't enough room.
trace: # t : (address trace-stream), line : string trace: # t : (address trace-stream), line : string
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
52/push-EDX 52/push-EDX
@ -95,9 +95,9 @@ trace: # t : (address trace-stream), line : string
# push &t->data[t->write] # push &t->data[t->write]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX
53/push-EBX 53/push-EBX
# call # . . call
e8/call _append-3/disp32 e8/call _append-3/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# if EAX == 0 return # if EAX == 0 return
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EDX 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EDX
@ -115,30 +115,30 @@ trace: # t : (address trace-stream), line : string
# push &t->data[t->write] # push &t->data[t->write]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX
53/push-EBX 53/push-EBX
# call # . . call
e8/call _append-3/disp32 e8/call _append-3/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# t->write += EAX # t->write += EAX
01/add 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to *EDI 01/add 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to *EDI
$trace:end: $trace:end:
# restore registers # . restore registers
5f/pop-to-EDI 5f/pop-to-EDI
5e/pop-to-ESI 5e/pop-to-ESI
5b/pop-to-EBX 5b/pop-to-EBX
5a/pop-to-EDX 5a/pop-to-EDX
59/pop-to-ECX 59/pop-to-ECX
58/pop-to-EAX 58/pop-to-EAX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
clear-trace-stream: # t : (address trace-stream) clear-trace-stream: # t : (address trace-stream)
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
# EAX = t # EAX = t
@ -164,10 +164,10 @@ $clear-trace-stream:loop:
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX 81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX
eb/jump $clear-trace-stream:loop/disp8 eb/jump $clear-trace-stream:loop/disp8
$clear-trace-stream:end: $clear-trace-stream:end:
# restore registers # . restore registers
59/pop-to-ECX 59/pop-to-ECX
58/pop-to-EAX 58/pop-to-EAX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
@ -176,98 +176,98 @@ $clear-trace-stream:end:
test-trace-single: test-trace-single:
# clear-trace-stream(_test-trace-stream) # clear-trace-stream(_test-trace-stream)
# push args # . . push args
68/push _test-trace-stream/imm32 68/push _test-trace-stream/imm32
# call # . . call
e8/call clear-trace-stream/disp32 e8/call clear-trace-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# trace(_test-trace-stream, "Ab") # trace(_test-trace-stream, "Ab")
# push args # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push _test-trace-stream/imm32 68/push _test-trace-stream/imm32
# call # . . call
e8/call trace/disp32 e8/call trace/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(*_test-trace-stream.data, 41/A 62/b 0a/newline 00, msg) # check-ints-equal(*_test-trace-stream.data, 41/A 62/b 0a/newline 00, msg)
# push args # . . push args
68/push "F - test-trace-single"/imm32 68/push "F - test-trace-single"/imm32
68/push 0x0a6241/imm32/Ab-newline 68/push 0x0a6241/imm32/Ab-newline
# push *_test-trace-stream.data # push *_test-trace-stream.data
b8/copy-to-EAX _test-trace-stream/imm32 b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # end
c3/return c3/return
test-trace-appends: test-trace-appends:
# clear-trace-stream(_test-trace-stream) # clear-trace-stream(_test-trace-stream)
# push args # . . push args
68/push _test-trace-stream/imm32 68/push _test-trace-stream/imm32
# call # . . call
e8/call clear-trace-stream/disp32 e8/call clear-trace-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# trace(_test-trace-stream, "C") # trace(_test-trace-stream, "C")
# push args # . . push args
68/push "C"/imm32 68/push "C"/imm32
68/push _test-trace-stream/imm32 68/push _test-trace-stream/imm32
# call # . . call
e8/call trace/disp32 e8/call trace/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# trace(_test-trace-stream, "D") # trace(_test-trace-stream, "D")
# push args # . . push args
68/push "D"/imm32 68/push "D"/imm32
68/push _test-trace-stream/imm32 68/push _test-trace-stream/imm32
# call # . . call
e8/call trace/disp32 e8/call trace/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(*_test-trace-stream.data, 43/C 0a/newline 44/D 0a/newline, msg) # check-ints-equal(*_test-trace-stream.data, 43/C 0a/newline 44/D 0a/newline, msg)
# push args # . . push args
68/push "F - test-trace-appends"/imm32 68/push "F - test-trace-appends"/imm32
68/push 0x0a440a43/imm32/C-newline-D-newline 68/push 0x0a440a43/imm32/C-newline-D-newline
# push *_test-trace-stream.data # push *_test-trace-stream.data
b8/copy-to-EAX _test-trace-stream/imm32 b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # end
c3/return c3/return
test-trace-empty-line: test-trace-empty-line:
# clear-trace-stream(_test-trace-stream) # clear-trace-stream(_test-trace-stream)
# push args # . . push args
68/push _test-trace-stream/imm32 68/push _test-trace-stream/imm32
# call # . . call
e8/call clear-trace-stream/disp32 e8/call clear-trace-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# trace(_test-trace-stream, "") # trace(_test-trace-stream, "")
# push args # . . push args
68/push ""/imm32 68/push ""/imm32
68/push _test-trace-stream/imm32 68/push _test-trace-stream/imm32
# call # . . call
e8/call trace/disp32 e8/call trace/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(*_test-trace-stream.data, 0, msg) # check-ints-equal(*_test-trace-stream.data, 0, msg)
# push args # . . push args
68/push "F - test-trace-empty-line"/imm32 68/push "F - test-trace-empty-line"/imm32
68/push 0/imm32 68/push 0/imm32
# push *_test-trace-stream.data # push *_test-trace-stream.data
b8/copy-to-EAX _test-trace-stream/imm32 b8/copy-to-EAX _test-trace-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # end
c3/return c3/return
@ -276,10 +276,10 @@ test-trace-empty-line:
# 3-argument variant of _append # 3-argument variant of _append
_append-3: # out : address, outend : address, s : (array byte) -> num_bytes_appended/EAX _append-3: # out : address, outend : address, s : (array byte) -> num_bytes_appended/EAX
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
51/push-ECX 51/push-ECX
# _append-4(out, outend, &s.data[0], &s.data[s.length]) -> num_bytes_appended/EAX # _append-4(out, outend, &s.data[0], &s.data[s.length]) -> num_bytes_appended/EAX
# push &s.data[s.length] # push &s.data[s.length]
@ -297,23 +297,23 @@ _append-3: # out : address, outend : address, s : (array byte) -> num_bytes_app
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# push out # push out
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call # . . call
e8/call _append-4/disp32 e8/call _append-4/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# restore registers # . restore registers
59/pop-to-ECX 59/pop-to-ECX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
# 4-argument variant of _append # 4-argument variant of _append
_append-4: # out : address, outend : address, in : address, inend : address -> num_bytes_appended/EAX _append-4: # out : address, outend : address, in : address, inend : address -> num_bytes_appended/EAX
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
51/push-ECX 51/push-ECX
52/push-EDX 52/push-EDX
53/push-EBX 53/push-EBX
@ -345,15 +345,15 @@ $_append-4:loop:
47/increment-EDI 47/increment-EDI
eb/jump $_append-4:loop/disp8 eb/jump $_append-4:loop/disp8
$_append-4:end: $_append-4:end:
# restore registers # . restore registers
5f/pop-to-EDI 5f/pop-to-EDI
5e/pop-to-ESI 5e/pop-to-ESI
5b/pop-to-EBX 5b/pop-to-EBX
5a/pop-to-EDX 5a/pop-to-EDX
59/pop-to-ECX 59/pop-to-ECX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

@ -16,9 +16,9 @@
# data: (array byte) # prefixed by length as usual # data: (array byte) # prefixed by length as usual
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: # main:
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
@ -31,23 +31,23 @@ write: # f : fd or (address stream), s : (address array byte) -> bytes_written/
# (If we ever leave the Linux kernel behind, it may be better to return # (If we ever leave the Linux kernel behind, it may be better to return
# the number of bytes *not* written. Success would then be signaled by # the number of bytes *not* written. Success would then be signaled by
# returning 0.) # returning 0.)
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# if (f < 0x08000000) _write(f, s), return # f can't be a user-mode address, so treat it as a kernel file descriptor # if (f < 0x08000000) _write(f, s), return # f can't be a user-mode address, so treat it as a kernel file descriptor
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 0x08000000/imm32 # compare *(EBP+8) 81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 0x08000000/imm32 # compare *(EBP+8)
7d/jump-if-greater-or-equal $write:fake/disp8 7d/jump-if-greater-or-equal $write:fake/disp8
# push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call # . . call
e8/call _write/disp32 e8/call _write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
eb/jump $write:end/disp8 eb/jump $write:end/disp8
$write:fake: $write:fake:
# otherwise, treat 'f' as a stream to append to # otherwise, treat 'f' as a stream to append to
# save registers # . save registers
51/push-ECX 51/push-ECX
52/push-EDX 52/push-EDX
53/push-EBX 53/push-EBX
@ -66,27 +66,27 @@ $write:fake:
# push &f->data[f->write] # push &f->data[f->write]
8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 2/index/EDX . 3/r32/EBX 0xc/disp8 . # copy ECX+EDX+12 to EBX 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ECX 2/index/EDX . 3/r32/EBX 0xc/disp8 . # copy ECX+EDX+12 to EBX
53/push-EBX 53/push-EBX
# call # . . call
e8/call _append-3/disp32 e8/call _append-3/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# f->write += EAX # f->write += EAX
01/add 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # add EAX to *ECX 01/add 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # add EAX to *ECX
# restore registers # . restore registers
5b/pop-to-EBX 5b/pop-to-EBX
5a/pop-to-EDX 5a/pop-to-EDX
59/pop-to-ECX 59/pop-to-ECX
$write:end: $write:end:
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
clear-stream: # f : (address stream) -> <void> clear-stream: # f : (address stream) -> <void>
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
# EAX = f # EAX = f
@ -112,87 +112,87 @@ $clear-stream:loop:
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX 81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 4/imm32 # add to EAX
eb/jump $clear-stream:loop/disp8 eb/jump $clear-stream:loop/disp8
$clear-stream:end: $clear-stream:end:
# restore registers # . restore registers
59/pop-to-ECX 59/pop-to-ECX
58/pop-to-EAX 58/pop-to-EAX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
test-write-single: test-write-single:
# clear-stream(_test-stream) # clear-stream(_test-stream)
# push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "Ab") # write(_test-stream, "Ab")
# push args # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(EAX, 2) # check-ints-equal(EAX, 2)
# push args # . . push args
68/push "F - test-read-single: return EAX"/imm32 68/push "F - test-read-single: return EAX"/imm32
68/push 2/imm32 68/push 2/imm32
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# check-ints-equal(*_test-stream->data, 41/A 62/b 00 00, msg) # check-ints-equal(*_test-stream->data, 41/A 62/b 00 00, msg)
# push args # . . push args
68/push "F - test-write-single"/imm32 68/push "F - test-write-single"/imm32
68/push 0x006241/imm32/Ab 68/push 0x006241/imm32/Ab
# push *_test-stream->data # push *_test-stream->data
b8/copy-to-EAX _test-stream/imm32 b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # end
c3/return c3/return
test-write-appends: test-write-appends:
# clear-stream(_test-stream) # clear-stream(_test-stream)
# push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# write(_test-stream, "C") # write(_test-stream, "C")
# push args # . . push args
68/push "C"/imm32 68/push "C"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(_test-stream, "D") # write(_test-stream, "D")
# push args # . . push args
68/push "D"/imm32 68/push "D"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check-ints-equal(*_test-stream->data, 43/C 44/D 00 00, msg) # check-ints-equal(*_test-stream->data, 43/C 44/D 00 00, msg)
# push args # . . push args
68/push "F - test-write-appends"/imm32 68/push "F - test-write-appends"/imm32
68/push 0x00004443/imm32/C-D 68/push 0x00004443/imm32/C-D
# push *_test-stream->data # push *_test-stream->data
b8/copy-to-EAX _test-stream/imm32 b8/copy-to-EAX _test-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# end # end
c3/return c3/return
@ -209,4 +209,4 @@ _test-stream:
# data # data
00 00 00 00 00 00 00 00 # 8 bytes 00 00 00 00 00 00 00 00 # 8 bytes
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

@ -33,9 +33,9 @@
# Its value is its output, computed during stop and available to the test. # Its value is its output, computed during stop and available to the test.
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: # main:
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
@ -49,10 +49,10 @@
# the stack. # the stack.
# Ugly that we need to know the size of args, but so it goes. # Ugly that we need to know the size of args, but so it goes.
tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void> tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void>
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
# EAX = nbytes # EAX = nbytes
@ -65,7 +65,7 @@ tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void
# That's the value we need to return: X-nbytes-4 # That's the value we need to return: X-nbytes-4
# #
# However, we also need to account for the perturbance to ESP caused by the # However, we also need to account for the perturbance to ESP caused by the
# call to tailor-exit-descriptor. It pushes 8 bytes of args followed by 4 # . . call to tailor-exit-descriptor. It pushes 8 bytes of args followed by 4
# bytes for the return address and 4 bytes to push EBP above. # bytes for the return address and 4 bytes to push EBP above.
# So EBP at this point is X-16. # So EBP at this point is X-16.
# #
@ -87,10 +87,10 @@ tailor-exit-descriptor: # ed : (address exit-descriptor), nbytes : int -> <void
89/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to *ECX 89/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to *ECX
# initialize ed->value # initialize ed->value
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # copy to *(ECX+4) c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # copy to *(ECX+4)
# restore registers # . restore registers
59/pop-to-ECX 59/pop-to-ECX
58/pop-to-EAX 58/pop-to-EAX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
@ -132,78 +132,78 @@ test-stop-skips-returns-on-exit:
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX 8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
# Size the exit-descriptor precisely for the next call below, to _test-stop-1. # Size the exit-descriptor precisely for the next call below, to _test-stop-1.
# tailor-exit-descriptor(ed, 4) # tailor-exit-descriptor(ed, 4)
# push args # . . push args
68/push 4/imm32/nbytes-of-args-for-_test-stop-1 68/push 4/imm32/nbytes-of-args-for-_test-stop-1
50/push-EAX 50/push-EAX
# call # . . call
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call _test-stop-1(ed) # . . call _test-stop-1(ed)
# push args # . . push args
50/push-EAX 50/push-EAX
# call # . . call
e8/call _test-stop-1/disp32 e8/call _test-stop-1/disp32
## registers except ESP may be clobbered at this point ## registers except ESP may be clobbered at this point
# restore args # restore args
58/pop-to-EAX 58/pop-to-EAX
# check that _test-stop-1 tried to call exit(1) # check that _test-stop-1 tried to call exit(1)
# check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 # check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
# push args # . . push args
68/push "F - test-stop-skips-returns-on-exit"/imm32 68/push "F - test-stop-skips-returns-on-exit"/imm32
68/push 2/imm32 68/push 2/imm32
# push ed->value # push ed->value
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# epilog # . epilog
5d/pop-to-EBP 5d/pop-to-EBP
# don't restore ESP from EBP; manually reclaim locals # don't restore ESP from EBP; manually reclaim locals
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
c3/return c3/return
_test-stop-1: # ed : (address exit-descriptor) _test-stop-1: # ed : (address exit-descriptor)
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# _test-stop-2(ed) # _test-stop-2(ed)
# push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call # . . call
e8/call _test-stop-2/disp32 e8/call _test-stop-2/disp32
## should never get past this point ## should never get past this point
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# signal test failed: check-ints-equal(1, 0, msg) # signal test failed: check-ints-equal(1, 0, msg)
# push args # . . push args
68/push "F - test-stop-skips-returns-on-exit"/imm32 68/push "F - test-stop-skips-returns-on-exit"/imm32
68/push 0/imm32 68/push 0/imm32
68/push 1/imm32 68/push 1/imm32
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
_test-stop-2: # ed : (address exit-descriptor) _test-stop-2: # ed : (address exit-descriptor)
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# call stop(ed, 1) # . . call stop(ed, 1)
# push args # . . push args
68/push 1/imm32 68/push 1/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call # . . call
e8/call stop/disp32 e8/call stop/disp32
## should never get past this point ## should never get past this point
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

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

View File

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

View File

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

View File

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

View File

@ -26,23 +26,23 @@
# naming conventions. # naming conventions.
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: run tests if necessary, call 'compile' if not # main: run tests if necessary, call 'compile' if not
# prolog # . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# if (argc > 1) # if (argc > 1)
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0/disp8 1/imm32 # compare *EBP 81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0/disp8 1/imm32 # compare *EBP
7e/jump-if-lesser-or-equal $run-main/disp8 7e/jump-if-lesser-or-equal $run-main/disp8
# and if (argv[1] == "test") # and if (argv[1] == "test")
# push args # . . push args
68/push "test"/imm32 68/push "test"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# check result # check result
3d/compare-EAX 1/imm32 3d/compare-EAX 1/imm32
@ -60,14 +60,14 @@ $run-main:
# clear ed->target (so we really exit) # clear ed->target (so we really exit)
c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX c7/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX
# compile(Stdin, 1/stdout, 2/stderr, ed) # compile(Stdin, 1/stdout, 2/stderr, ed)
# push args # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push 2/imm32/stderr 68/push 2/imm32/stderr
68/push 1/imm32/stdout 68/push 1/imm32/stdout
68/push Stdin/imm32 68/push Stdin/imm32
# call # . . call
e8/call compile/disp32 e8/call compile/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# syscall(exit, 0) # syscall(exit, 0)
bb/copy-to-EBX 0/imm32 bb/copy-to-EBX 0/imm32
@ -77,18 +77,18 @@ $main:end:
# the main entry point # the main entry point
compile: # in : fd or (address stream), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void> compile: # in : fd or (address stream), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
# Look = get-char(in) # Look = get-char(in)
# push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# var num/ECX : (address stream) on the stack # var num/ECX : (address stream) on the stack
# Numbers can be 32 bits or 8 hex bytes long. One of them will be in 'Look', so we need space for 7 bytes. # Numbers can be 32 bits or 8 hex bytes long. One of them will be in 'Look', so we need space for 7 bytes.
@ -99,90 +99,90 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd
# num->length = 7 # num->length = 7
c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 8/disp8 7/imm32 # copy to *(ECX+8) c7/copy 1/mod/*+disp8 1/rm32/ECX . . . . 8/disp8 7/imm32 # copy to *(ECX+8)
# clear-stream(num) # clear-stream(num)
# push args # . . push args
51/push-ECX 51/push-ECX
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# get-num(in, num, err, ed) # get-num(in, num, err, ed)
# push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20)
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
51/push-ECX/num 51/push-ECX/num
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call # . . call
e8/call get-num/disp32 e8/call get-num/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# EAX = write(_test-stream, "Ab") # EAX = write(_test-stream, "Ab")
# push args # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, "bb/copy-to-EBX ") # EAX = write(out, "bb/copy-to-EBX ")
# push args # . . push args
68/push "bb/copy-to-EBX "/imm32 68/push "bb/copy-to-EBX "/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write-stream(out, num) # write-stream(out, num)
# push args # . . push args
51/push-ECX/num 51/push-ECX/num
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write-stream/disp32 e8/call write-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(out, Newline) # write(out, Newline)
# push args # . . push args
68/push Newline/imm32 68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, "b8/copy-to-EAX 1/imm32/exit") # EAX = write(out, "b8/copy-to-EAX 1/imm32/exit")
# push args # . . push args
68/push "b8/copy-to-EAX 1/imm32/exit"/imm32 68/push "b8/copy-to-EAX 1/imm32/exit"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, Newline) # EAX = write(out, Newline)
# push args # . . push args
68/push Newline/imm32 68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, "cd/syscall 0x80/imm8") # EAX = write(out, "cd/syscall 0x80/imm8")
# push args # . . push args
68/push "cd/syscall 0x80/imm8"/imm32 68/push "cd/syscall 0x80/imm8"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# EAX = write(out, Newline) # EAX = write(out, Newline)
# push args # . . push args
68/push Newline/imm32 68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# restore registers # . restore registers
59/pop-to-ECX 59/pop-to-ECX
58/pop-to-EAX 58/pop-to-EAX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
@ -216,30 +216,30 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
# get-char in each iteration of the loop. (Thereby demonstrating that it's # get-char in each iteration of the loop. (Thereby demonstrating that it's
# not the right interface for us. But we'll keep it just to follow Crenshaw.) # not the right interface for us. But we'll keep it just to follow Crenshaw.)
# #
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# EAX = is-digit?(Look) # EAX = is-digit?(Look)
# push args # . . push args
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
# call # . . call
e8/call is-digit?/disp32 e8/call is-digit?/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# if EAX == 0 error # if EAX == 0 error
3d/compare-EAX 0/imm32 3d/compare-EAX 0/imm32
75/jump-if-not-equal $get-num:main/disp8 75/jump-if-not-equal $get-num:main/disp8
# expected(ed, err, "integer") # expected(ed, err, "integer")
# push args # . . push args
68/push "integer"/imm32 68/push "integer"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20)
# call # . . call
e8/call expected/disp32 # never returns e8/call expected/disp32 # never returns
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
$get-num:main: $get-num:main:
# save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
52/push-EDX 52/push-EDX
@ -260,13 +260,13 @@ $get-num:loop:
3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX 3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX
7d/jump-if-lesser $get-num:loop-stage2/disp8 7d/jump-if-lesser $get-num:loop-stage2/disp8
# error(ed, err, "get-num: too many digits in number") # TODO: show full number # error(ed, err, "get-num: too many digits in number") # TODO: show full number
# push args # . . push args
68/push "get-num: too many digits in number"/imm32 68/push "get-num: too many digits in number"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x14/disp8 . # push *(EBP+20)
# call # . . call
e8/call error/disp32 # never returns e8/call error/disp32 # never returns
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
$get-num:loop-stage2: $get-num:loop-stage2:
# out->data[out->write] = LSB(Look) # out->data[out->write] = LSB(Look)
@ -276,18 +276,18 @@ $get-num:loop-stage2:
# ++out->write # ++out->write
41/increment-ECX 41/increment-ECX
# Look = get-char(in) # Look = get-char(in)
# push args # . . push args
56/push-ESI 56/push-ESI
# call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# EAX = is-digit?(Look) # EAX = is-digit?(Look)
# push args # . . push args
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
# call # . . call
e8/call is-digit?/disp32 e8/call is-digit?/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# if EAX loop # if EAX loop
3d/compare-EAX 0/imm32 3d/compare-EAX 0/imm32
@ -295,14 +295,14 @@ $get-num:loop-stage2:
$get-num:loop-end: $get-num:loop-end:
# persist necessary variables from registers # persist necessary variables from registers
89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI 89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI
# restore registers # . restore registers
5f/pop-to-EDI 5f/pop-to-EDI
5e/pop-to-ESI 5e/pop-to-ESI
5b/pop-to-EBX 5b/pop-to-EBX
5a/pop-to-EDX 5a/pop-to-EDX
59/pop-to-ECX 59/pop-to-ECX
58/pop-to-EAX 58/pop-to-EAX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
@ -314,43 +314,43 @@ test-get-num-reads-single-digit:
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## clear all streams ## clear all streams
# clear-stream(_test-stream) # clear-stream(_test-stream)
# push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4) # clear-stream(_test-buffered-file+4)
# push args # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
50/push-EAX 50/push-EAX
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-output-stream) # clear-stream(_test-output-stream)
# push args # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-error-stream) # clear-stream(_test-error-stream)
# push args # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in' ## initialize 'in'
# write(_test-stream, "3") # write(_test-stream, "3")
# push args # . . push args
68/push "3"/imm32 68/push "3"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed' ## initialize exit-descriptor 'ed'
# allocate on stack # allocate on stack
@ -359,41 +359,41 @@ test-get-num-reads-single-digit:
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX 8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
# size the exit-descriptor for the call to get-num below # size the exit-descriptor for the call to get-num below
# tailor-exit-descriptor(ed, 16) # tailor-exit-descriptor(ed, 16)
# push args # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
# call # . . call
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## prime the pump ## prime the pump
# get-char(_test-buffered-file) # get-char(_test-buffered-file)
# push args # . . push args
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## get-num(in, out, err, ed) ## get-num(in, out, err, ed)
# push args # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# call # . . call
e8/call get-num/disp32 e8/call get-num/disp32
## registers except ESP may be clobbered at this point ## registers except ESP may be clobbered at this point
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# check-ints-equal(*_test-output-stream.data, '3') # check-ints-equal(*_test-output-stream.data, '3')
# push args # . . push args
68/push "F - test-get-num-reads-single-digit"/imm32 68/push "F - test-get-num-reads-single-digit"/imm32
68/push 0x33/imm32 68/push 0x33/imm32
b8/copy-to-EAX _test-output-stream/imm32 b8/copy-to-EAX _test-output-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# reclaim locals # reclaim locals
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
@ -407,43 +407,43 @@ test-get-num-aborts-on-non-digit-in-Look:
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## clear all streams ## clear all streams
# clear-stream(_test-stream) # clear-stream(_test-stream)
# push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4) # clear-stream(_test-buffered-file+4)
# push args # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
50/push-EAX 50/push-EAX
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-output-stream) # clear-stream(_test-output-stream)
# push args # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-error-stream) # clear-stream(_test-error-stream)
# push args # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in' ## initialize 'in'
# write(_test-stream, "3") # write(_test-stream, "3")
# push args # . . push args
68/push "3"/imm32 68/push "3"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed' ## initialize exit-descriptor 'ed'
# allocate on stack # allocate on stack
@ -452,35 +452,35 @@ test-get-num-aborts-on-non-digit-in-Look:
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX 8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
# size the exit-descriptor for the call to get-num below # size the exit-descriptor for the call to get-num below
# tailor-exit-descriptor(ed, 16) # tailor-exit-descriptor(ed, 16)
# push args # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
# call # . . call
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## don't initialize Look ## don't initialize Look
## get-num(in, out, err, ed) ## get-num(in, out, err, ed)
# push args # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# call # . . call
e8/call get-num/disp32 e8/call get-num/disp32
## registers except ESP may be clobbered at this point ## registers except ESP may be clobbered at this point
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
## check that get-num tried to call exit(1) ## check that get-num tried to call exit(1)
# check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 # check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1
# push args # . . push args
68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32
68/push 2/imm32 68/push 2/imm32
# push ed->value # push ed->value
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# reclaim locals # reclaim locals
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
@ -494,43 +494,43 @@ test-get-num-reads-multiple-digits:
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## clear all streams ## clear all streams
# clear-stream(_test-stream) # clear-stream(_test-stream)
# push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4) # clear-stream(_test-buffered-file+4)
# push args # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
50/push-EAX 50/push-EAX
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-output-stream) # clear-stream(_test-output-stream)
# push args # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-error-stream) # clear-stream(_test-error-stream)
# push args # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in' ## initialize 'in'
# write(_test-stream, "3456 x") # write(_test-stream, "3456 x")
# push args # . . push args
68/push "3456"/imm32 68/push "3456"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed' ## initialize exit-descriptor 'ed'
# allocate on stack # allocate on stack
@ -539,41 +539,41 @@ test-get-num-reads-multiple-digits:
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX 8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
# size the exit-descriptor for the call to get-num below # size the exit-descriptor for the call to get-num below
# tailor-exit-descriptor(ed, 16) # tailor-exit-descriptor(ed, 16)
# push args # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
# call # . . call
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## prime the pump ## prime the pump
# get-char(_test-buffered-file) # get-char(_test-buffered-file)
# push args # . . push args
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## get-num(in, out, err, ed) ## get-num(in, out, err, ed)
# push args # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# call # . . call
e8/call get-num/disp32 e8/call get-num/disp32
## registers except ESP may be clobbered at this point ## registers except ESP may be clobbered at this point
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# check-ints-equal(*_test-output-stream.data, '3456') # check-ints-equal(*_test-output-stream.data, '3456')
# push args # . . push args
68/push "F - test-get-num-reads-multiple-digits"/imm32 68/push "F - test-get-num-reads-multiple-digits"/imm32
68/push 0x36353433/imm32 68/push 0x36353433/imm32
b8/copy-to-EAX _test-output-stream/imm32 b8/copy-to-EAX _test-output-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# reclaim locals # reclaim locals
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
@ -587,43 +587,43 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
## clear all streams ## clear all streams
# clear-stream(_test-stream) # clear-stream(_test-stream)
# push args # . . push args
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-buffered-file+4) # clear-stream(_test-buffered-file+4)
# push args # . . push args
b8/copy-to-EAX _test-buffered-file/imm32 b8/copy-to-EAX _test-buffered-file/imm32
05/add-to-EAX 4/imm32 05/add-to-EAX 4/imm32
50/push-EAX 50/push-EAX
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-output-stream) # clear-stream(_test-output-stream)
# push args # . . push args
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# clear-stream(_test-error-stream) # clear-stream(_test-error-stream)
# push args # . . push args
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
# call # . . call
e8/call clear-stream/disp32 e8/call clear-stream/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## initialize 'in' ## initialize 'in'
# write(_test-stream, "3456 x") # write(_test-stream, "3456 x")
# push args # . . push args
68/push "3456 x"/imm32 68/push "3456 x"/imm32
68/push _test-stream/imm32 68/push _test-stream/imm32
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## initialize exit-descriptor 'ed' ## initialize exit-descriptor 'ed'
# allocate on stack # allocate on stack
@ -632,41 +632,41 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX 8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX
# size the exit-descriptor for the call to get-num below # size the exit-descriptor for the call to get-num below
# tailor-exit-descriptor(ed, 16) # tailor-exit-descriptor(ed, 16)
# push args # . . push args
68/push 0x10/imm32/nbytes-of-args-for-get-num 68/push 0x10/imm32/nbytes-of-args-for-get-num
50/push-EAX/ed 50/push-EAX/ed
# call # . . call
e8/call tailor-exit-descriptor/disp32 e8/call tailor-exit-descriptor/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
## prime the pump ## prime the pump
# get-char(_test-buffered-file) # get-char(_test-buffered-file)
# push args # . . push args
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# call # . . call
e8/call get-char/disp32 e8/call get-char/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
## get-num(in, out, err, ed) ## get-num(in, out, err, ed)
# push args # . . push args
50/push-EAX/ed 50/push-EAX/ed
68/push _test-error-stream/imm32 68/push _test-error-stream/imm32
68/push _test-output-stream/imm32 68/push _test-output-stream/imm32
68/push _test-buffered-file/imm32 68/push _test-buffered-file/imm32
# call # . . call
e8/call get-num/disp32 e8/call get-num/disp32
## registers except ESP may be clobbered at this point ## registers except ESP may be clobbered at this point
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
# check-ints-equal(*_test-output-stream.data, '3456') # check-ints-equal(*_test-output-stream.data, '3456')
# push args # . . push args
68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32 68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32
68/push 0x36353433/imm32 68/push 0x36353433/imm32
b8/copy-to-EAX _test-output-stream/imm32 b8/copy-to-EAX _test-output-stream/imm32
ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12)
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
# reclaim locals # reclaim locals
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
@ -677,119 +677,119 @@ test-get-num-reads-multiple-digits-followed-by-nondigit:
# write(f, "Error: "+s+" expected\n") then stop(ed, 1) # write(f, "Error: "+s+" expected\n") then stop(ed, 1)
expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void> expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# write(f, "Error: ") # write(f, "Error: ")
# push args # . . push args
68/push "Error: "/imm32 68/push "Error: "/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(f, s) # write(f, s)
# push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(f, " expected") # write(f, " expected")
# push args # . . push args
68/push " expected"/imm32 68/push " expected"/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(f, Newline) # write(f, Newline)
# push args # . . push args
68/push Newline/imm32 68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# stop(ed, 1) # stop(ed, 1)
# push args # . . push args
68/push 1/imm32 68/push 1/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call # . . call
e8/call stop/disp32 e8/call stop/disp32
## should never get past this point ## should never get past this point
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
# write(f, "Error: "+s+"\n") then stop(ed, 1) # write(f, "Error: "+s+"\n") then stop(ed, 1)
error: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void> error: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void>
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# write(f, "Error: ") # write(f, "Error: ")
# push args # . . push args
68/push "Error: "/imm32 68/push "Error: "/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(f, s) # write(f, s)
# push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x10/disp8 . # push *(EBP+16)
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# write(f, Newline) # write(f, Newline)
# push args # . . push args
68/push Newline/imm32 68/push Newline/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# call # . . call
e8/call write/disp32 e8/call write/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# stop(ed, 1) # stop(ed, 1)
# push args # . . push args
68/push 1/imm32 68/push 1/imm32
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 . # push *(EBP+8)
# call # . . call
e8/call stop/disp32 e8/call stop/disp32
## should never get past this point ## should never get past this point
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
# read a byte from 'f', and store it in 'Look' # read a byte from 'f', and store it in 'Look'
get-char: # f : (address buffered-file) -> <void> get-char: # f : (address buffered-file) -> <void>
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
50/push-EAX 50/push-EAX
# read-byte(f) # read-byte(f)
# push args # . . push args
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call # . . call
e8/call read-byte/disp32 e8/call read-byte/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# save EAX to Look # save EAX to Look
89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look
# restore registers # . restore registers
58/pop-to-EAX 58/pop-to-EAX
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
is-digit?: # c : int -> bool/EAX is-digit?: # c : int -> bool/EAX
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# EAX = false # EAX = false
@ -803,7 +803,7 @@ is-digit?: # c : int -> bool/EAX
# otherwise return true # otherwise return true
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
$is-digit?:end: $is-digit?:end:
# epilog # . epilog
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
@ -833,4 +833,4 @@ _test-error-stream:
# data # data
00 00 00 00 00 00 00 00 # 8 bytes 00 00 00 00 00 00 00 00 # 8 bytes
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

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

View File

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

View File

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

View File

@ -15,9 +15,9 @@
# would cause tests to not run, rather than to fail as we'd like.) # would cause tests to not run, rather than to fail as we'd like.)
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: # main:
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
@ -29,10 +29,10 @@
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
51/push-ECX 51/push-ECX
52/push-EDX 52/push-EDX
53/push-EBX 53/push-EBX
@ -97,7 +97,7 @@ $kernel-string-equal:false:
b8/copy-to-EAX 0/imm32 b8/copy-to-EAX 0/imm32
$kernel-string-equal:end: $kernel-string-equal:end:
# restore registers # . restore registers
5f/pop-to-EDI 5f/pop-to-EDI
5e/pop-to-ESI 5e/pop-to-ESI
5b/pop-to-EBX 5b/pop-to-EBX
@ -112,141 +112,141 @@ $kernel-string-equal:end:
test-compare-null-kernel-string-with-empty-array: test-compare-null-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "") # EAX = kernel-string-equal(Null-kernel-string, "")
# push args # . . push args
68/push ""/imm32 68/push ""/imm32
68/push Null-kernel-string/imm32 68/push Null-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 1, msg) # . . call check-ints-equal(EAX, 1, msg)
# push args # . . push args
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32 68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-null-kernel-string-with-non-empty-array: test-compare-null-kernel-string-with-non-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "Abc") # EAX = kernel-string-equal(Null-kernel-string, "Abc")
# push args # . . push args
68/push "Abc"/imm32 68/push "Abc"/imm32
68/push Null-kernel-string/imm32 68/push Null-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0, msg) # . . call check-ints-equal(EAX, 0, msg)
# push args # . . push args
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32 68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-equal-array: test-compare-kernel-string-with-equal-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Abc") # EAX = kernel-string-equal(Abc-kernel-string, "Abc")
# push args # . . push args
68/push "Abc"/imm32 68/push "Abc"/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 1, msg) # . . call check-ints-equal(EAX, 1, msg)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 1/imm32/true 68/push 1/imm32/true
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-inequal-array: test-compare-kernel-string-with-inequal-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Adc") # EAX = kernel-string-equal(Abc-kernel-string, "Adc")
# push args # . . push args
68/push "Adc"/imm32 68/push "Adc"/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0, msg) # . . call check-ints-equal(EAX, 0, msg)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-empty-array: test-compare-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Abc-kernel-string, "") # EAX = kernel-string-equal(Abc-kernel-string, "")
# push args # . . push args
68/push ""/imm32 68/push ""/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0) # . . call check-ints-equal(EAX, 0)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-equal-array"/imm32 68/push "F - test-compare-kernel-string-with-equal-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-shorter-array: test-compare-kernel-string-with-shorter-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Ab") # EAX = kernel-string-equal(Abc-kernel-string, "Ab")
# push args # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0) # . . call check-ints-equal(EAX, 0)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32 68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
test-compare-kernel-string-with-longer-array: test-compare-kernel-string-with-longer-array:
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd") # EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
# push args # . . push args
68/push "Abcd"/imm32 68/push "Abcd"/imm32
68/push Abc-kernel-string/imm32 68/push Abc-kernel-string/imm32
# call # . . call
e8/call kernel-string-equal/disp32 e8/call kernel-string-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# call check-ints-equal(EAX, 0) # . . call check-ints-equal(EAX, 0)
# push args # . . push args
68/push "F - test-compare-kernel-string-with-longer-array"/imm32 68/push "F - test-compare-kernel-string-with-longer-array"/imm32
68/push 0/imm32/false 68/push 0/imm32/false
50/push-EAX 50/push-EAX
# call # . . call
e8/call check-ints-equal/disp32 e8/call check-ints-equal/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
c3/return c3/return
@ -254,10 +254,10 @@ test-compare-kernel-string-with-longer-array:
# print msg to stderr if a != b, otherwise print "." # print msg to stderr if a != b, otherwise print "."
check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
51/push-ECX 51/push-ECX
53/push-EBX 53/push-EBX
# load args into EAX, EBX and ECX # load args into EAX, EBX and ECX
@ -267,11 +267,11 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
75/jump-if-unequal $check-ints-equal:else/disp8 75/jump-if-unequal $check-ints-equal:else/disp8
# print('.') # print('.')
# push args # . . push args
68/push "."/imm32 68/push "."/imm32
# call # . . call
e8/call write-stderr/disp32 e8/call write-stderr/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# return # return
eb/jump $check-ints-equal:end/disp8 eb/jump $check-ints-equal:end/disp8
@ -280,21 +280,21 @@ $check-ints-equal:else:
# copy msg into ECX # copy msg into ECX
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX 8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX
# print(ECX) # print(ECX)
# push args # . . push args
51/push-ECX 51/push-ECX
# call # . . call
e8/call write-stderr/disp32 e8/call write-stderr/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# print newline # print newline
# push args # . . push args
68/push Newline/imm32 68/push Newline/imm32
# call # . . call
e8/call write-stderr/disp32 e8/call write-stderr/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
$check-ints-equal:end: $check-ints-equal:end:
# restore registers # . restore registers
5b/pop-to-EBX 5b/pop-to-EBX
59/pop-to-ECX 59/pop-to-ECX
# end # end
@ -303,10 +303,10 @@ $check-ints-equal:end:
c3/return c3/return
write-stderr: # s : (address array byte) -> <void> write-stderr: # s : (address array byte) -> <void>
# prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# save registers # . save registers
50/push-EAX 50/push-EAX
51/push-ECX 51/push-ECX
52/push-EDX 52/push-EDX
@ -323,7 +323,7 @@ write-stderr: # s : (address array byte) -> <void>
# syscall # syscall
b8/copy-to-EAX 4/imm32/write b8/copy-to-EAX 4/imm32/write
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# restore registers # . restore registers
5b/pop-to-EBX 5b/pop-to-EBX
5a/pop-to-EDX 5a/pop-to-EDX
59/pop-to-ECX 59/pop-to-ECX
@ -347,4 +347,4 @@ Null-kernel-string:
Abc-kernel-string: Abc-kernel-string:
41/A 62/b 63/c 00/null 41/A 62/b 63/c 00/null
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

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

View File

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

View File

@ -8,9 +8,9 @@
# 55 # 55
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# result: EBX = 0 # result: EBX = 0
bb/copy-to-EBX 0/imm32 bb/copy-to-EBX 0/imm32
@ -33,4 +33,4 @@ $exit:
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

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

View File

@ -5,9 +5,9 @@
# $ subx run examples/ex5 # $ subx run examples/ex5
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# main: # main:
# allocate x on the stack # allocate x on the stack
@ -39,4 +39,4 @@
b8/copy-to-EAX 1/imm32/exit b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

@ -6,9 +6,9 @@
# Hello, world! # Hello, world!
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# syscall(write, stdout, X, size) # syscall(write, stdout, X, size)
# fd = 1 (stdout) # fd = 1 (stdout)
@ -33,4 +33,4 @@ X: # string to print
48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a 00 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0a 00
# H e l l o , ␣ w o r l d ! newline null # H e l l o , ␣ w o r l d ! newline null
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0

View File

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

View File

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

View File

@ -17,20 +17,20 @@
# Locals start from ESP-4 downwards. # Locals start from ESP-4 downwards.
== code == code
# instruction effective address operand displacement immediate # instruction effective address register displacement immediate
# op subop mod rm32 base index scale r32 # . op subop mod rm32 base index scale r32
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# prolog # . prolog
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# call ascii-difference(argv[1], argv[2]) # . . call ascii-difference(argv[1], argv[2])
# push argv[2] # push argv[2]
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
# push argv[1] # push argv[1]
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8) ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
# call # . . call
e8/call ascii-difference/disp32 e8/call ascii-difference/disp32
# discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
# exit(EAX) # exit(EAX)
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
@ -48,4 +48,4 @@ ascii-difference: # (s1, s2) : null-terminated ascii strings
29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX 29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX
c3/return c3/return
# vim:nowrap:textwidth=0 # . . vim:nowrap:textwidth=0