This commit is contained in:
Kartik Agaram 2019-02-14 16:24:20 -08:00
parent 1ab48a69cc
commit 1639687ba0
31 changed files with 254 additions and 210 deletions

View File

@ -32,7 +32,7 @@ check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> <void>
# load first 2 args into EAX and EBX # 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 . . . 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 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 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, '.')

View File

@ -30,19 +30,26 @@
# 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
# pseudocode: # pseudocode:
# initialize n = b->length # n = benchmark->length
# initialize s1 = s # s1 = s
# initialize s2 = b->data # s2 = benchmark->data
# i = 0 # i = 0
# for (i = 0; i < n; ++n) # while (i < n)
# c1 = *s1 # c1 = *s1
# c2 = *s2 # c2 = *s2
# if c1 == 0 # if (c1 == 0) return false
# return false # if (c1 != c2) return false
# if c1 != c2 # ++s1, ++s2, ++i
# return false
# return *s1 == 0 # return *s1 == 0
# #
# registers:
# i: ECX
# n: EDX
# s1: EDI
# s2: ESI
# c1: EAX
# c2: EBX
#
# . 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
@ -52,24 +59,25 @@ kernel-string-equal?: # s : null-terminated ascii string, benchmark : length-pr
53/push-EBX 53/push-EBX
56/push-ESI 56/push-ESI
57/push-EDI 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 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 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 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 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 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 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 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 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 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 # if (c1 == 0) return false
3d/compare-EAX 0/imm32 3d/compare-EAX 0/imm32
@ -77,22 +85,21 @@ $kernel-string-equal?:loop:
# if (c1 != c2) return false # if (c1 != c2) return false
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX 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 75/jump-if-not-equal $kernel-string-equal?:false/disp8
# ++s1, ++s2, ++i # ++i
41/inc-ECX 41/inc-ECX
46/inc-ESI # ++s1
47/inc-EDI 47/inc-EDI
# end while # ++s2
46/inc-ESI
eb/jump $kernel-string-equal?:loop/disp8 eb/jump $kernel-string-equal?:loop/disp8
$kernel-string-equal?:break: $kernel-string-equal?:break:
# if (*s/EDI == 0) return true # return *s1 == 0
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 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 3d/compare-EAX 0/imm32
75/jump-if-not-equal $kernel-string-equal?:false/disp8 75/jump-if-not-equal $kernel-string-equal?:false/disp8
$kernel-string-equal?:true: $kernel-string-equal?:true:
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
eb/jump $kernel-string-equal?:end/disp8 eb/jump $kernel-string-equal?:end/disp8
# return false
$kernel-string-equal?:false: $kernel-string-equal?:false:
b8/copy-to-EAX 0/imm32 b8/copy-to-EAX 0/imm32
$kernel-string-equal?:end: $kernel-string-equal?:end:
@ -253,6 +260,7 @@ test-compare-kernel-string-with-longer-array:
Null-kernel-string: Null-kernel-string:
00/null 00/null
_test-Abc-kernel-string: _test-Abc-kernel-string:
41/A 62/b 63/c 00/null 41/A 62/b 63/c 00/null

View File

@ -13,18 +13,27 @@
b8/copy-to-EAX 1/imm32/exit b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
string-equal?: # s : string, benchmark : string -> EAX : boolean string-equal?: # s : (address string), benchmark : (address string) -> EAX : boolean
# pseudocode: # pseudocode:
# if s->length != b->length return false # lens = s->length
# for i = 0; i < s->length; ++i # if (lens != benchmark->length) return false
# if s[i] != b[i] 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 # return true
#
# registers: # registers:
# i: ECX # i: ECX
# s->length: EDX # lens: EDX
# b->length: EBX # currs: EAX
# b[i]: EBX # currb: EBX
# s[i]: EAX # c1: ESI
# c2: EDI
# #
# . prolog # . prolog
55/push-EBP 55/push-EBP
@ -34,17 +43,16 @@ string-equal?: # s : string, benchmark : string -> EAX : boolean
52/push-EDX 52/push-EDX
53/push-EBX 53/push-EBX
56/push-ESI 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 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 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 # lens/EDX = s->length
# EDX = s->length
8b/copy 0/mod/indirect 0/rm32/EAX . . . 2/r32/EDX . . # copy *EAX to EDX 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 39/compare 0/mod/indirect 3/rm32/EBX . . . 2/r32/EDX . . # compare *EBX with EDX
75/jump-if-not-equal $string-equal?:false/disp8 75/jump-if-not-equal $string-equal?:false/disp8
$string-equal?:lengths:
# var i/ECX : int = 0 # var i/ECX : int = 0
b9/copy-to-ECX 0/imm32 b9/copy-to-ECX 0/imm32
# EBX = &b[i] # EBX = &b[i]
@ -52,7 +60,7 @@ $string-equal?:lengths:
# EAX = &s[i] # EAX = &s[i]
40/inc-EAX 40/inc-EAX
$string-equal?:loop: $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 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 7d/jump-if-greater-or-equal $string-equal?:true/disp8
# if b[i] != s[i] return false # if b[i] != s[i] return false
@ -63,16 +71,15 @@ $string-equal?:loop:
75/jump-if-not-equal $string-equal?:false/disp8 75/jump-if-not-equal $string-equal?:false/disp8
# ++i # ++i
41/inc-ECX 41/inc-ECX
# ++c1
40/inc-EAX 40/inc-EAX
# ++c2
43/inc-EBX 43/inc-EBX
# loop
eb/jump $string-equal?:loop/disp8 eb/jump $string-equal?:loop/disp8
$string-equal?:true: $string-equal?:true:
# return true
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
eb/jump $string-equal?:end/disp8 eb/jump $string-equal?:end/disp8
$string-equal?:false: $string-equal?: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

View File

@ -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 81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 0xc/imm32 # add to EAX
# while (true) # while (true)
$clear-stream:loop: $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 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 7d/jump-if-greater-or-equal $clear-stream:end/disp8
# *EAX = 0 # *EAX = 0
@ -76,3 +76,5 @@ $rewind-stream:end:
89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP
5d/pop-to-EBP 5d/pop-to-EBP
c3/return c3/return
# . . vim:nowrap:textwidth=0

View File

@ -99,7 +99,7 @@ trace: # t : (address trace-stream), line : string
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
74/jump-if-equal $trace:end/disp8 74/jump-if-equal $trace:end/disp8
# t->write += EAX # 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) c7 0/subop/copy 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 0/imm32 # copy to *(EAX+4)
# EAX = t->data # EAX = t->data
81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 0xc/imm32 # add to EAX 81 0/subop/add 3/mod/direct 0/rm32/EAX . . . . . 0xc/imm32 # add to EAX
# while (true)
$clear-trace-stream:loop: $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 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 7d/jump-if-greater-or-equal $clear-trace-stream:end/disp8
# *EAX = 0 # *EAX = 0
@ -328,18 +327,20 @@ _append-4: # out : address, outend : address, in : address, inend : address ->
# ECX = inend # ECX = inend
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 0x14/disp8 . # copy *(EBP+20) to ECX 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 0x14/disp8 . # copy *(EBP+20) to ECX
$_append-4:loop: $_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 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 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 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 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 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 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 40/increment-EAX
# ++in
46/increment-ESI 46/increment-ESI
# ++out
47/increment-EDI 47/increment-EDI
eb/jump $_append-4:loop/disp8 eb/jump $_append-4:loop/disp8
$_append-4:end: $_append-4:end:

View File

@ -32,7 +32,7 @@ write: # 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
# 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) 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 7d/jump-if-greater-or-equal $write:fake/disp8
# . . push args # . . push args

View File

@ -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 81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 0xc/imm32 # add to ESI
# EDI = s # EDI = s
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI 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 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 75/jump-if-not-equal $stream-data-equal?:false/disp8
# currs/EDI = s->data # currs/EDI = s->data
@ -235,25 +235,25 @@ next-stream-line-equal?: # f : (address stream), s : (address string) -> EAX :
# pseudocode: # pseudocode:
# currf = f->read # bound: f->write # currf = f->read # bound: f->write
# currs = 0 # bound : s->length # currs = 0 # bound : s->length
# while true # while true:
# if currf >= f->write # if (currf >= f->write)
# return currs >= s->length # return currs >= s->length
# if f[currf] == '\n' # if (f[currf] == '\n')
# ++currf # ++currf
# return currs >= s->length # return currs >= s->length
# if currs >= s->length return false # the current line of f still has data to match # if (currs >= s->length) return false # the current line of f still has data to match
# if f[currf] != s[currs] return false # if (f[currf] != s[currs]) return false
# ++currf # ++currf
# ++currs # ++currs
# #
# collapsing the two branches that can return true: # collapsing the two branches that can return true:
# currf = f->read # bound: f->write # currf = f->read # bound: f->write
# currs = 0 # bound : s->length # currs = 0 # bound : s->length
# while true # while true:
# if currf >= f->write break # if (currf >= f->write) break
# if f[currf] == '\n' break # if (f[currf] == '\n') break
# if currs >= s->length return false # the current line of f still has data to match # if (currs >= s->length) return false # the current line of f still has data to match
# if f[currf] != s[currs] return false # if (f[currf] != s[currs]) return false
# ++currf # ++currf
# ++currs # ++currs
# ++currf # skip '\n' # ++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) # Here the final `++currf` is sometimes unnecessary (if we're already at the end of the stream)
# #
# registers: # registers:
# f : ESI # f: ESI
# s : EDI # s: EDI
# currf : ECX # currf: ECX
# currs : EDX # currs: EDX
# f[currf] : EAX # f[currf]: EAX
# s[currs] : EBX # s[currs]: EBX
# #
# . prolog # . prolog
55/push-EBP 55/push-EBP
@ -312,7 +312,7 @@ $next-stream-line-equal?:loop:
$next-stream-line-equal?:break: $next-stream-line-equal?:break:
# ++currf # ++currf
41/increment-ECX 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 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 7c/jump-if-lesser $next-stream-line-equal?:false/disp8
$next-stream-line-equal?:true: $next-stream-line-equal?:true:

View File

@ -100,19 +100,20 @@ stop: # ed : (address exit-descriptor), value : int
# no prolog; one way or another, we're going to clobber registers # no prolog; one way or another, we're going to clobber registers
# EAX = ed # 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 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 81 7/subop/compare 0/mod/indirect 0/rm32/EAX . . . . . 0/imm32 # compare *EAX
75/jump-if-not-equal $stop:fake/disp8 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 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 b8/copy-to-EAX 1/imm32/exit
cd/syscall 0x80/imm8 cd/syscall 0x80/imm8
$stop:fake: $stop:fake:
# otherwise:
# ed->value = value+1 # 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 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 41/inc-ECX
89/copy 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy ECX to *(EAX+4) 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 8b/copy 0/mod/indirect 0/rm32/EAX . . . 4/r32/ESP . . # copy *EAX to ESP
$stop:end: $stop:end:
c3/return # doesn't return to caller c3/return # doesn't return to caller

View File

@ -74,7 +74,7 @@ read-byte: # f : (address buffered-file) -> byte-or-eof/EAX
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
75/jump-if-not-equal $read-byte:from-stream/disp8 75/jump-if-not-equal $read-byte:from-stream/disp8
b8/copy-to-EAX 0xffffffff/imm32 b8/copy-to-EAX 0xffffffff/imm32

View File

@ -71,7 +71,7 @@ $is-hex-int?:loop:
e8/call is-hex-digit?/disp32 e8/call is-hex-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 == false return false # if (EAX == false) return false
3d/compare-with-EAX 0/imm32 3d/compare-with-EAX 0/imm32
74/jump-if-equal $is-hex-int?:end/disp8 74/jump-if-equal $is-hex-int?:end/disp8
# ++curr # ++curr
@ -738,7 +738,7 @@ test-hex-above-f:
from-hex-char: # in/EAX : byte -> out/EAX : num from-hex-char: # in/EAX : byte -> out/EAX : num
# no error checking; accepts argument in EAX # 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 3d/compare-EAX 0x39/imm32/9
7f/jump-if-greater $from-hex-char:else/disp8 7f/jump-if-greater $from-hex-char:else/disp8
2d/subtract-from-EAX 0x30/imm32/0 2d/subtract-from-EAX 0x30/imm32/0
@ -750,7 +750,7 @@ $from-hex-char:else:
to-hex-char: # in/EAX : nibble -> out/EAX : byte to-hex-char: # in/EAX : nibble -> out/EAX : byte
# no error checking; accepts argument in EAX # 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 3d/compare-EAX 0x9/imm32/9
7f/jump-if-greater $to-hex-char:else/disp8 7f/jump-if-greater $to-hex-char:else/disp8
05/add-to-EAX 0x30/imm32/0 05/add-to-EAX 0x30/imm32/0

View File

@ -18,8 +18,8 @@ write-buffered: # f : (address buffered-file), msg : (address array byte) -> <v
# pseudocode: # pseudocode:
# in = msg->data # in = msg->data
# inend = &msg->data[msg->length] # inend = &msg->data[msg->length]
# while in < inend # while (in < inend)
# if f->write >= f->length # if (f->write >= f->length)
# flush(f) # flush(f)
# clear-stream(f) # clear-stream(f)
# f->data[f->write] = *in # f->data[f->write] = *in

View File

@ -164,7 +164,7 @@ allocate-region: # ad : (address allocation-descriptor), n : int -> new-ad : (a
e8/call allocate/disp32 e8/call allocate/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 abort # if (EAX == 0) abort
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
74/jump-if-equal $allocate-region:abort/disp8 74/jump-if-equal $allocate-region:abort/disp8
# earmark 8 bytes at the start for a new allocation descriptor # earmark 8 bytes at the start for a new allocation descriptor

View File

@ -23,7 +23,7 @@ read-line: # f : (address buffered-file), s : (address stream byte) -> eof?/EAX
# s->data[s->write] = AL # s->data[s->write] = AL
# ++f->read # ++f->read
# ++s->write # ++s->write
# if AL == '\n' break # if (AL == '\n') break
# . 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
@ -65,8 +65,8 @@ $read-line:loop:
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 f->write == 0 return true # if (f->write == 0) return true
# . if EAX == 0 return true # . if (EAX == 0) return true
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
75/jump-if-not-equal $read-line:from-stream/disp8 75/jump-if-not-equal $read-line:from-stream/disp8
b8/copy-to-EAX 0xffffffff/imm32 b8/copy-to-EAX 0xffffffff/imm32
@ -81,7 +81,7 @@ $read-line:from-stream:
41/increment-ECX 41/increment-ECX
# ++s->write # ++s->write
42/increment-EDX 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 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX
75/jump-if-not-equal $read-line:loop/disp8 75/jump-if-not-equal $read-line:loop/disp8
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX

View File

@ -21,7 +21,7 @@ slice-empty?: # s : (address slice) -> EAX : boolean
51/push-ECX 51/push-ECX
# ECX = s # ECX = s
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX 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 # . EAX = s->start
8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX
# . compare EAX with s->end # . compare EAX with s->end
@ -96,6 +96,24 @@ test-slice-empty-false:
c3/return c3/return
slice-equal?: # s : (address slice), p : (address string) -> EAX : boolean 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 # . 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
@ -106,37 +124,37 @@ slice-equal?: # s : (address slice), p : (address string) -> EAX : boolean
56/push-ESI 56/push-ESI
# ESI = s # ESI = s
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI 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 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 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI
# EBX = p # EBX = p
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX 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 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 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 39/compare 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # compare *EBX and EAX
75/jump-if-not-equal $slice-equal?:false/disp8 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 81 0/subop/add 3/mod/direct 3/rm32/EBX . . . . . 4/imm32 # add to EBX
# EAX = ECX = 0 # EAX = ECX = 0
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX
31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX
$slice-equal?:loop: $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 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 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 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 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 1/r32/CL . . # copy byte at *EDX to CL
# if (EAX != ECX) return false # if (EAX != ECX) return false
39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX and ECX 39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX and ECX
75/jump-if-not-equal $slice-equal?:false/disp8 75/jump-if-not-equal $slice-equal?:false/disp8
# ++p # ++currp
43/increment-EBX 43/increment-EBX
# ++curr # ++currs
42/increment-EDX 42/increment-EDX
eb/jump $slice-equal?:loop/disp8 eb/jump $slice-equal?:loop/disp8
$slice-equal?:false: $slice-equal?:false:

Binary file not shown.

View File

@ -37,7 +37,7 @@
# 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 and argv[1] == "test" then return run_tests() # - if argc > 1 and argv[1] == "test", then return run_tests()
# . argc > 1 # . argc > 1
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 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 7e/jump-if-lesser-or-equal $run-main/disp8
@ -199,8 +199,8 @@ $compile:end:
# 'in' into it on exit. # 'in' into it on exit.
get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void> get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
# pseudocode: # pseudocode:
# if !is-digit?(Look) expected(ed, err, "integer") # if (!is-digit?(Look)) expected(ed, err, "integer")
# if out->write >= out->length # if (out->write >= out->length)
# write(err, "Error: too many digits in number\n") # write(err, "Error: too many digits in number\n")
# stop(ed, 1) # stop(ed, 1)
# out->data[out->write] = LSB(Look) # out->data[out->write] = LSB(Look)
@ -221,7 +221,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
# . prolog # . prolog
55/push-EBP 55/push-EBP
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# - if is-digit?(Look) expected(ed, err, "integer") # - if (is-digit?(Look)) expected(ed, err, "integer")
# . 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
@ -229,7 +229,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
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 # . if (EAX == 0)
3d/compare-EAX 0/imm32 3d/compare-EAX 0/imm32
75/jump-if-not-equal $get-num:main/disp8 75/jump-if-not-equal $get-num:main/disp8
# . expected(ed, err, "integer") # . expected(ed, err, "integer")
@ -259,7 +259,7 @@ $get-num:main:
8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX
# EDX = out->length # EDX = out->length
8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX
# 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 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX
7d/jump-if-lesser $get-num:stage2/disp8 7d/jump-if-lesser $get-num:stage2/disp8
# . error(ed, err, msg) # TODO: show full number # . 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 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# EAX = false # EAX = false
b8/copy-to-EAX 0/imm32 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) 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 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) 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 7f/jump-if-greater $is-digit?:end/disp8
# otherwise return true # otherwise return true

Binary file not shown.

View File

@ -37,7 +37,7 @@
# 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 and argv[1] == "test" then return run_tests() # - if argc > 1 and argv[1] == "test", then return run_tests()
# . argc > 1 # . argc > 1
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 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 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. # '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> get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
# pseudocode: # pseudocode:
# if !is-digit?(Look) expected(ed, err, "integer") # if (!is-digit?(Look)) expected(ed, err, "integer")
# do # do
# if out->write >= out->length # if (out->write >= out->length)
# write(err, "Error: too many digits in number\n") # write(err, "Error: too many digits in number\n")
# stop(ed, 1) # stop(ed, 1)
# out->data[out->write] = LSB(Look) # out->data[out->write] = LSB(Look)
# ++out->write # ++out->write
# Look = get-char(in) # 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 # 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. # 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 # . 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 is-digit?(Look) expected(ed, err, "integer") # - if (is-digit?(Look)) expected(ed, err, "integer")
# . 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
@ -234,7 +234,7 @@ get-num: # in : (address buffered-file), out : (address stream), err : fd or (a
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 # . if (EAX == 0)
3d/compare-EAX 0/imm32 3d/compare-EAX 0/imm32
75/jump-if-not-equal $get-num:main/disp8 75/jump-if-not-equal $get-num:main/disp8
# . expected(ed, err, "integer") # . expected(ed, err, "integer")
@ -265,7 +265,7 @@ $get-num:main:
# EDX = out->length # EDX = out->length
8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX
$get-num:loop: $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 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # 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, msg) # TODO: show full number # . error(ed, err, msg) # TODO: show full number
@ -291,7 +291,7 @@ $get-num:loop-stage2:
e8/call get-char/disp32 e8/call get-char/disp32
# . . discard args # . . discard args
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
# if is-digit?(Look) loop # if (is-digit?(Look)) loop
# . 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
@ -299,7 +299,7 @@ $get-num:loop-stage2:
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 != 0) loop
3d/compare-EAX 0/imm32 3d/compare-EAX 0/imm32
0f 85/jump-if-not-equal $get-num:loop/disp32 0f 85/jump-if-not-equal $get-num:loop/disp32
$get-num:loop-end: $get-num:loop-end:
@ -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 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
# EAX = false # EAX = false
b8/copy-to-EAX 0/imm32 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) 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 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) 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 7f/jump-if-greater $is-digit?:end/disp8
# otherwise return true # otherwise return true

Binary file not shown.

View File

@ -21,7 +21,7 @@
# 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 and argv[1] == "test" then return run_tests() # - if argc > 1 and argv[1] == "test", then return run_tests()
# . argc > 1 # . argc > 1
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 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 7e/jump-if-lesser-or-equal $run-main/disp8

Binary file not shown.

Binary file not shown.

View File

@ -25,7 +25,7 @@
# main: run tests if necessary, convert stdin if not # main: run tests if necessary, convert stdin 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 and argv[1] == "test" then return run_tests() # - if argc > 1 and argv[1] == "test", then return run_tests()
# . argc > 1 # . argc > 1
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 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 7e/jump-if-lesser-or-equal $run-main/disp8
@ -73,7 +73,7 @@ convert: # in : (address buffered-file), out : (address buffered-file), err : (
# pseudocode: # pseudocode:
# repeatedly # repeatedly
# EAX = convert-next-octet(in, err, ed) # EAX = convert-next-octet(in, err, ed)
# if EAX == 0xffffffff break # eof # if (EAX == 0xffffffff) break # eof
# write-byte(out, AL) # write-byte(out, AL)
# flush(out) # flush(out)
# #
@ -92,7 +92,7 @@ $convert:loop:
e8/call convert-next-octet/disp32 e8/call convert-next-octet/disp32
# . . discard first 2 args # . . discard first 2 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 == 0xffffffff break # if (EAX == 0xffffffff) break
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX
74/jump-if-equal $convert:loop-end/disp8 74/jump-if-equal $convert:loop-end/disp8
# write-byte(out, AL) # write-byte(out, AL)
@ -489,10 +489,10 @@ scan-next-byte: # in : (address buffered-file), err : (address buffered-file),
# pseudocode: # pseudocode:
# repeatedly # repeatedly
# EAX = read-byte(in) # EAX = read-byte(in)
# if EAX == 0xffffffff return EAX # if (EAX == 0xffffffff) return EAX
# if is-hex-digit?(EAX) return EAX # if (is-hex-digit?(EAX)) return EAX
# if EAX == ' ' or '\t' or '\n' continue # if (EAX == ' ' or '\t' or '\n') continue
# if EAX == '#' skip-until-newline(in) # if (EAX == '#') skip-until-newline(in)
# else error-byte(ed, err, "invalid byte: " EAX) # else error-byte(ed, err, "invalid byte: " EAX)
# #
# . prolog # . prolog
@ -510,7 +510,7 @@ $scan-next-byte:loop:
# if (EAX == 0xffffffff) return EAX # if (EAX == 0xffffffff) return EAX
3d/compare-with-EAX 0xffffffff/imm32 3d/compare-with-EAX 0xffffffff/imm32
74/jump-if-equal $scan-next-byte:end/disp8 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 # . save EAX for now
50/push-EAX 50/push-EAX
# . is-hex-digit?(EAX) # . is-hex-digit?(EAX)
@ -527,17 +527,17 @@ $scan-next-byte:loop:
# . check whether to return # . check whether to return
75/jump-if-not-equal $scan-next-byte:end/disp8 75/jump-if-not-equal $scan-next-byte:end/disp8
$scan-next-byte:check1: $scan-next-byte:check1:
# if EAX == ' ' continue # if (EAX == ' ') continue
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x20/imm32 # compare EAX 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x20/imm32 # compare EAX
74/jump-if-equal $scan-next-byte:loop/disp8 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 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x9/imm32 # compare EAX
74/jump-if-equal $scan-next-byte:loop/disp8 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 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX
74/jump-if-equal $scan-next-byte:loop/disp8 74/jump-if-equal $scan-next-byte:loop/disp8
$scan-next-byte:check2: $scan-next-byte:check2:
# if EAX == '#' skip-until-newline(in) # if (EAX == '#') skip-until-newline(in)
3d/compare-with-EAX 0x23/imm32 3d/compare-with-EAX 0x23/imm32
75/jump-if-not-equal $scan-next-byte:check3/disp8 75/jump-if-not-equal $scan-next-byte:check3/disp8
# . skip-until-newline(in) # . skip-until-newline(in)
@ -1413,8 +1413,8 @@ skip-until-newline: # in : (address buffered-file) -> <void>
# push EAX # push EAX
# repeatedly: # repeatedly:
# EAX = read-byte(in) # EAX = read-byte(in)
# if EAX == 0xffffffff break # if (EAX == 0xffffffff) break
# if EAX == 0x0a break # if (EAX == 0x0a) break
# pop EAX # pop EAX
# . prolog # . prolog
55/push-EBP 55/push-EBP
@ -1429,10 +1429,10 @@ $skip-until-newline:loop:
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
# . if EAX == 0xffffffff break # . if (EAX == 0xffffffff) break
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX
74/jump-if-equal $skip-until-newline:end/disp8 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 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX
75/jump-if-not-equal $skip-until-newline:loop/disp8 75/jump-if-not-equal $skip-until-newline:loop/disp8
$skip-until-newline:end: $skip-until-newline:end:

Binary file not shown.

View File

@ -28,7 +28,7 @@
# main: run tests if necessary, convert stdin if not # main: run tests if necessary, convert stdin 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 and argv[1] == "test" then return run_tests() # - if argc > 1 and argv[1] == "test", then return run_tests()
# . argc > 1 # . argc > 1
81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP 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 7e/jump-if-lesser-or-equal $run-main/disp8
@ -88,7 +88,7 @@ convert: # in : (address buffered-file), out : (address buffered-file) -> <void
# repeatedly # repeatedly
# clear-stream(line) # clear-stream(line)
# EAX = read-line(in, line) # EAX = read-line(in, line)
# if EAX == EOF break # if (EAX == EOF) break
# convert-instruction(line, out) # convert-instruction(line, out)
# flush(out) # flush(out)
# #
@ -119,7 +119,7 @@ $convert:loop:
e8/call convert-instruction/disp32 e8/call convert-instruction/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 == 0xffffffff break # if (EAX == 0xffffffff) break
3d/compare-with-EAX 0xffffffff/imm32 3d/compare-with-EAX 0xffffffff/imm32
74/jump-if-equal $convert:break/disp8 74/jump-if-equal $convert:break/disp8
# convert-instruction(line, out) # convert-instruction(line, out)
@ -200,10 +200,10 @@ $convert:end:
convert-instruction: # line : (address stream byte), out : (address buffered-file) -> <void> convert-instruction: # line : (address stream byte), out : (address buffered-file) -> <void>
# pseudocode: # pseudocode:
# word-slice = next-word # word-slice = next-word
# if *word-slice->start == '#' # if (*word-slice->start == '#')
# write-stream-buffered(out, line) # write-stream-buffered(out, line)
# return # return
# if starts-with(word-slice, '==') # if (starts-with(word-slice, '=='))
# write-stream-buffered(out, line) # write-stream-buffered(out, line)
# return # 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 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 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 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] # . EAX = line->data[line->read]
31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX
8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/AL 0xc/disp8 . # copy byte at *(ESI+ECX+12) to AL 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 # curr = twig->end
# while true: # while true:
# twig = next-token-from-slice(curr, word->end, '/') # twig = next-token-from-slice(curr, word->end, '/')
# if twig.empty() break # if (twig.empty()) break
# if slice-equal?(twig, s) return true # if (slice-equal?(twig, s)) return true
# curr = twig->end # curr = twig->end
# return false # return false
# . prolog # . prolog
@ -813,7 +813,7 @@ $has-metadata?:loop:
e8/call next-token-from-slice/disp32 e8/call next-token-from-slice/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
# if slice-empty?(twig) return false # if (slice-empty?(twig)) return false
# . EAX = slice-empty?(twig) # . EAX = slice-empty?(twig)
# . . push args # . . push args
57/push-EDI 57/push-EDI
@ -824,7 +824,7 @@ $has-metadata?:loop:
# . if (EAX != 0) return false # . if (EAX != 0) return false
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
75/compare-if-not-equal $has-metadata?:false/disp8 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) # . EAX = slice-equal?(twig, s)
# . . push args # . . push args
ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 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 e8/call next-token-from-slice/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
# 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) # . is-hex-int?(name)
# . . push args # . . push args
57/push-EDI 57/push-EDI
@ -1066,7 +1066,7 @@ emit: # out : (address buffered-file), word : (address slice), width : int
e8/call is-hex-int?/disp32 e8/call is-hex-int?/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 # . if (EAX == 0)
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
75/jump-if-not-equal $emit:hex-int/disp8 75/jump-if-not-equal $emit:hex-int/disp8
# . write-slice(out, word) # . write-slice(out, word)

View File

@ -38,7 +38,6 @@ argv-equal: # (s1, s2) : null-terminated ascii strings -> EAX : boolean
# initialize s1 (ECX) and s2 (EDX) # 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 . 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 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: $argv-equal:loop:
# c1/EAX, c2/EBX = *s1, *s2 # c1/EAX, c2/EBX = *s1, *s2
b8/copy-to-EAX 0/imm32 b8/copy-to-EAX 0/imm32

Binary file not shown.

View File

@ -28,7 +28,28 @@
# 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
# 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 # . 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
@ -38,72 +59,57 @@ kernel-string-equal: # s : null-terminated ascii string, benchmark : length-pre
53/push-EBX 53/push-EBX
56/push-ESI 56/push-ESI
57/push-EDI 57/push-EDI
# s1/EDI = s
# 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
8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI 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 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 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 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 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 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 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 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 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 # if (c1 == 0) return false
3d/compare-EAX 0/imm32 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 # if (c1 != c2) return false
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX 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 75/jump-if-not-equal $kernel-string-equal?:false/disp8
# ++s1, ++s2, ++i # ++i
41/inc-ECX 41/inc-ECX
46/inc-ESI # ++s1
47/inc-EDI 47/inc-EDI
# end while # ++s2
eb/jump $kernel-string-equal:loop/disp8 46/inc-ESI
$kernel-string-equal:break: eb/jump $kernel-string-equal?:loop/disp8
# if (*s/EDI == 0) return true $kernel-string-equal?:break:
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 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 3d/compare-EAX 0/imm32
75/jump-if-not-equal $kernel-string-equal:false/disp8 75/jump-if-not-equal $kernel-string-equal?:false/disp8
$kernel-string-equal?:true:
b8/copy-to-EAX 1/imm32 b8/copy-to-EAX 1/imm32
$kernel-string-equal:true: eb/jump $kernel-string-equal?:end/disp8
eb/jump $kernel-string-equal:end/disp8 $kernel-string-equal?:false:
# return false
$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
# end # . 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
@ -111,12 +117,12 @@ $kernel-string-equal:end:
# - tests # - tests
test-compare-null-kernel-string-with-empty-array: test-compare-null-kernel-string-with-empty-array:
# EAX = kernel-string-equal(Null-kernel-string, "") # EAX = kernel-string-equal?(Null-kernel-string, "")
# . . 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
# check-ints-equal(EAX, 1, msg) # check-ints-equal(EAX, 1, msg)
@ -131,12 +137,12 @@ test-compare-null-kernel-string-with-empty-array:
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
# check-ints-equal(EAX, 0, msg) # check-ints-equal(EAX, 0, msg)
@ -151,12 +157,12 @@ test-compare-null-kernel-string-with-non-empty-array:
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?(_test-Abc-kernel-string, "Abc")
# . . push args # . . push args
68/push "Abc"/imm32 68/push "Abc"/imm32
68/push Abc-kernel-string/imm32 68/push _test-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
# check-ints-equal(EAX, 1, msg) # check-ints-equal(EAX, 1, msg)
@ -171,12 +177,12 @@ test-compare-kernel-string-with-equal-array:
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?(_test-Abc-kernel-string, "Adc")
# . . push args # . . push args
68/push "Adc"/imm32 68/push "Adc"/imm32
68/push Abc-kernel-string/imm32 68/push _test-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
# check-ints-equal(EAX, 0, msg) # check-ints-equal(EAX, 0, msg)
@ -191,12 +197,12 @@ test-compare-kernel-string-with-inequal-array:
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?(_test-Abc-kernel-string, "")
# . . push args # . . push args
68/push ""/imm32 68/push ""/imm32
68/push Abc-kernel-string/imm32 68/push _test-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
# check-ints-equal(EAX, 0, msg) # check-ints-equal(EAX, 0, msg)
@ -211,12 +217,12 @@ test-compare-kernel-string-with-empty-array:
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?(_test-Abc-kernel-string, "Ab")
# . . push args # . . push args
68/push "Ab"/imm32 68/push "Ab"/imm32
68/push Abc-kernel-string/imm32 68/push _test-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
# check-ints-equal(EAX, 0, msg) # check-ints-equal(EAX, 0, msg)
@ -231,12 +237,12 @@ test-compare-kernel-string-with-shorter-array:
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?(_test-Abc-kernel-string, "Abcd")
# . . push args # . . push args
68/push "Abcd"/imm32 68/push "Abcd"/imm32
68/push Abc-kernel-string/imm32 68/push _test-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
# check-ints-equal(EAX, 0, msg) # 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 # 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 . . . 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 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 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-stderr('.') # . write-stderr('.')
@ -344,7 +350,8 @@ Newline:
# for kernel-string-equal tests # for kernel-string-equal tests
Null-kernel-string: Null-kernel-string:
00/null 00/null
Abc-kernel-string:
_test-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

@ -18,7 +18,7 @@
b9/copy-to-ECX 1/imm32 b9/copy-to-ECX 1/imm32
$loop: $loop:
# while (counter <= 10) # if (counter > 10) break
81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0xa/imm32 # compare ECX 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0xa/imm32 # compare ECX
7f/jump-if-greater $exit/disp8 7f/jump-if-greater $exit/disp8
# result += counter # result += counter

View File

@ -42,7 +42,7 @@ ascii-length: # s : (address array byte) -> n/EAX
$ascii-length-loop: $ascii-length-loop:
# var c/ECX = *s # var c/ECX = *s
8a/copy 0/mod/* 2/rm32/EDX . . . 1/r32/ECX . . # copy byte at *EDX to lower byte of ECX 8a/copy 0/mod/* 2/rm32/EDX . . . 1/r32/ECX . . # copy byte at *EDX to lower byte of ECX
# if c == '\0' break # if (c == '\0') break
81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX
74/jump-if-equal $ascii-length-ret/disp8 74/jump-if-equal $ascii-length-ret/disp8
# ++s # ++s

View File

@ -74,6 +74,7 @@ Opcodes currently supported by SubX:
bf: copy imm32 to EDI (mov) bf: copy imm32 to EDI (mov)
c1: shift rm32 by imm8 bits depending on subop (sal/sar/shl/shr) c1: shift rm32 by imm8 bits depending on subop (sal/sar/shl/shr)
c3: return from most recent unfinished call (ret) c3: return from most recent unfinished call (ret)
c6: copy imm8 to r8/m8-at-r32 (mov)
c7: copy imm32 to rm32 (mov) c7: copy imm32 to rm32 (mov)
cd: software interrupt (int) cd: software interrupt (int)
d3: shift rm32 by CL bits depending on subop (sal/sar/shl/shr) d3: shift rm32 by CL bits depending on subop (sal/sar/shl/shr)