ae470b42f1
This was surprisingly hard; bugs discovered all over the place.
939 lines
48 KiB
Plaintext
939 lines
48 KiB
Plaintext
# some utilities for converting numbers from hex
|
|
# lowercase letters only for now
|
|
|
|
== code
|
|
# instruction effective address register displacement immediate
|
|
# . op subop mod rm32 base index scale r32
|
|
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
|
|
|
is-hex-int?: # in: (addr slice) -> result/eax: boolean
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
51/push-ecx
|
|
52/push-edx
|
|
53/push-ebx
|
|
# ecx = s
|
|
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
|
|
# edx = s->end
|
|
8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx
|
|
# var curr/ecx: (addr byte) = s->start
|
|
8b/copy 0/mod/indirect 1/rm32/ecx . . . 1/r32/ecx . . # copy *ecx to ecx
|
|
# if s is empty return false
|
|
b8/copy-to-eax 0/imm32/false
|
|
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
|
|
73/jump-if-addr>= $is-hex-int?:end/disp8
|
|
# skip past leading '-'
|
|
# . if (*curr == '-') ++curr
|
|
31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
|
|
8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 3/r32/BL . . # copy byte at *ecx to BL
|
|
81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x2d/imm32/- # compare ebx
|
|
75/jump-if-!= $is-hex-int?:initial-0/disp8
|
|
# . ++curr
|
|
41/increment-ecx
|
|
# skip past leading '0x'
|
|
$is-hex-int?:initial-0:
|
|
# . if (*curr != '0') jump to loop
|
|
31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
|
|
8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 3/r32/BL . . # copy byte at *ecx to BL
|
|
81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x30/imm32/0 # compare ebx
|
|
75/jump-if-!= $is-hex-int?:loop/disp8
|
|
# . ++curr
|
|
41/increment-ecx
|
|
$is-hex-int?:initial-0x:
|
|
# . if (curr >= in->end) return true
|
|
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
|
|
73/jump-if-addr>= $is-hex-int?:true/disp8
|
|
# . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again
|
|
31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
|
|
8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 3/r32/BL . . # copy byte at *ecx to BL
|
|
81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x78/imm32/x # compare ebx
|
|
75/jump-if-!= $is-hex-int?:loop/disp8
|
|
# . ++curr
|
|
41/increment-ecx
|
|
$is-hex-int?:loop:
|
|
# if (curr >= in->end) return true
|
|
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
|
|
73/jump-if-addr>= $is-hex-int?:true/disp8
|
|
# var eax: boolean = is-hex-digit?(*curr)
|
|
# . . push args
|
|
8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
|
|
50/push-eax
|
|
# . . call
|
|
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
|
|
3d/compare-eax-and 0/imm32/false
|
|
74/jump-if-= $is-hex-int?:end/disp8
|
|
# ++curr
|
|
41/increment-ecx
|
|
# loop
|
|
eb/jump $is-hex-int?:loop/disp8
|
|
$is-hex-int?:true:
|
|
# return true
|
|
b8/copy-to-eax 1/imm32/true
|
|
$is-hex-int?:end:
|
|
# . restore registers
|
|
5b/pop-to-ebx
|
|
5a/pop-to-edx
|
|
59/pop-to-ecx
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-is-hex-int:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "34"
|
|
b8/copy-to-eax "34"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = is-hex-int?(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call is-hex-int?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-is-hex-int"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-is-hex-int-handles-letters:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "34a"
|
|
b8/copy-to-eax "34a"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = is-hex-int?(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call is-hex-int?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-is-hex-int-handles-letters"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-is-hex-int-with-trailing-char:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "34q"
|
|
b8/copy-to-eax "34q"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = is-hex-int?(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call is-hex-int?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-is-hex-int-with-trailing-char"/imm32
|
|
68/push 0/imm32/false
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-is-hex-int-with-leading-char:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "q34"
|
|
b8/copy-to-eax "q34"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = is-hex-int?(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call is-hex-int?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-is-hex-int-with-leading-char"/imm32
|
|
68/push 0/imm32/false
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-is-hex-int-empty:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# var slice/ecx: slice = ""
|
|
68/push 0/imm32
|
|
68/push 0/imm32
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = is-hex-int?(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call is-hex-int?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-is-hex-int-empty"/imm32
|
|
68/push 0/imm32/false
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-is-hex-int-handles-0x-prefix:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "0x3a"
|
|
b8/copy-to-eax "0x3a"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = is-hex-int?(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call is-hex-int?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-is-hex-int-handles-0x-prefix"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-is-hex-int-handles-negative:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "-34a"
|
|
b8/copy-to-eax "-34a"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = is-hex-int?(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call is-hex-int?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-is-hex-int-handles-negative"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-is-hex-int-handles-negative-0x-prefix:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "-0x3a"
|
|
b8/copy-to-eax "-0x3a"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = is-hex-int?(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call is-hex-int?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-is-hex-int-handles-negative-0x-prefix"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
parse-hex-int: # in: (addr array byte) -> result/eax: int
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
51/push-ecx
|
|
52/push-edx
|
|
# eax = in
|
|
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
|
|
# var curr/ecx: (addr byte) = &in->data
|
|
8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy eax+4 to ecx
|
|
# var max/edx: (addr byte) = &in->data[in->size]
|
|
# . edx = in->size
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx
|
|
# . edx = in->data + in->size
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx
|
|
# return parse-hex-int-helper(curr, max)
|
|
# . . push args
|
|
52/push-edx
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call parse-hex-int-helper/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
$parse-hex-int:end:
|
|
# . restore registers
|
|
5a/pop-to-edx
|
|
59/pop-to-ecx
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
parse-hex-int-from-slice: # in: (addr slice) -> result/eax: int
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
51/push-ecx
|
|
52/push-edx
|
|
# ecx = in
|
|
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
|
|
# var max/edx: (addr byte) = in->end
|
|
8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx
|
|
# var curr/ecx: (addr byte) = in->start
|
|
8b/copy 0/mod/indirect 1/rm32/ecx . . . 1/r32/ecx . . # copy *ecx to ecx
|
|
# return parse-hex-int-helper(curr, max)
|
|
# . . push args
|
|
52/push-edx
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call parse-hex-int-helper/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
$parse-hex-int-from-slice:end:
|
|
# . restore registers
|
|
5a/pop-to-edx
|
|
59/pop-to-ecx
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
parse-hex-int-helper: # start: (addr byte), end: (addr byte) -> result/eax: int
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
51/push-ecx
|
|
52/push-edx
|
|
53/push-ebx
|
|
56/push-esi
|
|
# var curr/ecx: (addr byte) = start
|
|
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
|
|
# edx = max
|
|
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx
|
|
# var result/ebx: int = 0
|
|
31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
|
|
# var negate?/esi: boolean = false
|
|
31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi
|
|
$parse-hex-int-helper:negative:
|
|
# if (*curr == '-') ++curr, negate = true
|
|
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
|
|
8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
|
|
3d/compare-eax-and 0x2d/imm32/-
|
|
75/jump-if-!= $parse-hex-int-helper:initial-0/disp8
|
|
# . ++curr
|
|
41/increment-ecx
|
|
# . negate = true
|
|
be/copy-to-esi 1/imm32/true
|
|
$parse-hex-int-helper:initial-0:
|
|
# skip past leading '0x'
|
|
# . if (*curr != '0') jump to loop
|
|
8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
|
|
3d/compare-eax-and 0x30/imm32/0
|
|
75/jump-if-!= $parse-hex-int-helper:loop/disp8
|
|
# . ++curr
|
|
41/increment-ecx
|
|
$parse-hex-int-helper:initial-0x:
|
|
# . if (curr >= in->end) return result
|
|
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
|
|
73/jump-if-addr>= $parse-hex-int-helper:end/disp8
|
|
# . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again
|
|
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
|
|
8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
|
|
3d/compare-eax-and 0x78/imm32/x
|
|
75/jump-if-!= $parse-hex-int-helper:loop/disp8
|
|
# . ++curr
|
|
41/increment-ecx
|
|
$parse-hex-int-helper:loop:
|
|
# if (curr >= in->end) break
|
|
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
|
|
73/jump-if-addr>= $parse-hex-int-helper:negate/disp8
|
|
# var eax: int = from-hex-char(*curr)
|
|
# . . copy arg to eax
|
|
8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
|
|
# . . call
|
|
e8/call from-hex-char/disp32
|
|
# result = result * 16 + eax
|
|
c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 4/imm8 # shift ebx left by 4 bits
|
|
01/add 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # add eax to ebx
|
|
# ++curr
|
|
41/increment-ecx
|
|
# loop
|
|
eb/jump $parse-hex-int-helper:loop/disp8
|
|
$parse-hex-int-helper:negate:
|
|
# if (negate?) result = -result
|
|
81 7/subop/compare 3/mod/direct 6/rm32/esi . . . . . 0/imm32/false # compare esi
|
|
74/jump-if-= $parse-hex-int-helper:end/disp8
|
|
f7 3/subop/negate 3/mod/direct 3/rm32/ebx . . . . . . # negate ebx
|
|
$parse-hex-int-helper:end:
|
|
# return result
|
|
89/copy 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # copy ebx to eax
|
|
# . restore registers
|
|
5e/pop-to-esi
|
|
5b/pop-to-ebx
|
|
5a/pop-to-edx
|
|
59/pop-to-ecx
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-parse-hex-int-from-slice-single-digit:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "a"
|
|
b8/copy-to-eax "a"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = parse-hex-int-from-slice(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call parse-hex-int-from-slice/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0xa, msg)
|
|
# . . push args
|
|
68/push "F - test-parse-hex-int-from-slice-single-digit"/imm32
|
|
68/push 0xa/imm32
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-parse-hex-int-from-slice-multi-digit:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "34a"
|
|
b8/copy-to-eax "34a"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = parse-hex-int-from-slice(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call parse-hex-int-from-slice/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0x34a, msg)
|
|
# . . push args
|
|
68/push "F - test-parse-hex-int-from-slice-multi-digit"/imm32
|
|
68/push 0x34a/imm32
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-parse-hex-int-from-slice-0x-prefix:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "0x34"
|
|
b8/copy-to-eax "0x34"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = parse-hex-int-from-slice(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call parse-hex-int-from-slice/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0x34, msg)
|
|
# . . push args
|
|
68/push "F - test-parse-hex-int-from-slice-0x-prefix"/imm32
|
|
68/push 0x34/imm32
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-parse-hex-int-from-slice-zero:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "0"
|
|
b8/copy-to-eax "0"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = parse-hex-int-from-slice(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call parse-hex-int-from-slice/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-parse-hex-int-from-slice-zero"/imm32
|
|
68/push 0/imm32
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-parse-hex-int-from-slice-0-prefix:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "03"
|
|
b8/copy-to-eax "03"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = parse-hex-int-from-slice(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call parse-hex-int-from-slice/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0x3, msg)
|
|
# . . push args
|
|
68/push "F - test-parse-hex-int-from-slice-0-prefix"/imm32
|
|
68/push 0x3/imm32
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-parse-hex-int-from-slice-negative:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# (eax..ecx) = "-03"
|
|
b8/copy-to-eax "-03"/imm32
|
|
8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
|
|
8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
|
|
05/add-to-eax 4/imm32
|
|
# var slice/ecx: slice = {eax, ecx}
|
|
51/push-ecx
|
|
50/push-eax
|
|
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
|
|
# eax = parse-hex-int-from-slice(slice)
|
|
# . . push args
|
|
51/push-ecx
|
|
# . . call
|
|
e8/call parse-hex-int-from-slice/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, -3, msg)
|
|
# . . push args
|
|
68/push "F - test-parse-hex-int-from-slice-negative"/imm32
|
|
68/push -3/imm32
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
is-hex-digit?: # c: byte -> result/eax: boolean
|
|
# . prologue
|
|
55/push-ebp
|
|
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
|
|
# . save registers
|
|
51/push-ecx
|
|
# ecx = c
|
|
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
|
|
# return false if c < '0'
|
|
81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x30/imm32 # compare ecx
|
|
7c/jump-if-< $is-hex-digit?:false/disp8
|
|
# return true if c <= '9'
|
|
81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x39/imm32 # compare ecx
|
|
7e/jump-if-<= $is-hex-digit?:true/disp8
|
|
# drop case
|
|
25/and-eax-with 0x5f/imm32
|
|
# return false if c > 'f'
|
|
81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x66/imm32 # compare ecx
|
|
7f/jump-if-> $is-hex-digit?:false/disp8
|
|
# return true if c >= 'a'
|
|
81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x61/imm32 # compare ecx
|
|
7d/jump-if->= $is-hex-digit?:true/disp8
|
|
# otherwise return false
|
|
$is-hex-digit?:false:
|
|
b8/copy-to-eax 0/imm32/false
|
|
eb/jump $is-hex-digit?:end/disp8
|
|
$is-hex-digit?:true:
|
|
b8/copy-to-eax 1/imm32/true
|
|
$is-hex-digit?:end:
|
|
# . restore registers
|
|
59/pop-to-ecx
|
|
# . epilogue
|
|
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-hex-below-0:
|
|
# eax = is-hex-digit?(0x2f)
|
|
# . . push args
|
|
68/push 0x2f/imm32
|
|
# . . call
|
|
e8/call is-hex-digit?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-hex-below-0"/imm32
|
|
68/push 0/imm32/false
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
c3/return
|
|
|
|
test-hex-0-to-9:
|
|
# eax = is-hex-digit?(0x30)
|
|
# . . push args
|
|
68/push 0x30/imm32
|
|
# . . call
|
|
e8/call is-hex-digit?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-hex-at-0"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# eax = is-hex-digit?(0x39)
|
|
# . . push args
|
|
68/push 0x39/imm32
|
|
# . . call
|
|
e8/call is-hex-digit?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-hex-at-9"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
c3/return
|
|
|
|
test-hex-above-9-to-a:
|
|
# eax = is-hex-digit?(0x3a)
|
|
# . . push args
|
|
68/push 0x3a/imm32
|
|
# . . call
|
|
e8/call is-hex-digit?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-hex-above-9-to-a"/imm32
|
|
68/push 0/imm32/false
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
c3/return
|
|
|
|
test-hex-a-to-f:
|
|
# eax = is-hex-digit?(0x61)
|
|
# . . push args
|
|
68/push 0x61/imm32
|
|
# . . call
|
|
e8/call is-hex-digit?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-hex-at-a"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
# eax = is-hex-digit?(0x66)
|
|
# . . push args
|
|
68/push 0x66/imm32
|
|
# . . call
|
|
e8/call is-hex-digit?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 1, msg)
|
|
# . . push args
|
|
68/push "F - test-hex-at-f"/imm32
|
|
68/push 1/imm32/true
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
c3/return
|
|
|
|
test-hex-above-f:
|
|
# eax = is-hex-digit?(0x67)
|
|
# . . push args
|
|
68/push 0x67/imm32
|
|
# . . call
|
|
e8/call is-hex-digit?/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# check-ints-equal(eax, 0, msg)
|
|
# . . push args
|
|
68/push "F - test-hex-above-f"/imm32
|
|
68/push 0/imm32/false
|
|
50/push-eax
|
|
# . . call
|
|
e8/call check-ints-equal/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
|
|
c3/return
|
|
|
|
from-hex-char: # in/eax: byte -> out/eax: nibble
|
|
$from-hex-char:check0:
|
|
# if (eax < '0') goto abort
|
|
3d/compare-eax-with 0x30/imm32/0
|
|
7c/jump-if-< $from-hex-char:abort/disp8
|
|
$from-hex-char:check1:
|
|
# if (eax > 'f') goto abort
|
|
3d/compare-eax-with 0x66/imm32/f
|
|
7f/jump-if-> $from-hex-char:abort/disp8
|
|
$from-hex-char:check2:
|
|
# if (eax > '9') goto next check
|
|
3d/compare-eax-with 0x39/imm32/9
|
|
7f/jump-if-> $from-hex-char:check3/disp8
|
|
$from-hex-char:digit:
|
|
# return eax - '0'
|
|
2d/subtract-from-eax 0x30/imm32/0
|
|
c3/return
|
|
$from-hex-char:check3:
|
|
# if (eax < 'a') goto abort
|
|
3d/compare-eax-with 0x61/imm32/a
|
|
7c/jump-if-< $from-hex-char:abort/disp8
|
|
$from-hex-char:letter:
|
|
# return eax - ('a'-10)
|
|
2d/subtract-from-eax 0x57/imm32/a-10
|
|
c3/return
|
|
|
|
$from-hex-char:abort:
|
|
# . _write(2/stderr, error)
|
|
# . . push args
|
|
68/push "invalid hex char: "/imm32
|
|
68/push 2/imm32/stderr
|
|
# . . call
|
|
e8/call _write/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . clear-stream($Stderr->buffer)
|
|
# . . save eax
|
|
50/push-eax
|
|
# . . push args
|
|
68/push $Stderr->buffer/imm32
|
|
# . . call
|
|
e8/call clear-stream/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# . . restore eax
|
|
58/pop-to-eax
|
|
# . write-int32-hex-buffered(Stderr, eax)
|
|
# . . push args
|
|
50/push-eax
|
|
68/push Stderr/imm32
|
|
# . . call
|
|
e8/call write-int32-hex-buffered/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . flush(Stderr)
|
|
# . . push args
|
|
68/push Stderr/imm32
|
|
# . . call
|
|
e8/call flush/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
|
|
# . _write(2/stderr, "\n")
|
|
# . . push args
|
|
68/push Newline/imm32
|
|
68/push 2/imm32/stderr
|
|
# . . call
|
|
e8/call _write/disp32
|
|
# . . discard args
|
|
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
|
|
# . syscall(exit, 1)
|
|
bb/copy-to-ebx 1/imm32
|
|
e8/call syscall_exit/disp32
|
|
# never gets here
|
|
|
|
# . . vim:nowrap:textwidth=0
|