4667
Standardize on hyphens in all names. And we'll use colons for namespacing labels in functions.
This commit is contained in:
parent
7163541bf2
commit
03d50cc83c
|
@ -11,34 +11,34 @@ Transform.push_back(create_test_function);
|
|||
% Reg[ESP].u = 0x100;
|
||||
== 0x1
|
||||
main:
|
||||
e8/call run_tests/disp32 # 5 bytes
|
||||
e8/call run-tests/disp32 # 5 bytes
|
||||
f4/halt # 1 byte
|
||||
|
||||
test_foo: # offset 7
|
||||
test-foo: # offset 7
|
||||
01 d8 # just some unique instruction: add EBX to EAX
|
||||
c3/return
|
||||
|
||||
# check that code in test_foo ran (implicitly called by run_tests)
|
||||
# check that code in test_foo ran (implicitly called by run-tests)
|
||||
+run: inst: 0x00000007
|
||||
|
||||
:(code)
|
||||
void create_test_function(program& p) {
|
||||
if (p.segments.empty()) return;
|
||||
segment& code = p.segments.at(0);
|
||||
trace(99, "transform") << "-- create 'run_tests'" << end();
|
||||
trace(99, "transform") << "-- create 'run-tests'" << end();
|
||||
vector<line> new_insts;
|
||||
for (int i = 0; i < SIZE(code.lines); ++i) {
|
||||
line& inst = code.lines.at(i);
|
||||
for (int j = 0; j < SIZE(inst.words); ++j) {
|
||||
const word& curr = inst.words.at(j);
|
||||
if (*curr.data.rbegin() != ':') continue; // not a label
|
||||
if (!starts_with(curr.data, "test_")) continue;
|
||||
if (!starts_with(curr.data, "test-")) continue;
|
||||
string fn = drop_last(curr.data);
|
||||
new_insts.push_back(call(fn));
|
||||
}
|
||||
}
|
||||
if (new_insts.empty()) return; // no tests found
|
||||
code.lines.push_back(label("run_tests"));
|
||||
code.lines.push_back(label("run-tests"));
|
||||
code.lines.insert(code.lines.end(), new_insts.begin(), new_insts.end());
|
||||
code.lines.push_back(ret());
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# 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
|
||||
|
||||
write_stderr: # s : (address array byte) -> <void>
|
||||
write-stderr: # s : (address array byte) -> <void>
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# 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
|
||||
|
||||
# print msg to stderr if a != b, otherwise print "."
|
||||
check_ints_equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
||||
check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -17,37 +17,37 @@ check_ints_equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX
|
||||
# if EAX == b/EBX
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
|
||||
75/jump-if-unequal $check_ints_equal:else/disp8
|
||||
75/jump-if-unequal $check-ints-equal:else/disp8
|
||||
# print('.')
|
||||
# push args
|
||||
68/push "."/imm32
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# return
|
||||
eb/jump $check_ints_equal:end/disp8
|
||||
eb/jump $check-ints-equal:end/disp8
|
||||
# else:
|
||||
$check_ints_equal:else:
|
||||
$check-ints-equal:else:
|
||||
# copy msg into ECX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX
|
||||
# print(ECX)
|
||||
# push args
|
||||
51/push-ECX
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# print newline
|
||||
# push args
|
||||
68/push Newline/imm32
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# increment Num_test_failures
|
||||
ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num_test_failures/disp32 # increment *Num_test_failures
|
||||
$check_ints_equal:end:
|
||||
# increment Num-test-failures
|
||||
ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures
|
||||
$check-ints-equal:end:
|
||||
# restore registers
|
||||
5b/pop-to-EBX
|
||||
59/pop-to-ECX
|
||||
|
@ -64,7 +64,7 @@ Newline:
|
|||
# data
|
||||
0a/newline
|
||||
|
||||
Num_test_failures:
|
||||
Num-test-failures:
|
||||
00 00 00 00
|
||||
|
||||
# vim:nowrap:textwidth=0
|
||||
|
|
|
@ -21,15 +21,15 @@
|
|||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
|
||||
# main: (manual test if this is the last file loaded)
|
||||
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
|
||||
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
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
||||
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
|
||||
kernel_string_equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
||||
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -65,9 +65,9 @@ kernel_string_equal: # s : null-terminated ascii string, benchmark : length-pre
|
|||
# initialize loop counter i into ECX
|
||||
b9/copy . . . . . . . 0/imm32/exit # copy to ECX
|
||||
# while (i/ECX < n/EDX)
|
||||
$kernel_string_loop:
|
||||
$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_break/disp8
|
||||
74/jump-if-equal $kernel-string-equal:break/disp8
|
||||
# c1/EAX, c2/EBX = *s, *benchmark
|
||||
b8/copy 0/imm32 # clear EAX
|
||||
8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX
|
||||
|
@ -75,29 +75,30 @@ $kernel_string_loop:
|
|||
8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX
|
||||
# if (c1 == 0) return false
|
||||
3d/compare-EAX 0/imm32
|
||||
74/jump-if-equal $kernel_string_fail/disp8
|
||||
74/jump-if-equal $kernel-string-equal:false/disp8
|
||||
# if (c1 != c2) return false
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX
|
||||
75/jump-if-not-equal $kernel_string_fail/disp8
|
||||
75/jump-if-not-equal $kernel-string-equal:false/disp8
|
||||
# ++s1, ++s2, ++i
|
||||
41/inc-ECX
|
||||
46/inc-ESI
|
||||
47/inc-EDI
|
||||
# end while
|
||||
eb/jump $kernel_string_loop/disp8
|
||||
$kernel_string_break:
|
||||
eb/jump $kernel-string-equal:loop/disp8
|
||||
$kernel-string-equal:break:
|
||||
# if (*s/EDI == 0) return true
|
||||
b8/copy 0/imm32 # clear 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
|
||||
75/jump-if-not-equal $kernel_string_fail/disp8
|
||||
75/jump-if-not-equal $kernel-string-equal:false/disp8
|
||||
$kernel-string-equal:true:
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
eb/jump $kernel_string_end/disp8
|
||||
eb/jump $kernel-string-equal:end/disp8
|
||||
# return false
|
||||
$kernel_string_fail:
|
||||
$kernel-string-equal:false:
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
|
||||
$kernel_string_end:
|
||||
$kernel-string-equal:end:
|
||||
# restore registers
|
||||
5f/pop-to-EDI
|
||||
5e/pop-to-ESI
|
||||
|
@ -111,151 +112,151 @@ $kernel_string_end:
|
|||
|
||||
## tests
|
||||
|
||||
test_compare_null_kernel_string_with_empty_array:
|
||||
# EAX = kernel_string_equal(Null_kernel_string, "")
|
||||
test-compare-null-kernel-string-with-empty-array:
|
||||
# EAX = kernel-string-equal(Null-kernel-string, "")
|
||||
# push args
|
||||
68/push ""/imm32
|
||||
68/push Null_kernel_string/imm32
|
||||
68/push Null-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 1, msg)
|
||||
# call check-ints-equal(EAX, 1, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_null_kernel_string_with_empty_array"/imm32
|
||||
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
|
||||
68/push 1/imm32/true
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_null_kernel_string_with_non_empty_array:
|
||||
# EAX = kernel_string_equal(Null_kernel_string, "Abc")
|
||||
test-compare-null-kernel-string-with-non-empty-array:
|
||||
# EAX = kernel-string-equal(Null-kernel-string, "Abc")
|
||||
# push args
|
||||
68/push "Abc"/imm32
|
||||
68/push Null_kernel_string/imm32
|
||||
68/push Null-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0, msg)
|
||||
# call check-ints-equal(EAX, 0, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_null_kernel_string_with_non_empty_array"/imm32
|
||||
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_equal_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "Abc")
|
||||
test-compare-kernel-string-with-equal-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
|
||||
# push args
|
||||
68/push "Abc"/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 1, msg)
|
||||
# call check-ints-equal(EAX, 1, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_equal_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 1/imm32/true
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_inequal_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "Adc")
|
||||
test-compare-kernel-string-with-inequal-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
|
||||
# push args
|
||||
68/push "Adc"/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0, msg)
|
||||
# call check-ints-equal(EAX, 0, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_equal_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_empty_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "")
|
||||
test-compare-kernel-string-with-empty-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "")
|
||||
# push args
|
||||
68/push ""/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0)
|
||||
# call check-ints-equal(EAX, 0)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_equal_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_shorter_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "Ab")
|
||||
test-compare-kernel-string-with-shorter-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
|
||||
# push args
|
||||
68/push "Ab"/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0)
|
||||
# call check-ints-equal(EAX, 0)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_shorter_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_longer_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "Abcd")
|
||||
test-compare-kernel-string-with-longer-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
|
||||
# push args
|
||||
68/push "Abcd"/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0)
|
||||
# call check-ints-equal(EAX, 0)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_longer_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-longer-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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
|
||||
|
||||
== data
|
||||
|
||||
Null_kernel_string:
|
||||
Null-kernel-string:
|
||||
00/null
|
||||
Abc_kernel_string:
|
||||
Abc-kernel-string:
|
||||
41/A 62/b 63/c 00/null
|
||||
|
||||
# vim:nowrap:textwidth=0
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
|
||||
# main: (manual test if this is the last file loaded)
|
||||
# EAX = new_segment(0x1000)
|
||||
# EAX = new-segment(0x1000)
|
||||
# push arg
|
||||
68/push 0x1000/imm32
|
||||
# call
|
||||
e8/call new_segment/disp32
|
||||
e8/call new-segment/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
|
||||
|
@ -23,18 +23,18 @@
|
|||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
new_segment: # len : int -> address
|
||||
new-segment: # len : int -> address
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
53/push-EBX
|
||||
# copy len to mmap_new_segment.len
|
||||
# TODO: compute mmap_new_segment+4 before runtime
|
||||
# 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 . . . . . . . mmap-new-segment/imm32 # copy to EBX
|
||||
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
|
||||
# mmap(mmap-new-segment)
|
||||
bb/copy . . . . . . . mmap-new-segment/imm32 # copy to EBX
|
||||
b8/copy . . . . . . . 0x5a/imm32/mmap # copy to EAX
|
||||
cd/syscall 0x80/imm8
|
||||
# epilog
|
||||
|
@ -45,7 +45,7 @@ new_segment: # len : int -> address
|
|||
|
||||
== data
|
||||
# various constants used here were found in the Linux sources (search for file mman-common.h)
|
||||
mmap_new_segment: # type mmap_arg_struct
|
||||
mmap-new-segment: # type mmap_arg_struct
|
||||
# addr
|
||||
00 00 00 00 # null
|
||||
# len
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
|
||||
# main: (manual test if this is the last file loaded)
|
||||
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
|
||||
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
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
string_equal: # s : string, benchmark : string -> EAX : boolean
|
||||
string-equal: # s : string, benchmark : string -> EAX : boolean
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -43,38 +43,38 @@ string_equal: # s : string, benchmark : string -> EAX : boolean
|
|||
8b/copy 0/mod/indirect 0/rm32/EAX . . . 2/r32/EDX . . # copy *EAX to EDX
|
||||
# compare s.length and b.length
|
||||
39/compare 0/mod/indirect 3/rm32/EBX . . . 2/r32/EDX . . # compare *EBX with EDX
|
||||
75/jump-if-not-equal $string_not_equal/disp8
|
||||
$string_lengths_equal:
|
||||
75/jump-if-not-equal $string-equal:false/disp8
|
||||
$string-equal:lengths:
|
||||
# var i/ECX : int = 0
|
||||
b9/copy . . . . . . . 0/imm32 # copy to ECX
|
||||
# EBX = &b[i]
|
||||
43/inc-EBX
|
||||
# EAX = &s[i]
|
||||
40/inc-EAX
|
||||
$string_equal_loop:
|
||||
$string-equal:loop:
|
||||
# if i >= s.length return true
|
||||
39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX
|
||||
7d/jump-if-greater-or-equal $string_equal/disp8
|
||||
7d/jump-if-greater-or-equal $string-equal:true/disp8
|
||||
# if b[i] != s[i] return false
|
||||
# ESI = s[i]
|
||||
8b/copy 0/mod/indirect 0/rm32/EAX . . . 6/r32/ESI . . # copy *EAX to ESI
|
||||
# compare b[i] with ESI
|
||||
39/compare 0/mod/indirect 3/rm32/EBX . . . 6/r32/ESI . . # compare *EBX with ESI
|
||||
75/jump-if-not-equal $string_not_equal/disp8
|
||||
75/jump-if-not-equal $string-equal:false/disp8
|
||||
# ++i
|
||||
41/inc-ECX
|
||||
40/inc-EAX
|
||||
43/inc-EBX
|
||||
# loop
|
||||
eb/jump $string_equal_loop/disp8
|
||||
$string_equal:
|
||||
eb/jump $string-equal:loop/disp8
|
||||
$string-equal:true:
|
||||
# return true
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
eb/jump $string_equal_end/disp8
|
||||
$string_not_equal:
|
||||
eb/jump $string-equal:end/disp8
|
||||
$string-equal:false:
|
||||
# return false
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
$string_equal_end:
|
||||
$string-equal:end:
|
||||
# restore registers
|
||||
5e/pop-to-ESI
|
||||
5b/pop-to-EBX
|
||||
|
@ -87,82 +87,82 @@ $string_equal_end:
|
|||
|
||||
## tests
|
||||
|
||||
test_compare_empty_with_empty_string:
|
||||
# EAX = string_equal("", "")
|
||||
test-compare-empty-with-empty-string:
|
||||
# EAX = string-equal("", "")
|
||||
# push args
|
||||
68/push ""/imm32
|
||||
68/push ""/imm32
|
||||
# call
|
||||
e8/call string_equal/disp32
|
||||
e8/call string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 1, msg)
|
||||
# call check-ints-equal(EAX, 1, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_empty_with_empty_string"/imm32
|
||||
68/push "F - test-compare-empty-with-empty-string"/imm32
|
||||
68/push 1/imm32/true
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_empty_with_non_empty_string: # also checks length-mismatch code path
|
||||
# EAX = string_equal("", "Abc")
|
||||
test-compare-empty-with-non-empty-string: # also checks length-mismatch code path
|
||||
# EAX = string-equal("", "Abc")
|
||||
# push args
|
||||
68/push "Abc"/imm32
|
||||
68/push ""/imm32
|
||||
# call
|
||||
e8/call string_equal/disp32
|
||||
e8/call string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0, msg)
|
||||
# call check-ints-equal(EAX, 0, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_empty_with_non_empty_string"/imm32
|
||||
68/push "F - test-compare-empty-with-non-empty-string"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_equal_strings:
|
||||
# EAX = string_equal("Abc", "Abc")
|
||||
test-compare-equal-strings:
|
||||
# EAX = string-equal("Abc", "Abc")
|
||||
# push args
|
||||
68/push "Abc"/imm32
|
||||
68/push "Abc"/imm32
|
||||
# call
|
||||
e8/call string_equal/disp32
|
||||
e8/call string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 1, msg)
|
||||
# call check-ints-equal(EAX, 1, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_equal_strings"/imm32
|
||||
68/push "F - test-compare-equal-strings"/imm32
|
||||
68/push 1/imm32/true
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_inequal_strings_equal_lengths:
|
||||
# EAX = string_equal("Abc", "Adc")
|
||||
test-compare-inequal-strings-equal-lengths:
|
||||
# EAX = string-equal("Abc", "Adc")
|
||||
# push args
|
||||
68/push "Adc"/imm32
|
||||
68/push "Abc"/imm32
|
||||
# call
|
||||
e8/call string_equal/disp32
|
||||
e8/call string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0, msg)
|
||||
# call check-ints-equal(EAX, 0, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_inequal_strings_equal_lengths"/imm32
|
||||
68/push "F - test-compare-inequal-strings-equal-lengths"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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
|
||||
|
|
Binary file not shown.
|
@ -50,38 +50,38 @@ abort: # s : (address array byte) -> <void>
|
|||
|
||||
# print out "Error: #{s} expected\n" to stderr
|
||||
error: # s : (address array byte) -> <void>
|
||||
# write_stderr("Error: ")
|
||||
# write-stderr("Error: ")
|
||||
# push args
|
||||
68/push "Error: "/imm32
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# write_stderr(s)
|
||||
# write-stderr(s)
|
||||
# push args
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . . 4/disp8 . # push *(ESP+4)
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# write_stderr(" expected")
|
||||
# write-stderr(" expected")
|
||||
# push args
|
||||
68/push " expected"/imm32
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# write_stderr("\n")
|
||||
# write-stderr("\n")
|
||||
# push args
|
||||
68/push Newline/imm32
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# end
|
||||
c3/return
|
||||
|
||||
write_stdout: # s : (address array byte) -> <void>
|
||||
write-stdout: # s : (address array byte) -> <void>
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
|
Binary file not shown.
|
@ -24,30 +24,30 @@
|
|||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# if (argc > 1)
|
||||
81 7/subop/compare 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0/disp8 1/imm32 # compare *EBP
|
||||
7e/jump-if-lesser-or-equal $run_main/disp8
|
||||
7e/jump-if-lesser-or-equal $run-main/disp8
|
||||
# and if (argv[1] == "test")
|
||||
# push args
|
||||
68/push "test"/imm32
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# check result
|
||||
3d/compare-EAX 1/imm32
|
||||
75/jump-if-not-equal $run_main/disp8
|
||||
75/jump-if-not-equal $run-main/disp8
|
||||
# then
|
||||
e8/call run_tests/disp32
|
||||
eb/jump $main_exit/disp8
|
||||
e8/call run-tests/disp32
|
||||
eb/jump $main-exit/disp8
|
||||
# else EAX = factorial(5)
|
||||
$run_main:
|
||||
$run-main:
|
||||
# push arg
|
||||
68/push 5/imm32
|
||||
# call
|
||||
e8/call factorial/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
$main_exit:
|
||||
$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
|
||||
|
@ -84,7 +84,7 @@ $factorial:exit:
|
|||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
test_factorial:
|
||||
test-factorial:
|
||||
# factorial(5)
|
||||
# push arg
|
||||
68/push 5/imm32
|
||||
|
@ -92,13 +92,13 @@ test_factorial:
|
|||
e8/call factorial/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# check_ints_equal(EAX, 120, failure message)
|
||||
# check-ints-equal(EAX, 120, failure message)
|
||||
# push args
|
||||
68/push "F - test_factorial"/imm32
|
||||
68/push "F - test-factorial"/imm32
|
||||
68/push 0x78/imm32/expected-120
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
e8/call check-ints-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP
|
||||
# end
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# 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
|
||||
|
||||
# main: return argv_equal(argv[1], argv[2])
|
||||
# main: return argv-equal(argv[1], argv[2])
|
||||
# At the start of a SubX program:
|
||||
# argc: *ESP
|
||||
# argv[0]: *(ESP+4)
|
||||
|
@ -20,13 +20,13 @@
|
|||
# ...
|
||||
# prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# call argv_equal(argv[1], argv[2])
|
||||
# call argv-equal(argv[1], argv[2])
|
||||
# push argv[2]
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
# push argv[1]
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
# call
|
||||
e8/call argv_equal/disp32
|
||||
e8/call argv-equal/disp32
|
||||
# exit(EAX)
|
||||
$exit:
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
|
@ -35,12 +35,12 @@ $exit:
|
|||
|
||||
# compare two null-terminated ascii strings
|
||||
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
|
||||
argv_equal: # (s1, s2) : null-terminated ascii strings -> EAX : boolean
|
||||
argv-equal: # (s1, s2) : null-terminated ascii strings -> EAX : boolean
|
||||
# initialize s1 (ECX) and s2 (EDX)
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX 4/disp8 . # copy *(ESP+4) to ECX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 2/r32/EDX 8/disp8 . # copy *(ESP+8) to EDX
|
||||
# while (true)
|
||||
$argv_loop:
|
||||
$argv-equal:loop:
|
||||
# c1/EAX, c2/EBX = *s1, *s2
|
||||
b8/copy 0/imm32 # clear EAX
|
||||
8a/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy byte at *ECX to lower byte of EAX
|
||||
|
@ -48,23 +48,24 @@ $argv_loop:
|
|||
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
|
||||
74/jump-if-equal $argv_break/disp8
|
||||
74/jump-if-equal $argv-equal:break/disp8
|
||||
# if (c1 != c2) return false
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX
|
||||
75/jump-if-not-equal $argv_fail/disp8
|
||||
75/jump-if-not-equal $argv-equal:false/disp8
|
||||
# ++s1, ++s2
|
||||
41/inc-ECX
|
||||
42/inc-EDX
|
||||
# end while
|
||||
eb/jump $argv_loop/disp8
|
||||
$argv_break:
|
||||
eb/jump $argv-equal:loop/disp8
|
||||
$argv-equal:break:
|
||||
# if (c2 == 0) return true
|
||||
81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0/imm32 # compare EBX
|
||||
75/jump-if-not-equal $argv_fail/disp8
|
||||
75/jump-if-not-equal $argv-equal:false/disp8
|
||||
$argv-equal:success:
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
c3/return
|
||||
# return false
|
||||
$argv_fail:
|
||||
$argv-equal:false:
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
c3/return
|
||||
|
||||
|
|
Binary file not shown.
|
@ -21,7 +21,7 @@
|
|||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
|
||||
# main:
|
||||
e8/call run_tests/disp32 # 'run_tests' is a function created automatically by SubX. It calls all functions that start with 'test_'.
|
||||
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
|
||||
# exit(EAX)
|
||||
89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
|
||||
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
|
||||
kernel_string_equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
||||
kernel-string-equal: # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -64,9 +64,9 @@ kernel_string_equal: # s : null-terminated ascii string, benchmark : length-pre
|
|||
# initialize loop counter i into ECX
|
||||
b9/copy . . . . . . . 0/imm32/exit # copy to ECX
|
||||
# while (i/ECX < n/EDX)
|
||||
$kernel_string_loop:
|
||||
$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_break/disp8
|
||||
74/jump-if-equal $kernel-string-equal:break/disp8
|
||||
# c1/EAX, c2/EBX = *s, *benchmark
|
||||
b8/copy 0/imm32 # clear EAX
|
||||
8a/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy byte at *EDI to lower byte of EAX
|
||||
|
@ -74,29 +74,30 @@ $kernel_string_loop:
|
|||
8a/copy 0/mod/indirect 6/rm32/ESI . . . 3/r32/EBX . . # copy byte at *ESI to lower byte of EBX
|
||||
# if (c1 == 0) return false
|
||||
3d/compare-EAX 0/imm32
|
||||
74/jump-if-equal $kernel_string_fail/disp8
|
||||
74/jump-if-equal $kernel-string-equal:false/disp8
|
||||
# if (c1 != c2) return false
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX with EBX
|
||||
75/jump-if-not-equal $kernel_string_fail/disp8
|
||||
75/jump-if-not-equal $kernel-string-equal:false/disp8
|
||||
# ++s1, ++s2, ++i
|
||||
41/inc-ECX
|
||||
46/inc-ESI
|
||||
47/inc-EDI
|
||||
# end while
|
||||
eb/jump $kernel_string_loop/disp8
|
||||
$kernel_string_break:
|
||||
eb/jump $kernel-string-equal:loop/disp8
|
||||
$kernel-string-equal:break:
|
||||
# if (*s/EDI == 0) return true
|
||||
b8/copy 0/imm32 # clear 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
|
||||
75/jump-if-not-equal $kernel_string_fail/disp8
|
||||
75/jump-if-not-equal $kernel-string-equal:false/disp8
|
||||
b8/copy . . . . . . . 1/imm32 # copy to EAX
|
||||
eb/jump $kernel_string_end/disp8
|
||||
$kernel-string-equal:true:
|
||||
eb/jump $kernel-string-equal:end/disp8
|
||||
# return false
|
||||
$kernel_string_fail:
|
||||
$kernel-string-equal:false:
|
||||
b8/copy . . . . . . . 0/imm32 # copy to EAX
|
||||
|
||||
$kernel_string_end:
|
||||
$kernel-string-equal:end:
|
||||
# restore registers
|
||||
5f/pop-to-EDI
|
||||
5e/pop-to-ESI
|
||||
|
@ -110,142 +111,142 @@ $kernel_string_end:
|
|||
|
||||
## tests
|
||||
|
||||
test_compare_null_kernel_string_with_empty_array:
|
||||
# EAX = kernel_string_equal(Null_kernel_string, "")
|
||||
test-compare-null-kernel-string-with-empty-array:
|
||||
# EAX = kernel-string-equal(Null-kernel-string, "")
|
||||
# push args
|
||||
68/push ""/imm32
|
||||
68/push Null_kernel_string/imm32
|
||||
68/push Null-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 1, msg)
|
||||
# call check-ints-equal(EAX, 1, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_null_kernel_string_with_empty_array"/imm32
|
||||
68/push "F - test-compare-null-kernel-string-with-empty-array"/imm32
|
||||
68/push 1/imm32/true
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_null_kernel_string_with_non_empty_array:
|
||||
# EAX = kernel_string_equal(Null_kernel_string, "Abc")
|
||||
test-compare-null-kernel-string-with-non-empty-array:
|
||||
# EAX = kernel-string-equal(Null-kernel-string, "Abc")
|
||||
# push args
|
||||
68/push "Abc"/imm32
|
||||
68/push Null_kernel_string/imm32
|
||||
68/push Null-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0, msg)
|
||||
# call check-ints-equal(EAX, 0, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_null_kernel_string_with_non_empty_array"/imm32
|
||||
68/push "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_equal_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "Abc")
|
||||
test-compare-kernel-string-with-equal-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abc")
|
||||
# push args
|
||||
68/push "Abc"/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 1, msg)
|
||||
# call check-ints-equal(EAX, 1, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_equal_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 1/imm32/true
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_inequal_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "Adc")
|
||||
test-compare-kernel-string-with-inequal-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Adc")
|
||||
# push args
|
||||
68/push "Adc"/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0, msg)
|
||||
# call check-ints-equal(EAX, 0, msg)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_equal_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_empty_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "")
|
||||
test-compare-kernel-string-with-empty-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "")
|
||||
# push args
|
||||
68/push ""/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0)
|
||||
# call check-ints-equal(EAX, 0)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_equal_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-equal-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_shorter_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "Ab")
|
||||
test-compare-kernel-string-with-shorter-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Ab")
|
||||
# push args
|
||||
68/push "Ab"/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0)
|
||||
# call check-ints-equal(EAX, 0)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_shorter_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-shorter-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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_compare_kernel_string_with_longer_array:
|
||||
# EAX = kernel_string_equal(Abc_kernel_string, "Abcd")
|
||||
test-compare-kernel-string-with-longer-array:
|
||||
# EAX = kernel-string-equal(Abc-kernel-string, "Abcd")
|
||||
# push args
|
||||
68/push "Abcd"/imm32
|
||||
68/push Abc_kernel_string/imm32
|
||||
68/push Abc-kernel-string/imm32
|
||||
# call
|
||||
e8/call kernel_string_equal/disp32
|
||||
e8/call kernel-string-equal/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# call check_ints_equal(EAX, 0)
|
||||
# call check-ints-equal(EAX, 0)
|
||||
# push args
|
||||
68/push "F - test_compare_kernel_string_with_longer_array"/imm32
|
||||
68/push "F - test-compare-kernel-string-with-longer-array"/imm32
|
||||
68/push 0/imm32/false
|
||||
50/push-EAX
|
||||
# call
|
||||
e8/call check_ints_equal/disp32
|
||||
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
|
||||
|
@ -253,7 +254,7 @@ test_compare_kernel_string_with_longer_array:
|
|||
## helpers
|
||||
|
||||
# print msg to stderr if a != b, otherwise print "."
|
||||
check_ints_equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
||||
check-ints-equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -265,35 +266,35 @@ check_ints_equal: # (a : int, b : int, msg : (address array byte)) -> boolean
|
|||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX
|
||||
# if EAX == b/EBX
|
||||
39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX
|
||||
75/jump-if-unequal $check_ints_equal:else/disp8
|
||||
75/jump-if-unequal $check-ints-equal:else/disp8
|
||||
# print('.')
|
||||
# push args
|
||||
68/push "."/imm32
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# return
|
||||
eb/jump $check_ints_equal:end/disp8
|
||||
eb/jump $check-ints-equal:end/disp8
|
||||
# else:
|
||||
$check_ints_equal:else:
|
||||
$check-ints-equal:else:
|
||||
# copy msg into ECX
|
||||
8b/copy 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . 1/r32/ECX 0x10/disp8 . # copy *(EBP+16) to ECX
|
||||
# print(ECX)
|
||||
# push args
|
||||
51/push-ECX
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
# print newline
|
||||
# push args
|
||||
68/push Newline/imm32
|
||||
# call
|
||||
e8/call write_stderr/disp32
|
||||
e8/call write-stderr/disp32
|
||||
# discard arg
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
$check_ints_equal:end:
|
||||
$check-ints-equal:end:
|
||||
# restore registers
|
||||
5b/pop-to-EBX
|
||||
59/pop-to-ECX
|
||||
|
@ -302,7 +303,7 @@ $check_ints_equal:end:
|
|||
5d/pop-to-EBP
|
||||
c3/return
|
||||
|
||||
write_stderr: # s : (address array byte) -> <void>
|
||||
write-stderr: # s : (address array byte) -> <void>
|
||||
# prolog
|
||||
55/push-EBP
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
|
@ -340,10 +341,10 @@ Newline:
|
|||
# data
|
||||
0a/newline
|
||||
|
||||
# for kernel_string_equal tests
|
||||
Null_kernel_string:
|
||||
# for kernel-string-equal tests
|
||||
Null-kernel-string:
|
||||
00/null
|
||||
Abc_kernel_string:
|
||||
Abc-kernel-string:
|
||||
41/A 62/b 63/c 00/null
|
||||
|
||||
# vim:nowrap:textwidth=0
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# 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
|
||||
bb/copy . . . . . . . mmap-new-segment/imm32 # copy to EBX
|
||||
b8/copy . . . . . . . 0x5a/imm32/mmap # copy to EAX
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
== data
|
||||
# various constants used here were found in the Linux sources (search for file mman-common.h)
|
||||
mmap_new_segment: # type mmap_arg_struct
|
||||
mmap-new-segment: # type mmap_arg_struct
|
||||
# addr
|
||||
00 00 00 00 # null
|
||||
# len
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
# prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# call ascii_length(argv[1])
|
||||
# call ascii-length(argv[1])
|
||||
# push args
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
# call
|
||||
e8/call ascii_length/disp32
|
||||
e8/call ascii-length/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP
|
||||
|
||||
|
@ -33,24 +33,24 @@
|
|||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
ascii_length: # (s)
|
||||
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
|
||||
$ascii_length_loop:
|
||||
$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
|
||||
# if c == '\0' break
|
||||
81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX
|
||||
74/jump-if-equal $ascii_length_ret/disp8
|
||||
74/jump-if-equal $ascii-length-ret/disp8
|
||||
# ++s
|
||||
81 0/subop/add 3/mod/direct 2/rm32/EDX . . . . . 1/imm32 # add to EDX
|
||||
# ++result
|
||||
40/inc-EAX
|
||||
# loop
|
||||
eb/jump $ascii_length_loop/disp8
|
||||
$ascii_length_ret:
|
||||
eb/jump $ascii-length-loop/disp8
|
||||
$ascii-length-ret:
|
||||
# return (result in EAX)
|
||||
c3/return
|
||||
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
# 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
|
||||
# prolog
|
||||
89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP
|
||||
# call ascii_difference(argv[1], argv[2])
|
||||
# call ascii-difference(argv[1], argv[2])
|
||||
# push argv[2]
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0xc/disp8 . # push *(EBP+12)
|
||||
# push argv[1]
|
||||
ff 6/subop/push 1/mod/*+disp8 4/rm32/sib 5/base/EBP 4/index/none . . 0x8/disp8 . # push *(EBP+8)
|
||||
# call
|
||||
e8/call ascii_difference/disp32
|
||||
e8/call ascii-difference/disp32
|
||||
# discard args
|
||||
81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP
|
||||
# exit(EAX)
|
||||
|
@ -36,7 +36,7 @@
|
|||
b8/copy . . . . . . . 1/imm32/exit # copy to EAX
|
||||
cd/syscall 0x80/imm8
|
||||
|
||||
ascii_difference: # (s1, s2) : null-terminated ascii strings
|
||||
ascii-difference: # (s1, s2) : null-terminated ascii strings
|
||||
# a = first letter of s1 (ECX)
|
||||
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 0/mod/indirect 0/rm32/EAX . . . 0/r32/EAX . . # copy *EAX to EAX
|
||||
|
|
|
@ -15,6 +15,8 @@ set cpo&vim
|
|||
setlocal formatoptions-=t " allow long lines
|
||||
setlocal formatoptions+=c " but comments should still wrap
|
||||
|
||||
setlocal iskeyword+=-
|
||||
|
||||
syntax match subxComment /#.*$/ | highlight link subxComment Comment
|
||||
syntax match subxSalientComment /##.*$/ | highlight link subxSalientComment SalientComment
|
||||
set comments-=:#
|
||||
|
|
Loading…
Reference in New Issue