4668
This commit is contained in:
parent
03d50cc83c
commit
94ad882e82
|
@ -29,10 +29,7 @@ cerr << " instructions\n";
|
|||
|
||||
:(scenario pack_immediate_constants)
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
bb 0x2a/imm32 # copy 42 to EBX
|
||||
bb 0x2a/imm32
|
||||
+transform: packing instruction 'bb 0x2a/imm32'
|
||||
+transform: instruction after packing: 'bb 2a 00 00 00'
|
||||
+run: copy imm32 0x0000002a to EBX
|
||||
|
@ -335,40 +332,31 @@ void transform(const string& text_bytes) {
|
|||
|
||||
:(scenario pack_imm32_large)
|
||||
== 0x1
|
||||
b9 0x080490a7/imm32 # copy to ECX
|
||||
b9 0x080490a7/imm32
|
||||
+transform: packing instruction 'b9 0x080490a7/imm32'
|
||||
+transform: instruction after packing: 'b9 a7 90 04 08'
|
||||
|
||||
:(scenario pack_immediate_constants_hex)
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
bb 0x2a/imm32 # copy 42 to EBX
|
||||
+transform: packing instruction 'bb 0x2a/imm32'
|
||||
+transform: instruction after packing: 'bb 2a 00 00 00'
|
||||
+run: copy imm32 0x0000002a to EBX
|
||||
b9 0x2a/imm32
|
||||
+transform: packing instruction 'b9 0x2a/imm32'
|
||||
+transform: instruction after packing: 'b9 2a 00 00 00'
|
||||
+run: copy imm32 0x0000002a to ECX
|
||||
|
||||
:(scenarios transform)
|
||||
:(scenario pack_silently_ignores_non_hex)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
bb foo/imm32 # copy to EBX
|
||||
+transform: packing instruction 'bb foo/imm32'
|
||||
b9 foo/imm32
|
||||
+transform: packing instruction 'b9 foo/imm32'
|
||||
# no change (we're just not printing metadata to the trace)
|
||||
+transform: instruction after packing: 'bb foo'
|
||||
+transform: instruction after packing: 'b9 foo'
|
||||
:(scenarios run)
|
||||
|
||||
:(scenario pack_flags_bad_hex)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
bb 0xfoo/imm32 # copy to EBX
|
||||
b9 0xfoo/imm32
|
||||
+error: not a number: 0xfoo
|
||||
|
||||
//:: helpers
|
||||
|
|
|
@ -4,10 +4,7 @@
|
|||
:(scenario check_missing_imm8_operand)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
cd # int ??
|
||||
cd # int ??
|
||||
+error: 'cd' (software interrupt): missing imm8 operand
|
||||
|
||||
:(before "Pack Operands(segment code)")
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
:(scenario segment_name)
|
||||
== code
|
||||
05/add 0x0d0c0b0a/imm32 # add 0x0d0c0b0a to EAX
|
||||
05/add-to-EAX 0x0d0c0b0a/imm32
|
||||
# code starts at 0x08048000 + p_offset, which is 0x54 for a single-segment binary
|
||||
+load: 0x09000054 -> 05
|
||||
+load: 0x09000055 -> 0a
|
||||
|
@ -65,9 +65,9 @@ if (Currently_parsing_named_segment) {
|
|||
|
||||
:(scenario repeated_segment_merges_data)
|
||||
== code
|
||||
05/add 0x0d0c0b0a/imm32 # add 0x0d0c0b0a to EAX
|
||||
05/add-to-EAX 0x0d0c0b0a/imm32
|
||||
== code
|
||||
2d/subtract 0xddccbbaa/imm32 # subtract 0xddccbbaa from EAX
|
||||
2d/subtract-from-EAX 0xddccbbaa/imm32
|
||||
+parse: new segment 'code'
|
||||
+parse: prepending to segment 'code'
|
||||
+load: 0x09000054 -> 2d
|
||||
|
|
|
@ -26,7 +26,7 @@ if (SIZE(s) == 2) return true;
|
|||
:(scenario pack_immediate_ignores_single_byte_nondigit_operand)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
b9/copy a/imm32 # copy to ECX
|
||||
b9/copy a/imm32
|
||||
+transform: packing instruction 'b9/copy a/imm32'
|
||||
# no change (we're just not printing metadata to the trace)
|
||||
+transform: instruction after packing: 'b9 a'
|
||||
|
@ -34,7 +34,7 @@ b9/copy a/imm32 # copy to ECX
|
|||
:(scenario pack_immediate_ignores_3_hex_digit_operand)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
b9/copy aaa/imm32 # copy to ECX
|
||||
b9/copy aaa/imm32
|
||||
+transform: packing instruction 'b9/copy aaa/imm32'
|
||||
# no change (we're just not printing metadata to the trace)
|
||||
+transform: instruction after packing: 'b9 aaa'
|
||||
|
@ -42,7 +42,7 @@ b9/copy aaa/imm32 # copy to ECX
|
|||
:(scenario pack_immediate_ignores_non_hex_operand)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
b9/copy xxx/imm32 # copy to ECX
|
||||
b9/copy xxx/imm32
|
||||
+transform: packing instruction 'b9/copy xxx/imm32'
|
||||
# no change (we're just not printing metadata to the trace)
|
||||
+transform: instruction after packing: 'b9 xxx'
|
||||
|
@ -70,11 +70,8 @@ void check_valid_name(const string& s) {
|
|||
|
||||
:(scenario map_label)
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
loop:
|
||||
05 0x0d0c0b0a/imm32 # add to EAX
|
||||
05 0x0d0c0b0a/imm32
|
||||
+transform: label 'loop' is at address 1
|
||||
|
||||
:(before "End Level-2 Transforms")
|
||||
|
@ -207,18 +204,15 @@ string drop_last(const string& s) {
|
|||
|
||||
:(scenario multiple_labels_at)
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
# address 1
|
||||
loop:
|
||||
$loop2:
|
||||
# address 1 (labels take up no space)
|
||||
05 0x0d0c0b0a/imm32 # add to EAX
|
||||
05 0x0d0c0b0a/imm32
|
||||
# address 6
|
||||
eb $loop2/disp8
|
||||
eb $loop2/disp8
|
||||
# address 8
|
||||
eb $loop3/disp8
|
||||
eb $loop3/disp8
|
||||
# address 0xa
|
||||
$loop3:
|
||||
+transform: label 'loop' is at address 1
|
||||
|
@ -232,31 +226,22 @@ loop:
|
|||
:(scenario label_too_short)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
xz:
|
||||
05 0x0d0c0b0a/imm32 # add to EAX
|
||||
05 0x0d0c0b0a/imm32
|
||||
+error: 'xz' is two characters long which can look like raw hex bytes at a glance; use a different name
|
||||
|
||||
:(scenario label_hex)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
0xab:
|
||||
05 0x0d0c0b0a/imm32 # add to EAX
|
||||
05 0x0d0c0b0a/imm32
|
||||
+error: '0xab' looks like a hex number; use a different name
|
||||
|
||||
:(scenario label_negative_hex)
|
||||
% Hide_errors = true;
|
||||
== 0x1
|
||||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
-a: # indent to avoid looking like a trace_should_not_contain command for this scenario
|
||||
05 0x0d0c0b0a/imm32 # add to EAX
|
||||
05 0x0d0c0b0a/imm32
|
||||
+error: '-a' starts with '-', which can be confused with a negative number; use a different name
|
||||
|
||||
//: now that we have labels, we need to adjust segment size computation to
|
||||
|
@ -264,11 +249,11 @@ xz:
|
|||
|
||||
:(scenario segment_size_ignores_labels)
|
||||
== code # 0x09000074
|
||||
05/add 0x0d0c0b0a/imm32 # 5 bytes
|
||||
foo: # 0 bytes
|
||||
05/add 0x0d0c0b0a/imm32 # 5 bytes
|
||||
foo: # 0 bytes
|
||||
== data # 0x0a000079
|
||||
bar:
|
||||
00
|
||||
00
|
||||
+transform: segment 1 begins at address 0x0a000079
|
||||
|
||||
:(before "End num_bytes(curr) Special-cases")
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
:(scenario global_variable)
|
||||
== code
|
||||
b9/copy x/imm32 # copy to ECX
|
||||
b9 x/imm32
|
||||
== data
|
||||
x:
|
||||
00 00 00 00
|
||||
|
@ -129,7 +129,7 @@ bool has_metadata(const word& w, const string& m) {
|
|||
:(scenario global_variable_disallowed_in_jump)
|
||||
% Hide_errors = true;
|
||||
== code
|
||||
eb/jump x/disp8
|
||||
eb/jump x/disp8
|
||||
== data
|
||||
x:
|
||||
00 00 00 00
|
||||
|
@ -140,7 +140,7 @@ x:
|
|||
:(scenario global_variable_disallowed_in_call)
|
||||
% Hide_errors = true;
|
||||
== code
|
||||
e8/call x/disp32
|
||||
e8/call x/disp32
|
||||
== data
|
||||
x:
|
||||
00 00 00 00
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
:(scenario transform_literal_string)
|
||||
== code
|
||||
b8/copy "test"/imm32 # copy to EAX
|
||||
b8/copy "test"/imm32
|
||||
== data # need to manually create this for now
|
||||
+transform: -- move literal strings to data segment
|
||||
+transform: adding global variable '__subx_global_1' containing "test"
|
||||
|
|
|
@ -15,7 +15,7 @@ write-stderr: # s : (address array byte) -> <void>
|
|||
53/push-EBX
|
||||
# write(2/stderr, (data) s+4, (size) *s)
|
||||
# fd = 2 (stderr)
|
||||
bb/copy . . . . . . . 2/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 2/imm32
|
||||
# x = s+4
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX
|
||||
81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add to ECX
|
||||
|
@ -23,7 +23,7 @@ write-stderr: # s : (address array byte) -> <void>
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 2/r32/EDX 8/disp8 . # copy *(EBP+8) to EDX
|
||||
8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX
|
||||
# call write()
|
||||
b8/copy . . . . . . . 4/imm32/write # copy to EAX
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
# restore registers
|
||||
5b/pop-to-EBX
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
# exit(Num-test-failures)
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
||||
|
@ -63,15 +63,15 @@ kernel-string-equal: # s : null-terminated ascii string, benchmark : length-pre
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI
|
||||
81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 4/imm32 # add to ESI
|
||||
# initialize loop counter i into ECX
|
||||
b9/copy . . . . . . . 0/imm32/exit # copy to ECX
|
||||
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 0/imm32 # clear EAX
|
||||
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 0/imm32 # clear EBX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX
|
||||
# if (c1 == 0) return false
|
||||
3d/compare-EAX 0/imm32
|
||||
|
@ -87,16 +87,16 @@ $kernel-string-equal:loop:
|
|||
eb/jump $kernel-string-equal:loop/disp8
|
||||
$kernel-string-equal:break:
|
||||
# if (*s/EDI == 0) return true
|
||||
b8/copy 0/imm32 # clear EAX
|
||||
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
|
||||
3d/compare-EAX 0/imm32
|
||||
75/jump-if-not-equal $kernel-string-equal:false/disp8
|
||||
$kernel-string-equal:true:
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
eb/jump $kernel-string-equal:end/disp8
|
||||
# return false
|
||||
$kernel-string-equal:false:
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 0/imm32
|
||||
|
||||
$kernel-string-equal:end:
|
||||
# restore registers
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
# exit(EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
new-segment: # len : int -> address
|
||||
|
@ -31,11 +31,11 @@ new-segment: # len : int -> address
|
|||
# copy len to mmap-new-segment.len
|
||||
# TODO: compute mmap-new-segment+4 before runtime
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX
|
||||
bb/copy . . . . . . . mmap-new-segment/imm32 # copy to EBX
|
||||
bb/copy-to-EBX mmap-new-segment/imm32
|
||||
89/copy 1/mod/*+disp8 3/rm32/EBX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EBX+4)
|
||||
# mmap(mmap-new-segment)
|
||||
bb/copy . . . . . . . mmap-new-segment/imm32 # copy to EBX
|
||||
b8/copy . . . . . . . 0x5a/imm32/mmap # copy to EAX
|
||||
bb/copy-to-EBX mmap-new-segment/imm32
|
||||
b8/copy-to-EAX 0x5a/imm32/mmap
|
||||
cd/syscall 0x80/imm8
|
||||
# epilog
|
||||
5b/pop-to-EBX
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
# exit(Num-test-failures)
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
string-equal: # s : string, benchmark : string -> EAX : boolean
|
||||
|
@ -46,7 +46,7 @@ string-equal: # s : string, benchmark : string -> EAX : boolean
|
|||
75/jump-if-not-equal $string-equal:false/disp8
|
||||
$string-equal:lengths:
|
||||
# var i/ECX : int = 0
|
||||
b9/copy . . . . . . . 0/imm32 # copy to ECX
|
||||
b9/copy-to-ECX 0/imm32
|
||||
# EBX = &b[i]
|
||||
43/inc-EBX
|
||||
# EAX = &s[i]
|
||||
|
@ -69,11 +69,11 @@ $string-equal:loop:
|
|||
eb/jump $string-equal:loop/disp8
|
||||
$string-equal:true:
|
||||
# return true
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
eb/jump $string-equal:end/disp8
|
||||
$string-equal:false:
|
||||
# return false
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 0/imm32
|
||||
$string-equal:end:
|
||||
# restore registers
|
||||
5e/pop-to-ESI
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# exit(0)
|
||||
bb/copy . . . . . . . 0/imm32 # copy to EBX
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
## helpers
|
||||
|
@ -44,8 +44,8 @@ abort: # s : (address array byte) -> <void>
|
|||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# exit(1)
|
||||
bb/copy . . . . . . . 1/imm32 # copy to EBX
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
bb/copy-to-EBX 1/imm32
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# print out "Error: #{s} expected\n" to stderr
|
||||
|
@ -92,7 +92,7 @@ write-stdout: # s : (address array byte) -> <void>
|
|||
53/push-EBX
|
||||
# write(1/stdout, (data) s+4, (size) *s)
|
||||
# fd = 1 (stdout)
|
||||
bb/copy . . . . . . . 1/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 1/imm32
|
||||
# x = s+4
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX
|
||||
81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add to ECX
|
||||
|
@ -100,7 +100,7 @@ write-stdout: # s : (address array byte) -> <void>
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 2/r32/EDX 8/disp8 . # copy *(EBP+8) to EDX
|
||||
8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX
|
||||
# call write()
|
||||
b8/copy . . . . . . . 4/imm32/write # copy to EAX
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
# restore registers
|
||||
5b/pop-to-EBX
|
||||
|
|
|
@ -50,7 +50,7 @@ $run-main:
|
|||
$main-exit:
|
||||
# exit(EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# factorial(n)
|
||||
|
@ -60,7 +60,7 @@ factorial:
|
|||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
53/push-EBX
|
||||
# initialize EAX to 1 (base case)
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
# if (n <= 1) jump exit
|
||||
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 8/disp8 1/imm32 # compare *(EBP+8)
|
||||
7e/jump-if-<= $factorial:exit/disp8
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
bb/copy . . . . . . . 2a/imm32 # copy 42 to EBX
|
||||
bb/copy-to-EBX 2a/imm32
|
||||
# exit(EBX)
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# vim:nowrap:textwidth=0
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
# exit(EAX)
|
||||
$exit:
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# compare two null-terminated ascii strings
|
||||
|
@ -42,9 +42,9 @@ argv-equal: # (s1, s2) : null-terminated ascii strings -> EAX : boolean
|
|||
# while (true)
|
||||
$argv-equal:loop:
|
||||
# c1/EAX, c2/EBX = *s1, *s2
|
||||
b8/copy 0/imm32 # clear EAX
|
||||
b8/copy-to-EAX 0/imm32
|
||||
8a/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy byte at *ECX to lower byte of EAX
|
||||
bb/copy 0/imm32 # clear EBX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
8a/copy 0/mod/indirect 2/rm32/EDX . . . 3/r32/EBX . . # copy byte at *EDX to lower byte of EBX
|
||||
# if (c1 == 0) break
|
||||
3d/compare-EAX 0/imm32
|
||||
|
@ -62,11 +62,11 @@ $argv-equal:break:
|
|||
81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0/imm32 # compare EBX
|
||||
75/jump-if-not-equal $argv-equal:false/disp8
|
||||
$argv-equal:success:
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
c3/return
|
||||
# return false
|
||||
$argv-equal:false:
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 0/imm32
|
||||
c3/return
|
||||
|
||||
# vim:nowrap:textwidth=0
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
# exit(EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
||||
|
@ -62,15 +62,15 @@ kernel-string-equal: # s : null-terminated ascii string, benchmark : length-pre
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI
|
||||
81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 4/imm32 # add to ESI
|
||||
# initialize loop counter i into ECX
|
||||
b9/copy . . . . . . . 0/imm32/exit # copy to ECX
|
||||
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 0/imm32 # clear EAX
|
||||
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 0/imm32 # clear EBX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX
|
||||
# if (c1 == 0) return false
|
||||
3d/compare-EAX 0/imm32
|
||||
|
@ -86,16 +86,16 @@ $kernel-string-equal:loop:
|
|||
eb/jump $kernel-string-equal:loop/disp8
|
||||
$kernel-string-equal:break:
|
||||
# if (*s/EDI == 0) return true
|
||||
b8/copy 0/imm32 # clear EAX
|
||||
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
|
||||
81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX
|
||||
75/jump-if-not-equal $kernel-string-equal:false/disp8
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
$kernel-string-equal:true:
|
||||
eb/jump $kernel-string-equal:end/disp8
|
||||
# return false
|
||||
$kernel-string-equal:false:
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 0/imm32
|
||||
|
||||
$kernel-string-equal:end:
|
||||
# restore registers
|
||||
|
@ -314,7 +314,7 @@ write-stderr: # s : (address array byte) -> <void>
|
|||
53/push-EBX
|
||||
# write(2/stderr, (data) s+4, (size) *s)
|
||||
# fd = 2 (stderr)
|
||||
bb/copy . . . . . . . 2/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 2/imm32
|
||||
# x = s+4
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX
|
||||
81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add to ECX
|
||||
|
@ -322,7 +322,7 @@ write-stderr: # s : (address array byte) -> <void>
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 2/r32/EDX 8/disp8 . # copy *(EBP+8) to EDX
|
||||
8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX
|
||||
# call write()
|
||||
b8/copy . . . . . . . 4/imm32/write # copy to EAX
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
# restore registers
|
||||
5b/pop-to-EBX
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
# 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
|
||||
|
||||
# mmap(0x1000)
|
||||
bb/copy . . . . . . . mmap-new-segment/imm32 # copy to EBX
|
||||
b8/copy . . . . . . . 0x5a/imm32/mmap # copy to EAX
|
||||
bb/copy-to-EBX mmap-new-segment/imm32
|
||||
b8/copy-to-EAX 0x5a/imm32/mmap
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# store to *EAX
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
# exit(EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
== data
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
# instruction effective address operand displacement immediate
|
||||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
bb/copy . . . . . . . 1/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 1/imm32
|
||||
43/inc-EBX
|
||||
# exit(EBX)
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# vim:nowrap:textwidth=0
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
# op subop mod rm32 base index scale r32
|
||||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
# result: EBX = 0
|
||||
bb/copy . . . . . . . 0/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
# counter: ECX = 1
|
||||
b9/copy . . . . . . . 1/imm32 # copy to ECX
|
||||
b9/copy-to-ECX 1/imm32
|
||||
|
||||
$loop:
|
||||
# while (counter <= 10)
|
||||
|
@ -29,7 +29,7 @@ $loop:
|
|||
|
||||
$exit:
|
||||
# exit(EBX)
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# vim:nowrap:textwidth=0
|
||||
|
|
|
@ -11,28 +11,28 @@
|
|||
|
||||
# read(stdin, x, 1)
|
||||
# fd = 0 (stdin)
|
||||
bb/copy . . . . . . . 0/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
# initialize x (location to write result to)
|
||||
b9/copy . . . . . . . x/imm32 # copy to ECX
|
||||
b9/copy-to-ECX x/imm32
|
||||
# size = 1 character
|
||||
ba/copy . . . . . . . 1/imm32 # copy to EDX
|
||||
ba/copy-to-EDX 1/imm32
|
||||
# read(fd, x, size)
|
||||
b8/copy . . . . . . . 3/imm32/read # copy to EAX
|
||||
b8/copy-to-EAX 3/imm32/read
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# write(stdout, x, 1)
|
||||
# fd = 1 (stdout)
|
||||
bb/copy . . . . . . . 1/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 1/imm32
|
||||
# initialize x (location to read from)
|
||||
b9/copy . . . . . . . x/imm32 # copy to ECX
|
||||
b9/copy-to-ECX x/imm32
|
||||
# size = 1 character
|
||||
ba/copy . . . . . . . 1/imm32 # copy to EDX
|
||||
ba/copy-to-EDX 1/imm32
|
||||
# write(fd, x, size)
|
||||
b8/copy . . . . . . . 4/imm32/write # copy to EAX
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# exit(EBX)
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
== data
|
||||
|
|
|
@ -15,28 +15,28 @@
|
|||
|
||||
# read(stdin, x, 1)
|
||||
# fd = 0 (stdin)
|
||||
bb/copy . . . . . . . 0/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 0/imm32
|
||||
# initialize x (location to write result to)
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 1/r32/ECX 4/disp8 . # copy ESP+4 to ECX
|
||||
# size = 1 character
|
||||
ba/copy . . . . . . . 1/imm32 # copy to EDX
|
||||
ba/copy-to-EDX 1/imm32
|
||||
# read(fd, x, size)
|
||||
b8/copy . . . . . . . 3/imm32/read # copy to EAX
|
||||
b8/copy-to-EAX 3/imm32/read
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# write(stdout, x, 1)
|
||||
# fd = 1 (stdout)
|
||||
bb/copy . . . . . . . 1/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 1/imm32
|
||||
# initialize x (location to read from)
|
||||
8d/copy-address 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 1/r32/ECX 4/disp8 . # copy ESP+4 to ECX
|
||||
# size = 1 character
|
||||
ba/copy . . . . . . . 1/imm32 # copy to EDX
|
||||
ba/copy-to-EDX 1/imm32
|
||||
# write(fd, x, size)
|
||||
b8/copy . . . . . . . 4/imm32/write # copy to EAX
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# exit(EBX)
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# vim:nowrap:textwidth=0
|
||||
|
|
|
@ -12,17 +12,17 @@
|
|||
|
||||
# write(stdout, x, size)
|
||||
# fd = 1 (stdout)
|
||||
bb/copy . . . . . . . 1/imm32 # copy to EBX
|
||||
bb/copy-to-EBX 1/imm32
|
||||
# initialize x (location to write result to)
|
||||
b9/copy . . . . . . . x/imm32 # copy to ECX
|
||||
b9/copy-to-ECX x/imm32
|
||||
# initialize size
|
||||
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 2/r32/EDX size/disp32 . # copy *size to EDX
|
||||
# write(fd, x, size)
|
||||
b8/copy . . . . . . . 4/imm32/write # copy to EAX
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# exit(EBX)
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
== data
|
||||
|
|
|
@ -16,78 +16,78 @@
|
|||
# 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
|
||||
|
||||
# creat(filename)
|
||||
bb/copy . . . . . . . filename/imm32 # copy to EBX
|
||||
b9/copy . . . . . . . 0x180/imm32/fixed-perms # copy to ECX
|
||||
b8/copy . . . . . . . 8/imm32/creat # copy to EAX
|
||||
bb/copy-to-EBX filename/imm32
|
||||
b9/copy-to-ECX 0x180/imm32/fixed-perms
|
||||
b8/copy-to-EAX 8/imm32/creat
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# stream = open(filename, O_WRONLY, 0) # we can't use 'fd' because it looks like a hex byte
|
||||
bb/copy . . . . . . . filename/imm32 # copy to EBX
|
||||
b9/copy . . . . . . . 1/imm32/wronly # copy to ECX
|
||||
ba/copy . . . . . . . 0x180/imm32/fixed-perms # copy to EDX
|
||||
b8/copy . . . . . . . 5/imm32/open # copy to EAX
|
||||
bb/copy-to-EBX filename/imm32
|
||||
b9/copy-to-ECX 1/imm32/wronly
|
||||
ba/copy-to-EDX 0x180/imm32/fixed-perms
|
||||
b8/copy-to-EAX 5/imm32/open
|
||||
cd/syscall 0x80/imm8
|
||||
# save stream
|
||||
bb/copy . . . . . . . stream/imm32 # copy to EBX
|
||||
bb/copy-to-EBX stream/imm32
|
||||
89/copy 0/mod/indirect 3/rm32/EBX 0/r32/EAX # copy EAX to *EBX
|
||||
|
||||
# write(stream, "a", 1)
|
||||
# load stream
|
||||
bb/copy . . . . . . . stream/imm32 # copy to EBX
|
||||
bb/copy-to-EBX stream/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX
|
||||
#
|
||||
b9/copy . . . . . . . a/imm32 # copy to ECX
|
||||
ba/copy . . . . . . . 1/imm32/size # copy to EDX
|
||||
b8/copy . . . . . . . 4/imm32/write # copy to EAX
|
||||
b9/copy-to-ECX a/imm32
|
||||
ba/copy-to-EDX 1/imm32/size
|
||||
b8/copy-to-EAX 4/imm32/write
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# close(stream)
|
||||
# load stream
|
||||
bb/copy . . . . . . . stream/imm32 # copy to EBX
|
||||
bb/copy-to-EBX stream/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX
|
||||
#
|
||||
b8/copy . . . . . . . 6/imm32/close # copy to EAX
|
||||
b8/copy-to-EAX 6/imm32/close
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# stream = open(filename, O_RDONLY, 0)
|
||||
bb/copy . . . . . . . filename/imm32 # copy to EBX
|
||||
b9/copy . . . . . . . 0/imm32/rdonly # copy to ECX
|
||||
ba/copy . . . . . . . 0x180/imm32/fixed-perms # copy to EDX
|
||||
b8/copy . . . . . . . 5/imm32/open # copy to EAX
|
||||
bb/copy-to-EBX filename/imm32
|
||||
b9/copy-to-ECX 0/imm32/rdonly
|
||||
ba/copy-to-EDX 0x180/imm32/fixed-perms
|
||||
b8/copy-to-EAX 5/imm32/open
|
||||
cd/syscall 0x80/imm8
|
||||
# save stream
|
||||
bb/copy . . . . . . . stream/imm32 # copy to EBX
|
||||
bb/copy-to-EBX stream/imm32
|
||||
89/copy 0/mod/indirect 3/rm32/EBX 0/r32/EAX # copy EAX to *EBX
|
||||
|
||||
# read(stream, b, 1)
|
||||
# load stream
|
||||
bb/copy . . . . . . . stream/imm32 # copy to EBX
|
||||
bb/copy-to-EBX stream/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX
|
||||
#
|
||||
b9/copy . . . . . . . b/imm32 # copy to ECX
|
||||
ba/copy . . . . . . . 1/imm32/size # copy to EDX
|
||||
b8/copy . . . . . . . 3/imm32/read # copy to EAX
|
||||
b9/copy-to-ECX b/imm32
|
||||
ba/copy-to-EDX 1/imm32/size
|
||||
b8/copy-to-EAX 3/imm32/read
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# close(stream)
|
||||
# load stream
|
||||
bb/copy . . . . . . . stream/imm32 # copy to EBX
|
||||
bb/copy-to-EBX stream/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX
|
||||
#
|
||||
b8/copy . . . . . . . 6/imm32/close # copy to EAX
|
||||
b8/copy-to-EAX 6/imm32/close
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# unlink(filename)
|
||||
bb/copy . . . . . . . filename/imm32 # copy to EBX
|
||||
b8/copy . . . . . . . 0xa/imm32/unlink # copy to EAX
|
||||
bb/copy-to-EBX filename/imm32
|
||||
b8/copy-to-EAX 0xa/imm32/unlink
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# exit(b)
|
||||
# load b
|
||||
bb/copy . . . . . . . b/imm32 # copy to EBX
|
||||
bb/copy-to-EBX b/imm32
|
||||
8b/copy 0/mod/indirect 3/rm32/EBX 3/r32/EBX # copy *EBX to EBX
|
||||
#
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
== data
|
||||
|
|
|
@ -30,14 +30,14 @@
|
|||
|
||||
# exit(EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
ascii-length: # (s)
|
||||
# initialize s (EDX)
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 2/r32/EDX 4/disp8 # copy *(ESP+4) to EDX
|
||||
# var result = 0 (EAX)
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
b8/copy-to-EAX 0/imm32
|
||||
$ascii-length-loop:
|
||||
# var c = *s (ECX)
|
||||
8a/copy 0/mod/* 2/rm32/EDX . . . 1/r32/ECX . . # copy byte at *EDX to lower byte of ECX
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# exit(EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
b8/copy-to-EAX 1/imm32/exit
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
ascii-difference: # (s1, s2) : null-terminated ascii strings
|
||||
|
|
Loading…
Reference in New Issue