4961
This commit is contained in:
parent
1ab48a69cc
commit
1639687ba0
|
@ -32,7 +32,7 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> <void>
|
|||
# load first 2 args into EAX and EBX
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX
|
||||
# if EAX == EBX success
|
||||
# if (EAX == EBX) success
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
|
||||
75/jump-if-unequal $check-ints-equal:else/disp8
|
||||
# . _write(2/stderr, '.')
|
||||
|
|
|
@ -30,19 +30,26 @@
|
|||
# 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
|
||||
# pseudocode:
|
||||
# initialize n = b->length
|
||||
# initialize s1 = s
|
||||
# initialize s2 = b->data
|
||||
# n = benchmark->length
|
||||
# s1 = s
|
||||
# s2 = benchmark->data
|
||||
# i = 0
|
||||
# for (i = 0; i < n; ++n)
|
||||
# while (i < n)
|
||||
# c1 = *s1
|
||||
# c2 = *s2
|
||||
# if c1 == 0
|
||||
# return false
|
||||
# if c1 != c2
|
||||
# return false
|
||||
# if (c1 == 0) return false
|
||||
# if (c1 != c2) return false
|
||||
# ++s1, ++s2, ++i
|
||||
# return *s1 == 0
|
||||
#
|
||||
# registers:
|
||||
# i: ECX
|
||||
# n: EDX
|
||||
# s1: EDI
|
||||
# s2: ESI
|
||||
# c1: EAX
|
||||
# c2: EBX
|
||||
#
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -52,24 +59,25 @@ kernel-string-equal?: # s : null-terminated ascii string, benchmark : length-pr
|
|||
53/push-EBX
|
||||
56/push-ESI
|
||||
57/push-EDI
|
||||
# initialize s into EDI
|
||||
# s1/EDI = s
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI
|
||||
# initialize benchmark length n into EDX
|
||||
# n/EDX = benchmark->length
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 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
|
||||
# initialize benchmark data into ESI
|
||||
# s2/ESI = benchmark->data
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI
|
||||
81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 4/imm32 # add to ESI
|
||||
# initialize loop counter i into ECX
|
||||
# i/ECX = c1/EAX = c2/EBX = 0
|
||||
b9/copy-to-ECX 0/imm32/exit
|
||||
# while (i/ECX < n/EDX)
|
||||
$kernel-string-equal?:loop:
|
||||
39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX
|
||||
74/jump-if-equal $kernel-string-equal?:break/disp8
|
||||
# c1/EAX, c2/EBX = *s, *benchmark
|
||||
b8/copy-to-EAX 0/imm32
|
||||
8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
$kernel-string-equal?:loop:
|
||||
# if (i >= n) break
|
||||
39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX
|
||||
7d/jump-if-greater-or-equal $kernel-string-equal?:break/disp8
|
||||
# c1 = *s1
|
||||
8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX
|
||||
# c2 = *s2
|
||||
8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX
|
||||
# if (c1 == 0) return false
|
||||
3d/compare-EAX 0/imm32
|
||||
|
@ -77,22 +85,21 @@ $kernel-string-equal?:loop:
|
|||
# if (c1 != c2) return false
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX
|
||||
75/jump-if-not-equal $kernel-string-equal?:false/disp8
|
||||
# ++s1, ++s2, ++i
|
||||
# ++i
|
||||
41/inc-ECX
|
||||
46/inc-ESI
|
||||
# ++s1
|
||||
47/inc-EDI
|
||||
# end while
|
||||
# ++s2
|
||||
46/inc-ESI
|
||||
eb/jump $kernel-string-equal?:loop/disp8
|
||||
$kernel-string-equal?:break:
|
||||
# if (*s/EDI == 0) return true
|
||||
b8/copy-to-EAX 0/imm32
|
||||
# return *s1 == 0
|
||||
8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX
|
||||
3d/compare-EAX 0/imm32
|
||||
75/jump-if-not-equal $kernel-string-equal?:false/disp8
|
||||
$kernel-string-equal?:true:
|
||||
b8/copy-to-EAX 1/imm32
|
||||
eb/jump $kernel-string-equal?:end/disp8
|
||||
# return false
|
||||
$kernel-string-equal?:false:
|
||||
b8/copy-to-EAX 0/imm32
|
||||
$kernel-string-equal?:end:
|
||||
|
@ -253,6 +260,7 @@ test-compare-kernel-string-with-longer-array:
|
|||
|
||||
Null-kernel-string:
|
||||
00/null
|
||||
|
||||
_test-Abc-kernel-string:
|
||||
41/A 62/b 63/c 00/null
|
||||
|
||||
|
|
|
@ -13,18 +13,27 @@
|
|||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
string-equal?: # s : string, benchmark : string -> EAX : boolean
|
||||
string-equal?: # s : (address string), benchmark : (address string) -> EAX : boolean
|
||||
# pseudocode:
|
||||
# if s->length != b->length return false
|
||||
# for i = 0; i < s->length; ++i
|
||||
# if s[i] != b[i] return false
|
||||
# lens = s->length
|
||||
# if (lens != benchmark->length) return false
|
||||
# i = 0
|
||||
# currs = s->data
|
||||
# currb = benchmark->data
|
||||
# while (i < s->length)
|
||||
# c1 = *currs
|
||||
# c2 = *currb
|
||||
# if (c1 != c2) return false
|
||||
# ++i, ++currs, ++currb
|
||||
# return true
|
||||
#
|
||||
# registers:
|
||||
# i: ECX
|
||||
# s->length: EDX
|
||||
# b->length: EBX
|
||||
# b[i]: EBX
|
||||
# s[i]: EAX
|
||||
# lens: EDX
|
||||
# currs: EAX
|
||||
# currb: EBX
|
||||
# c1: ESI
|
||||
# c2: EDI
|
||||
#
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
|
@ -34,17 +43,16 @@ string-equal?: # s : string, benchmark : string -> EAX : boolean
|
|||
52/push-EDX
|
||||
53/push-EBX
|
||||
56/push-ESI
|
||||
# var s/EAX : (address array byte)
|
||||
# EAX = s
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX
|
||||
# var benchmark/EBX : (address array byte)
|
||||
# EBX = benchmark
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX
|
||||
# if s->length != b->length return false
|
||||
# EDX = s->length
|
||||
# lens/EDX = s->length
|
||||
8b/copy 0/mod/indirect 0/rm32/EAX . . . 2/r32/EDX . . # copy *EAX to EDX
|
||||
# compare s->length and b->length
|
||||
$string-equal?:lengths:
|
||||
# if (lens != benchmark->length) return false
|
||||
39/compare 0/mod/indirect 3/rm32/EBX . . . 2/r32/EDX . . # compare *EBX with EDX
|
||||
75/jump-if-not-equal $string-equal?:false/disp8
|
||||
$string-equal?:lengths:
|
||||
# var i/ECX : int = 0
|
||||
b9/copy-to-ECX 0/imm32
|
||||
# EBX = &b[i]
|
||||
|
@ -52,7 +60,7 @@ $string-equal?:lengths:
|
|||
# EAX = &s[i]
|
||||
40/inc-EAX
|
||||
$string-equal?:loop:
|
||||
# if i >= s->length return true
|
||||
# if (i >= lens) return true
|
||||
39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX
|
||||
7d/jump-if-greater-or-equal $string-equal?:true/disp8
|
||||
# if b[i] != s[i] return false
|
||||
|
@ -63,16 +71,15 @@ $string-equal?:loop:
|
|||
75/jump-if-not-equal $string-equal?:false/disp8
|
||||
# ++i
|
||||
41/inc-ECX
|
||||
# ++c1
|
||||
40/inc-EAX
|
||||
# ++c2
|
||||
43/inc-EBX
|
||||
# loop
|
||||
eb/jump $string-equal?:loop/disp8
|
||||
$string-equal?:true:
|
||||
# return true
|
||||
b8/copy-to-EAX 1/imm32
|
||||
eb/jump $string-equal?:end/disp8
|
||||
$string-equal?:false:
|
||||
# return false
|
||||
b8/copy-to-EAX 0/imm32
|
||||
$string-equal?:end:
|
||||
# . restore registers
|
||||
|
|
|
@ -42,7 +42,7 @@ clear-stream: # f : (address stream) -> <void>
|
|||
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 0xc/imm32 # add to EAX
|
||||
# while (true)
|
||||
$clear-stream:loop:
|
||||
# if EAX >= ECX break
|
||||
# if (EAX >= ECX) break
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX with ECX
|
||||
7d/jump-if-greater-or-equal $clear-stream:end/disp8
|
||||
# *EAX = 0
|
||||
|
@ -76,3 +76,5 @@ $rewind-stream:end:
|
|||
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
# . . vim:nowrap:textwidth=0
|
||||
|
|
|
@ -99,7 +99,7 @@ trace: # t : (address trace-stream), line : string
|
|||
e8/call _append-3/disp32
|
||||
# . . discard args
|
||||
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
|
||||
74/jump-if-equal $trace:end/disp8
|
||||
# t->write += EAX
|
||||
|
@ -153,9 +153,8 @@ clear-trace-stream: # t : (address trace-stream)
|
|||
c7 0/subop/copy 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 0/imm32 # copy to *(EAX+4)
|
||||
# EAX = t->data
|
||||
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 0xc/imm32 # add to EAX
|
||||
# while (true)
|
||||
$clear-trace-stream:loop:
|
||||
# if EAX >= ECX break
|
||||
# if (EAX >= ECX) break
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX with ECX
|
||||
7d/jump-if-greater-or-equal $clear-trace-stream:end/disp8
|
||||
# *EAX = 0
|
||||
|
@ -328,18 +327,20 @@ _append-4: # out : address, outend : address, in : address, inend : address ->
|
|||
# ECX = inend
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 0x14/disp8 . # copy *(EBP+20) to ECX
|
||||
$_append-4:loop:
|
||||
# if ESI/in >= ECX/inend break
|
||||
# if (in >= inend) break
|
||||
39/compare 3/mod/direct 6/rm32/ESI . . . 1/r32/ECX . . # compare ESI with ECX
|
||||
7d/jump-if-greater-or-equal $_append-4:end/disp8
|
||||
# if EDI/out >= EDX/outend break (for now silently ignore filled up buffer)
|
||||
# if (out >= outend) break # for now silently ignore filled up buffer
|
||||
39/compare 3/mod/direct 7/rm32/EDI . . . 2/r32/EDX . . # compare EDI with EDX
|
||||
7d/jump-if-greater-or-equal $_append-4:end/disp8
|
||||
# copy one byte from ESI/in to EDI/out
|
||||
# *out = *in
|
||||
8a/copy-byte 0/mod/indirect 6/rm32/ESI . . . 3/r32/BL . . # copy byte at *ESI to BL
|
||||
88/copy-byte 0/mod/indirect 7/rm32/EDI . . . 3/r32/BL . . # copy byte at BL to *EDI
|
||||
# updates
|
||||
# ++num_bytes_appended
|
||||
40/increment-EAX
|
||||
# ++in
|
||||
46/increment-ESI
|
||||
# ++out
|
||||
47/increment-EDI
|
||||
eb/jump $_append-4:loop/disp8
|
||||
$_append-4:end:
|
||||
|
|
|
@ -32,7 +32,7 @@ write: # f : fd or (address stream), s : (address array byte) -> <void>
|
|||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# if (f < 0x08000000) _write(f, s), return # f can't be a user-mode address, so treat it as a kernel file descriptor
|
||||
# if (f < 0x08000000) _write(f, s) and return # f can't be a user-mode address, so treat it as a kernel file descriptor
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x08000000/imm32 # compare *(EBP+8)
|
||||
7d/jump-if-greater-or-equal $write:fake/disp8
|
||||
# . . push args
|
||||
|
|
|
@ -32,7 +32,7 @@ stream-data-equal?: # f : (address stream), s : (address string) -> EAX : boole
|
|||
81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 0xc/imm32 # add to ESI
|
||||
# EDI = s
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI
|
||||
# if (f->write != s->length) return false;
|
||||
# if (f->write != s->length) return false
|
||||
39/compare 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # compare *EDI and EAX
|
||||
75/jump-if-not-equal $stream-data-equal?:false/disp8
|
||||
# currs/EDI = s->data
|
||||
|
@ -235,25 +235,25 @@ next-stream-line-equal?: # f : (address stream), s : (address string) -> EAX :
|
|||
# pseudocode:
|
||||
# currf = f->read # bound: f->write
|
||||
# currs = 0 # bound : s->length
|
||||
# while true
|
||||
# if currf >= f->write
|
||||
# while true:
|
||||
# if (currf >= f->write)
|
||||
# return currs >= s->length
|
||||
# if f[currf] == '\n'
|
||||
# if (f[currf] == '\n')
|
||||
# ++currf
|
||||
# return currs >= s->length
|
||||
# if currs >= s->length return false # the current line of f still has data to match
|
||||
# if f[currf] != s[currs] return false
|
||||
# if (currs >= s->length) return false # the current line of f still has data to match
|
||||
# if (f[currf] != s[currs]) return false
|
||||
# ++currf
|
||||
# ++currs
|
||||
#
|
||||
# collapsing the two branches that can return true:
|
||||
# currf = f->read # bound: f->write
|
||||
# currs = 0 # bound : s->length
|
||||
# while true
|
||||
# if currf >= f->write break
|
||||
# if f[currf] == '\n' break
|
||||
# if currs >= s->length return false # the current line of f still has data to match
|
||||
# if f[currf] != s[currs] return false
|
||||
# while true:
|
||||
# if (currf >= f->write) break
|
||||
# if (f[currf] == '\n') break
|
||||
# if (currs >= s->length) return false # the current line of f still has data to match
|
||||
# if (f[currf] != s[currs]) return false
|
||||
# ++currf
|
||||
# ++currs
|
||||
# ++currf # skip '\n'
|
||||
|
@ -261,12 +261,12 @@ next-stream-line-equal?: # f : (address stream), s : (address string) -> EAX :
|
|||
# Here the final `++currf` is sometimes unnecessary (if we're already at the end of the stream)
|
||||
#
|
||||
# registers:
|
||||
# f : ESI
|
||||
# s : EDI
|
||||
# currf : ECX
|
||||
# currs : EDX
|
||||
# f[currf] : EAX
|
||||
# s[currs] : EBX
|
||||
# f: ESI
|
||||
# s: EDI
|
||||
# currf: ECX
|
||||
# currs: EDX
|
||||
# f[currf]: EAX
|
||||
# s[currs]: EBX
|
||||
#
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
|
@ -312,7 +312,7 @@ $next-stream-line-equal?:loop:
|
|||
$next-stream-line-equal?:break:
|
||||
# ++currf
|
||||
41/increment-ECX
|
||||
# if currs >= s->length return true
|
||||
# if (currs >= s->length) return true
|
||||
3b/compare 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # compare EDX with *EDI
|
||||
7c/jump-if-lesser $next-stream-line-equal?:false/disp8
|
||||
$next-stream-line-equal?:true:
|
||||
|
|
|
@ -100,19 +100,20 @@ stop: # ed : (address exit-descriptor), value : int
|
|||
# no prolog; one way or another, we're going to clobber registers
|
||||
# EAX = ed
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX 4/disp8 . # copy *(ESP+4) to EAX
|
||||
# exit(value) if ed->target == 0
|
||||
# if (ed->target == 0) really exit
|
||||
81 7/subop/compare 0/mod/indirect 0/rm32/EAX . . . . . 0/imm32 # compare *EAX
|
||||
75/jump-if-not-equal $stop:fake/disp8
|
||||
# syscall(exit, value)
|
||||
# . syscall(exit, value)
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 3/r32/EBX 8/disp8 . # copy *(ESP+8) to EBX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
$stop:fake:
|
||||
# otherwise:
|
||||
# ed->value = value+1
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(ESP+8) to ECX
|
||||
41/inc-ECX
|
||||
89/copy 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy ECX to *(EAX+4)
|
||||
# non-local jump to ed->target
|
||||
# perform a non-local jump to ed->target
|
||||
8b/copy 0/mod/indirect 0/rm32/EAX . . . 4/r32/ESP . . # copy *EAX to ESP
|
||||
$stop:end:
|
||||
c3/return # doesn't return to caller
|
||||
|
|
|
@ -74,7 +74,7 @@ read-byte: # f : (address buffered-file) -> byte-or-eof/EAX
|
|||
e8/call read/disp32
|
||||
# . . discard args
|
||||
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
|
||||
75/jump-if-not-equal $read-byte:from-stream/disp8
|
||||
b8/copy-to-EAX 0xffffffff/imm32
|
||||
|
|
|
@ -71,7 +71,7 @@ $is-hex-int?:loop:
|
|||
e8/call is-hex-digit?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# if EAX == false return false
|
||||
# if (EAX == false) return false
|
||||
3d/compare-with-EAX 0/imm32
|
||||
74/jump-if-equal $is-hex-int?:end/disp8
|
||||
# ++curr
|
||||
|
@ -738,7 +738,7 @@ test-hex-above-f:
|
|||
|
||||
from-hex-char: # in/EAX : byte -> out/EAX : num
|
||||
# no error checking; accepts argument in EAX
|
||||
# if EAX <= '9' return EAX - '0'
|
||||
# if (EAX <= '9') return EAX - '0'
|
||||
3d/compare-EAX 0x39/imm32/9
|
||||
7f/jump-if-greater $from-hex-char:else/disp8
|
||||
2d/subtract-from-EAX 0x30/imm32/0
|
||||
|
@ -750,7 +750,7 @@ $from-hex-char:else:
|
|||
|
||||
to-hex-char: # in/EAX : nibble -> out/EAX : byte
|
||||
# no error checking; accepts argument in EAX
|
||||
# if EAX <= 9 return EAX + '0'
|
||||
# if (EAX <= 9) return EAX + '0'
|
||||
3d/compare-EAX 0x9/imm32/9
|
||||
7f/jump-if-greater $to-hex-char:else/disp8
|
||||
05/add-to-EAX 0x30/imm32/0
|
||||
|
|
|
@ -18,8 +18,8 @@ write-buffered: # f : (address buffered-file), msg : (address array byte) -> <v
|
|||
# pseudocode:
|
||||
# in = msg->data
|
||||
# inend = &msg->data[msg->length]
|
||||
# while in < inend
|
||||
# if f->write >= f->length
|
||||
# while (in < inend)
|
||||
# if (f->write >= f->length)
|
||||
# flush(f)
|
||||
# clear-stream(f)
|
||||
# f->data[f->write] = *in
|
||||
|
|
|
@ -164,7 +164,7 @@ allocate-region: # ad : (address allocation-descriptor), n : int -> new-ad : (a
|
|||
e8/call allocate/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# if EAX == 0 abort
|
||||
# if (EAX == 0) abort
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
|
||||
74/jump-if-equal $allocate-region:abort/disp8
|
||||
# earmark 8 bytes at the start for a new allocation descriptor
|
||||
|
|
|
@ -23,7 +23,7 @@ read-line: # f : (address buffered-file), s : (address stream byte) -> eof?/EAX
|
|||
# s->data[s->write] = AL
|
||||
# ++f->read
|
||||
# ++s->write
|
||||
# if AL == '\n' break
|
||||
# if (AL == '\n') break
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -65,8 +65,8 @@ $read-line:loop:
|
|||
e8/call read/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# if f->write == 0 return true
|
||||
# . if EAX == 0 return true
|
||||
# if (f->write == 0) return true
|
||||
# . if (EAX == 0) return true
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
|
||||
75/jump-if-not-equal $read-line:from-stream/disp8
|
||||
b8/copy-to-EAX 0xffffffff/imm32
|
||||
|
@ -81,7 +81,7 @@ $read-line:from-stream:
|
|||
41/increment-ECX
|
||||
# ++s->write
|
||||
42/increment-EDX
|
||||
# if AL == '\n' return false
|
||||
# if (AL == '\n') return false
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX
|
||||
75/jump-if-not-equal $read-line:loop/disp8
|
||||
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX
|
||||
|
|
|
@ -21,7 +21,7 @@ slice-empty?: # s : (address slice) -> EAX : boolean
|
|||
51/push-ECX
|
||||
# ECX = s
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX
|
||||
# if s->start == s->end return true
|
||||
# if (s->start == s->end) return true
|
||||
# . EAX = s->start
|
||||
8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX
|
||||
# . compare EAX with s->end
|
||||
|
@ -96,6 +96,24 @@ test-slice-empty-false:
|
|||
c3/return
|
||||
|
||||
slice-equal?: # s : (address slice), p : (address string) -> EAX : boolean
|
||||
# pseudocode:
|
||||
# currs = s->start
|
||||
# maxs = s->end
|
||||
# if (maxs - currs != p->length) return false
|
||||
# currp = p->data
|
||||
# while (currs < maxs)
|
||||
# if (*currs != *currp) return false
|
||||
# ++currs
|
||||
# ++currp
|
||||
# return true
|
||||
#
|
||||
# registers:
|
||||
# EAX : *currs
|
||||
# ECX : *currp
|
||||
# EDX : currs
|
||||
# EBX : currp
|
||||
# ESI : maxs
|
||||
#
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -106,37 +124,37 @@ slice-equal?: # s : (address slice), p : (address string) -> EAX : boolean
|
|||
56/push-ESI
|
||||
# ESI = s
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI
|
||||
# curr/EDX = s->start
|
||||
# currs/EDX = s->start
|
||||
8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX
|
||||
# max/ESI = s->end
|
||||
# maxs/ESI = s->end
|
||||
8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI
|
||||
# EBX = p
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX
|
||||
# EAX = s->end - s->start
|
||||
# EAX = maxs - currs
|
||||
89/copy 3/mod/direct 0/rm32/EAX . . . 6/r32/ESI . . # copy ESI to EAX
|
||||
29/subtract 3/mod/direct 0/rm32/EAX . . . 2/r32/EDX . . # subtract EDX from EAX
|
||||
# if (EAX != p->length) return false;
|
||||
# if (EAX != p->length) return false
|
||||
39/compare 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # compare *EBX and EAX
|
||||
75/jump-if-not-equal $slice-equal?:false/disp8
|
||||
# skip p->length
|
||||
# currp/EBX = p->data
|
||||
81 0/subop/add 3/mod/direct 3/rm32/EBX . . . . . 4/imm32 # add to EBX
|
||||
# EAX = ECX = 0
|
||||
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX
|
||||
31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX
|
||||
$slice-equal?:loop:
|
||||
# if (curr >= max) return true
|
||||
# if (currs >= maxs) return true
|
||||
39/compare 3/mod/direct 2/rm32/EDX . . . 6/r32/ESI . . # compare EDX and ESI
|
||||
7d/jump-if-greater-or-equal $slice-equal?:true/disp8
|
||||
# AL = *p
|
||||
# AL = *currp
|
||||
8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL
|
||||
# CL = *curr
|
||||
# CL = *currs
|
||||
8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 1/r32/CL . . # copy byte at *EDX to CL
|
||||
# if (EAX != ECX) return false
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX and ECX
|
||||
75/jump-if-not-equal $slice-equal?:false/disp8
|
||||
# ++p
|
||||
# ++currp
|
||||
43/increment-EBX
|
||||
# ++curr
|
||||
# ++currs
|
||||
42/increment-EDX
|
||||
eb/jump $slice-equal?:loop/disp8
|
||||
$slice-equal?:false:
|
||||
|
|
Binary file not shown.
|
@ -37,7 +37,7 @@
|
|||
# main: run tests if necessary, call 'compile' if not
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - if argc > 1 and argv[1] == "test" then return run_tests()
|
||||
# - if argc > 1 and argv[1] == "test", then return run_tests()
|
||||
# . argc > 1
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
|
@ -199,8 +199,8 @@ $compile:end:
|
|||
# 'in' into it on exit.
|
||||
get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
|
||||
# pseudocode:
|
||||
# if !is-digit?(Look) expected(ed, err, "integer")
|
||||
# if out->write >= out->length
|
||||
# if (!is-digit?(Look)) expected(ed, err, "integer")
|
||||
# if (out->write >= out->length)
|
||||
# write(err, "Error: too many digits in number\n")
|
||||
# stop(ed, 1)
|
||||
# out->data[out->write] = LSB(Look)
|
||||
|
@ -221,7 +221,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - if is-digit?(Look) expected(ed, err, "integer")
|
||||
# - if (is-digit?(Look)) expected(ed, err, "integer")
|
||||
# . EAX = is-digit?(Look)
|
||||
# . . push args
|
||||
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
|
||||
|
@ -229,7 +229,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
e8/call is-digit?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# . if EAX == 0
|
||||
# . if (EAX == 0)
|
||||
3d/compare-EAX 0/imm32
|
||||
75/jump-if-not-equal $get-num:main/disp8
|
||||
# . expected(ed, err, "integer")
|
||||
|
@ -259,7 +259,7 @@ $get-num:main:
|
|||
8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX
|
||||
# EDX = out->length
|
||||
8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX
|
||||
# if out->write >= out->length error
|
||||
# if (out->write >= out->length) error
|
||||
39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX
|
||||
7d/jump-if-lesser $get-num:stage2/disp8
|
||||
# . error(ed, err, msg) # TODO: show full number
|
||||
|
@ -559,10 +559,10 @@ is-digit?: # c : int -> EAX : boolean
|
|||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# EAX = false
|
||||
b8/copy-to-EAX 0/imm32
|
||||
# if c < '0' return false
|
||||
# if (c < '0') return false
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x30/imm32 # compare *(EBP+8)
|
||||
7c/jump-if-lesser $is-digit?:end/disp8
|
||||
# if c > '9' return false
|
||||
# if (c > '9') return false
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x39/imm32 # compare *(EBP+8)
|
||||
7f/jump-if-greater $is-digit?:end/disp8
|
||||
# otherwise return true
|
||||
|
|
Binary file not shown.
|
@ -37,7 +37,7 @@
|
|||
# main: run tests if necessary, call 'compile' if not
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - if argc > 1 and argv[1] == "test" then return run_tests()
|
||||
# - if argc > 1 and argv[1] == "test", then return run_tests()
|
||||
# . argc > 1
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
|
@ -200,15 +200,15 @@ $compile:end:
|
|||
# 'in' (rest). We leave the next byte from 'in' into 'Look' on exit.
|
||||
get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
|
||||
# pseudocode:
|
||||
# if !is-digit?(Look) expected(ed, err, "integer")
|
||||
# if (!is-digit?(Look)) expected(ed, err, "integer")
|
||||
# do
|
||||
# if out->write >= out->length
|
||||
# if (out->write >= out->length)
|
||||
# write(err, "Error: too many digits in number\n")
|
||||
# stop(ed, 1)
|
||||
# out->data[out->write] = LSB(Look)
|
||||
# ++out->write
|
||||
# Look = get-char(in)
|
||||
# while is-digit?(Look)
|
||||
# while (is-digit?(Look))
|
||||
# This is complicated because I don't want to hard-code the error strategy in
|
||||
# a general helper like write-byte. Maybe I should just create a local helper.
|
||||
#
|
||||
|
@ -226,7 +226,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - if is-digit?(Look) expected(ed, err, "integer")
|
||||
# - if (is-digit?(Look)) expected(ed, err, "integer")
|
||||
# . EAX = is-digit?(Look)
|
||||
# . . push args
|
||||
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
|
||||
|
@ -234,7 +234,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
|
|||
e8/call is-digit?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# . if EAX == 0
|
||||
# . if (EAX == 0)
|
||||
3d/compare-EAX 0/imm32
|
||||
75/jump-if-not-equal $get-num:main/disp8
|
||||
# . expected(ed, err, "integer")
|
||||
|
@ -265,7 +265,7 @@ $get-num:main:
|
|||
# EDX = out->length
|
||||
8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX
|
||||
$get-num:loop:
|
||||
# if out->write >= out->length error
|
||||
# if (out->write >= out->length) error
|
||||
39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX
|
||||
7d/jump-if-lesser $get-num:loop-stage2/disp8
|
||||
# . error(ed, err, msg) # TODO: show full number
|
||||
|
@ -291,7 +291,7 @@ $get-num:loop-stage2:
|
|||
e8/call get-char/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# if is-digit?(Look) loop
|
||||
# if (is-digit?(Look)) loop
|
||||
# . EAX = is-digit?(Look)
|
||||
# . . push args
|
||||
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look
|
||||
|
@ -299,7 +299,7 @@ $get-num:loop-stage2:
|
|||
e8/call is-digit?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# . if EAX loop
|
||||
# . if (EAX != 0) loop
|
||||
3d/compare-EAX 0/imm32
|
||||
0f 85/jump-if-not-equal $get-num:loop/disp32
|
||||
$get-num:loop-end:
|
||||
|
@ -756,10 +756,10 @@ is-digit?: # c : int -> EAX : boolean
|
|||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# EAX = false
|
||||
b8/copy-to-EAX 0/imm32
|
||||
# if c < '0' return false
|
||||
# if (c < '0') return false
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x30/imm32 # compare *(EBP+8)
|
||||
7c/jump-if-lesser $is-digit?:end/disp8
|
||||
# if c > '9' return false
|
||||
# if (c > '9') return false
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x39/imm32 # compare *(EBP+8)
|
||||
7f/jump-if-greater $is-digit?:end/disp8
|
||||
# otherwise return true
|
||||
|
|
Binary file not shown.
|
@ -21,7 +21,7 @@
|
|||
# main:
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - if argc > 1 and argv[1] == "test" then return run_tests()
|
||||
# - if argc > 1 and argv[1] == "test", then return run_tests()
|
||||
# . argc > 1
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
|
|
BIN
subx/apps/handle
BIN
subx/apps/handle
Binary file not shown.
BIN
subx/apps/hex
BIN
subx/apps/hex
Binary file not shown.
|
@ -25,7 +25,7 @@
|
|||
# main: run tests if necessary, convert stdin if not
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - if argc > 1 and argv[1] == "test" then return run_tests()
|
||||
# - if argc > 1 and argv[1] == "test", then return run_tests()
|
||||
# . argc > 1
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
|
@ -73,7 +73,7 @@ convert: # in : (address buffered-file), out : (address buffered-file), err : (
|
|||
# pseudocode:
|
||||
# repeatedly
|
||||
# EAX = convert-next-octet(in, err, ed)
|
||||
# if EAX == 0xffffffff break # eof
|
||||
# if (EAX == 0xffffffff) break # eof
|
||||
# write-byte(out, AL)
|
||||
# flush(out)
|
||||
#
|
||||
|
@ -92,7 +92,7 @@ $convert:loop:
|
|||
e8/call convert-next-octet/disp32
|
||||
# . . discard first 2 args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# if EAX == 0xffffffff break
|
||||
# if (EAX == 0xffffffff) break
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX
|
||||
74/jump-if-equal $convert:loop-end/disp8
|
||||
# write-byte(out, AL)
|
||||
|
@ -489,10 +489,10 @@ scan-next-byte: # in : (address buffered-file), err : (address buffered-file),
|
|||
# pseudocode:
|
||||
# repeatedly
|
||||
# EAX = read-byte(in)
|
||||
# if EAX == 0xffffffff return EAX
|
||||
# if is-hex-digit?(EAX) return EAX
|
||||
# if EAX == ' ' or '\t' or '\n' continue
|
||||
# if EAX == '#' skip-until-newline(in)
|
||||
# if (EAX == 0xffffffff) return EAX
|
||||
# if (is-hex-digit?(EAX)) return EAX
|
||||
# if (EAX == ' ' or '\t' or '\n') continue
|
||||
# if (EAX == '#') skip-until-newline(in)
|
||||
# else error-byte(ed, err, "invalid byte: " EAX)
|
||||
#
|
||||
# . prolog
|
||||
|
@ -510,7 +510,7 @@ $scan-next-byte:loop:
|
|||
# if (EAX == 0xffffffff) return EAX
|
||||
3d/compare-with-EAX 0xffffffff/imm32
|
||||
74/jump-if-equal $scan-next-byte:end/disp8
|
||||
# if is-hex-digit?(EAX) return EAX
|
||||
# if (is-hex-digit?(EAX)) return EAX
|
||||
# . save EAX for now
|
||||
50/push-EAX
|
||||
# . is-hex-digit?(EAX)
|
||||
|
@ -527,17 +527,17 @@ $scan-next-byte:loop:
|
|||
# . check whether to return
|
||||
75/jump-if-not-equal $scan-next-byte:end/disp8
|
||||
$scan-next-byte:check1:
|
||||
# if EAX == ' ' continue
|
||||
# if (EAX == ' ') continue
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x20/imm32 # compare EAX
|
||||
74/jump-if-equal $scan-next-byte:loop/disp8
|
||||
# if EAX == '\t' continue
|
||||
# if (EAX == '\t') continue
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x9/imm32 # compare EAX
|
||||
74/jump-if-equal $scan-next-byte:loop/disp8
|
||||
# if EAX == '\n' continue
|
||||
# if (EAX == '\n') continue
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX
|
||||
74/jump-if-equal $scan-next-byte:loop/disp8
|
||||
$scan-next-byte:check2:
|
||||
# if EAX == '#' skip-until-newline(in)
|
||||
# if (EAX == '#') skip-until-newline(in)
|
||||
3d/compare-with-EAX 0x23/imm32
|
||||
75/jump-if-not-equal $scan-next-byte:check3/disp8
|
||||
# . skip-until-newline(in)
|
||||
|
@ -1413,8 +1413,8 @@ skip-until-newline: # in : (address buffered-file) -> <void>
|
|||
# push EAX
|
||||
# repeatedly:
|
||||
# EAX = read-byte(in)
|
||||
# if EAX == 0xffffffff break
|
||||
# if EAX == 0x0a break
|
||||
# if (EAX == 0xffffffff) break
|
||||
# if (EAX == 0x0a) break
|
||||
# pop EAX
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
|
@ -1429,10 +1429,10 @@ $skip-until-newline:loop:
|
|||
e8/call read-byte/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# . if EAX == 0xffffffff break
|
||||
# . if (EAX == 0xffffffff) break
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX
|
||||
74/jump-if-equal $skip-until-newline:end/disp8
|
||||
# . if EAX != 0xa/newline loop
|
||||
# . if (EAX != 0xa/newline) loop
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX
|
||||
75/jump-if-not-equal $skip-until-newline:loop/disp8
|
||||
$skip-until-newline:end:
|
||||
|
|
BIN
subx/apps/pack
BIN
subx/apps/pack
Binary file not shown.
|
@ -28,7 +28,7 @@
|
|||
# main: run tests if necessary, convert stdin if not
|
||||
# . prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# - if argc > 1 and argv[1] == "test" then return run_tests()
|
||||
# - if argc > 1 and argv[1] == "test", then return run_tests()
|
||||
# . argc > 1
|
||||
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
|
@ -88,7 +88,7 @@ convert: # in : (address buffered-file), out : (address buffered-file) -> <void
|
|||
# repeatedly
|
||||
# clear-stream(line)
|
||||
# EAX = read-line(in, line)
|
||||
# if EAX == EOF break
|
||||
# if (EAX == EOF) break
|
||||
# convert-instruction(line, out)
|
||||
# flush(out)
|
||||
#
|
||||
|
@ -119,7 +119,7 @@ $convert:loop:
|
|||
e8/call convert-instruction/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# if EAX == 0xffffffff break
|
||||
# if (EAX == 0xffffffff) break
|
||||
3d/compare-with-EAX 0xffffffff/imm32
|
||||
74/jump-if-equal $convert:break/disp8
|
||||
# convert-instruction(line, out)
|
||||
|
@ -200,10 +200,10 @@ $convert:end:
|
|||
convert-instruction: # line : (address stream byte), out : (address buffered-file) -> <void>
|
||||
# pseudocode:
|
||||
# word-slice = next-word
|
||||
# if *word-slice->start == '#'
|
||||
# if (*word-slice->start == '#')
|
||||
# write-stream-buffered(out, line)
|
||||
# return
|
||||
# if starts-with(word-slice, '==')
|
||||
# if (starts-with(word-slice, '=='))
|
||||
# write-stream-buffered(out, line)
|
||||
# return
|
||||
#
|
||||
|
@ -599,7 +599,7 @@ next-word: # line : (address stream byte), out : (address slice)
|
|||
8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/EAX 0xc/disp8 . # copy ESI+ECX+12 to EAX
|
||||
89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI
|
||||
# if line->data[line->read] == '#': out->end = &line->data[line->write]), skip rest of stream and return
|
||||
# if (line->data[line->read] == '#') out->end = &line->data[line->write]), skip rest of stream and return
|
||||
# . EAX = line->data[line->read]
|
||||
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX
|
||||
8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/AL 0xc/disp8 . # copy byte at *(ESI+ECX+12) to AL
|
||||
|
@ -770,8 +770,8 @@ has-metadata?: # word : (address slice), s : (address string) -> EAX : boolean
|
|||
# curr = twig->end
|
||||
# while true:
|
||||
# twig = next-token-from-slice(curr, word->end, '/')
|
||||
# if twig.empty() break
|
||||
# if slice-equal?(twig, s) return true
|
||||
# if (twig.empty()) break
|
||||
# if (slice-equal?(twig, s)) return true
|
||||
# curr = twig->end
|
||||
# return false
|
||||
# . prolog
|
||||
|
@ -813,7 +813,7 @@ $has-metadata?:loop:
|
|||
e8/call next-token-from-slice/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# if slice-empty?(twig) return false
|
||||
# if (slice-empty?(twig)) return false
|
||||
# . EAX = slice-empty?(twig)
|
||||
# . . push args
|
||||
57/push-EDI
|
||||
|
@ -824,7 +824,7 @@ $has-metadata?:loop:
|
|||
# . if (EAX != 0) return false
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
|
||||
75/compare-if-not-equal $has-metadata?:false/disp8
|
||||
# if slice-equal?(twig, s) return true
|
||||
# if (slice-equal?(twig, s)) return true
|
||||
# . EAX = slice-equal?(twig, s)
|
||||
# . . push args
|
||||
ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12)
|
||||
|
@ -1058,7 +1058,7 @@ emit: # out : (address buffered-file), word : (address slice), width : int
|
|||
e8/call next-token-from-slice/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP
|
||||
# if !is-hex-int?(name) write-slice(out, word) and return
|
||||
# if (!is-hex-int?(name)) write-slice(out, word) and return
|
||||
# . is-hex-int?(name)
|
||||
# . . push args
|
||||
57/push-EDI
|
||||
|
@ -1066,7 +1066,7 @@ emit: # out : (address buffered-file), word : (address slice), width : int
|
|||
e8/call is-hex-int?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# . if EAX == 0
|
||||
# . if (EAX == 0)
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
|
||||
75/jump-if-not-equal $emit:hex-int/disp8
|
||||
# . write-slice(out, word)
|
||||
|
|
|
@ -38,7 +38,6 @@ argv-equal: # (s1, s2) : null-terminated ascii strings -> EAX : boolean
|
|||
# initialize s1 (ECX) and s2 (EDX)
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX 4/disp8 . # copy *(ESP+4) to ECX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 2/r32/EDX 8/disp8 . # copy *(ESP+8) to EDX
|
||||
# while (true)
|
||||
$argv-equal:loop:
|
||||
# c1/EAX, c2/EBX = *s1, *s2
|
||||
b8/copy-to-EAX 0/imm32
|
||||
|
|
Binary file not shown.
|
@ -28,7 +28,28 @@
|
|||
|
||||
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
||||
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
|
||||
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
||||
kernel-string-equal?: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
||||
# pseudocode:
|
||||
# n = benchmark->length
|
||||
# s1 = s
|
||||
# s2 = benchmark->data
|
||||
# i = 0
|
||||
# while (i < n)
|
||||
# c1 = *s1
|
||||
# c2 = *s2
|
||||
# if (c1 == 0) return false
|
||||
# if (c1 != c2) return false
|
||||
# ++s1, ++s2, ++i
|
||||
# return *s1 == 0
|
||||
#
|
||||
# registers:
|
||||
# i: ECX
|
||||
# n: EDX
|
||||
# s1: EDI
|
||||
# s2: ESI
|
||||
# c1: EAX
|
||||
# c2: EBX
|
||||
#
|
||||
# . prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -38,72 +59,57 @@ kernel-string-equal: # s : null-terminated ascii string, benchmark : length-pre
|
|||
53/push-EBX
|
||||
56/push-ESI
|
||||
57/push-EDI
|
||||
|
||||
# pseudocode:
|
||||
# initialize n = b->length
|
||||
# initialize s1 = s
|
||||
# initialize s2 = b->data
|
||||
# i = 0
|
||||
# for (i = 0; i < n; ++n)
|
||||
# c1 = *s1
|
||||
# c2 = *s2
|
||||
# if c1 == 0
|
||||
# return false
|
||||
# if c1 != c2
|
||||
# return false
|
||||
# return *s1 == 0
|
||||
# initialize s into EDI
|
||||
# s1/EDI = s
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI
|
||||
# initialize benchmark length n into EDX
|
||||
# n/EDX = benchmark->length
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 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
|
||||
# initialize benchmark data into ESI
|
||||
# s2/ESI = benchmark->data
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI
|
||||
81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 4/imm32 # add to ESI
|
||||
# initialize loop counter i into ECX
|
||||
# i/ECX = c1/EAX = c2/EBX = 0
|
||||
b9/copy-to-ECX 0/imm32/exit
|
||||
# while (i/ECX < n/EDX)
|
||||
$kernel-string-equal:loop:
|
||||
39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX
|
||||
74/jump-if-equal $kernel-string-equal:break/disp8
|
||||
# c1/EAX, c2/EBX = *s, *benchmark
|
||||
b8/copy-to-EAX 0/imm32
|
||||
8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
$kernel-string-equal?:loop:
|
||||
# if (i >= n) break
|
||||
39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX
|
||||
7d/jump-if-greater-or-equal $kernel-string-equal?:break/disp8
|
||||
# c1 = *s1
|
||||
8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX
|
||||
# c2 = *s2
|
||||
8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX
|
||||
# if (c1 == 0) return false
|
||||
3d/compare-EAX 0/imm32
|
||||
74/jump-if-equal $kernel-string-equal:false/disp8
|
||||
74/jump-if-equal $kernel-string-equal?:false/disp8
|
||||
# if (c1 != c2) return false
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX
|
||||
75/jump-if-not-equal $kernel-string-equal:false/disp8
|
||||
# ++s1, ++s2, ++i
|
||||
75/jump-if-not-equal $kernel-string-equal?:false/disp8
|
||||
# ++i
|
||||
41/inc-ECX
|
||||
46/inc-ESI
|
||||
# ++s1
|
||||
47/inc-EDI
|
||||
# end while
|
||||
eb/jump $kernel-string-equal:loop/disp8
|
||||
$kernel-string-equal:break:
|
||||
# if (*s/EDI == 0) return true
|
||||
b8/copy-to-EAX 0/imm32
|
||||
# ++s2
|
||||
46/inc-ESI
|
||||
eb/jump $kernel-string-equal?:loop/disp8
|
||||
$kernel-string-equal?:break:
|
||||
# return *s1 == 0
|
||||
8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
|
||||
75/jump-if-not-equal $kernel-string-equal:false/disp8
|
||||
3d/compare-EAX 0/imm32
|
||||
75/jump-if-not-equal $kernel-string-equal?:false/disp8
|
||||
$kernel-string-equal?:true:
|
||||
b8/copy-to-EAX 1/imm32
|
||||
$kernel-string-equal:true:
|
||||
eb/jump $kernel-string-equal:end/disp8
|
||||
# return false
|
||||
$kernel-string-equal:false:
|
||||
eb/jump $kernel-string-equal?:end/disp8
|
||||
$kernel-string-equal?:false:
|
||||
b8/copy-to-EAX 0/imm32
|
||||
|
||||
$kernel-string-equal:end:
|
||||
$kernel-string-equal?:end:
|
||||
# . restore registers
|
||||
5f/pop-to-EDI
|
||||
5e/pop-to-ESI
|
||||
5b/pop-to-EBX
|
||||
5a/pop-to-EDX
|
||||
59/pop-to-ECX
|
||||
# end
|
||||
# . epilog
|
||||
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
|
||||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
@ -111,12 +117,12 @@ $kernel-string-equal:end:
|
|||
# - tests
|
||||
|
||||
test-compare-null-kernel-string-with-empty-array:
|
||||
# EAX = kernel-string-equal(Null-kernel-string, "")
|
||||
# EAX = kernel-string-equal?(Null-kernel-string, "")
|
||||
# . . push args
|
||||
68/push ""/imm32
|
||||
68/push Null-kernel-string/imm32
|
||||
# . . call
|
||||
e8/call kernel-string-equal/disp32
|
||||
e8/call kernel-string-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check-ints-equal(EAX, 1, msg)
|
||||
|
@ -131,12 +137,12 @@ test-compare-null-kernel-string-with-empty-array:
|
|||
c3/return
|
||||
|
||||
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
|
||||
68/push "Abc"/imm32
|
||||
68/push Null-kernel-string/imm32
|
||||
# . . call
|
||||
e8/call kernel-string-equal/disp32
|
||||
e8/call kernel-string-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
|
@ -151,12 +157,12 @@ test-compare-null-kernel-string-with-non-empty-array:
|
|||
c3/return
|
||||
|
||||
test-compare-kernel-string-with-equal-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
|
||||
# EAX = kernel-string-equal?(_test-Abc-kernel-string, "Abc")
|
||||
# . . push args
|
||||
68/push "Abc"/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
68/push _test-Abc-kernel-string/imm32
|
||||
# . . call
|
||||
e8/call kernel-string-equal/disp32
|
||||
e8/call kernel-string-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check-ints-equal(EAX, 1, msg)
|
||||
|
@ -171,12 +177,12 @@ test-compare-kernel-string-with-equal-array:
|
|||
c3/return
|
||||
|
||||
test-compare-kernel-string-with-inequal-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
|
||||
# EAX = kernel-string-equal?(_test-Abc-kernel-string, "Adc")
|
||||
# . . push args
|
||||
68/push "Adc"/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
68/push _test-Abc-kernel-string/imm32
|
||||
# . . call
|
||||
e8/call kernel-string-equal/disp32
|
||||
e8/call kernel-string-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
|
@ -191,12 +197,12 @@ test-compare-kernel-string-with-inequal-array:
|
|||
c3/return
|
||||
|
||||
test-compare-kernel-string-with-empty-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "")
|
||||
# EAX = kernel-string-equal?(_test-Abc-kernel-string, "")
|
||||
# . . push args
|
||||
68/push ""/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
68/push _test-Abc-kernel-string/imm32
|
||||
# . . call
|
||||
e8/call kernel-string-equal/disp32
|
||||
e8/call kernel-string-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
|
@ -211,12 +217,12 @@ test-compare-kernel-string-with-empty-array:
|
|||
c3/return
|
||||
|
||||
test-compare-kernel-string-with-shorter-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
|
||||
# EAX = kernel-string-equal?(_test-Abc-kernel-string, "Ab")
|
||||
# . . push args
|
||||
68/push "Ab"/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
68/push _test-Abc-kernel-string/imm32
|
||||
# . . call
|
||||
e8/call kernel-string-equal/disp32
|
||||
e8/call kernel-string-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
|
@ -231,12 +237,12 @@ test-compare-kernel-string-with-shorter-array:
|
|||
c3/return
|
||||
|
||||
test-compare-kernel-string-with-longer-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
|
||||
# EAX = kernel-string-equal?(_test-Abc-kernel-string, "Abcd")
|
||||
# . . push args
|
||||
68/push "Abcd"/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
68/push _test-Abc-kernel-string/imm32
|
||||
# . . call
|
||||
e8/call kernel-string-equal/disp32
|
||||
e8/call kernel-string-equal?/disp32
|
||||
# . . discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check-ints-equal(EAX, 0, msg)
|
||||
|
@ -263,7 +269,7 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
|||
# load args into EAX, EBX and ECX
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX
|
||||
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX
|
||||
# if EAX == b/EBX print('.') and return
|
||||
# if (EAX == b/EBX) print('.') and return
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
|
||||
75/jump-if-unequal $check-ints-equal:else/disp8
|
||||
# . write-stderr('.')
|
||||
|
@ -344,7 +350,8 @@ Newline:
|
|||
# for kernel-string-equal tests
|
||||
Null-kernel-string:
|
||||
00/null
|
||||
Abc-kernel-string:
|
||||
|
||||
_test-Abc-kernel-string:
|
||||
41/A 62/b 63/c 00/null
|
||||
|
||||
# . . vim:nowrap:textwidth=0
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
b9/copy-to-ECX 1/imm32
|
||||
|
||||
$loop:
|
||||
# while (counter <= 10)
|
||||
# if (counter > 10) break
|
||||
81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0xa/imm32 # compare ECX
|
||||
7f/jump-if-greater $exit/disp8
|
||||
# result += counter
|
||||
|
|
|
@ -42,7 +42,7 @@ ascii-length: # s : (address array byte) -> n/EAX
|
|||
$ascii-length-loop:
|
||||
# var c/ECX = *s
|
||||
8a/copy 0/mod/* 2/rm32/EDX . . . 1/r32/ECX . . # copy byte at *EDX to lower byte of ECX
|
||||
# if c == '\0' break
|
||||
# if (c == '\0') break
|
||||
81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX
|
||||
74/jump-if-equal $ascii-length-ret/disp8
|
||||
# ++s
|
||||
|
|
|
@ -74,6 +74,7 @@ Opcodes currently supported by SubX:
|
|||
bf: copy imm32 to EDI (mov)
|
||||
c1: shift rm32 by imm8 bits depending on subop (sal/sar/shl/shr)
|
||||
c3: return from most recent unfinished call (ret)
|
||||
c6: copy imm8 to r8/m8-at-r32 (mov)
|
||||
c7: copy imm32 to rm32 (mov)
|
||||
cd: software interrupt (int)
|
||||
d3: shift rm32 by CL bits depending on subop (sal/sar/shl/shr)
|
||||
|
|
Loading…
Reference in New Issue