add test suite, help/exit functionality
This commit is contained in:
parent
a183d55b69
commit
6d162f5ae9
7 changed files with 441 additions and 69 deletions
|
@ -6,6 +6,9 @@
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
in {
|
in {
|
||||||
packages.${system}.default = pkgs.callPackage ./package.nix {};
|
packages.${system} = {
|
||||||
|
default = pkgs.callPackage ./package.nix {};
|
||||||
|
test = pkgs.callPackage ./test.nix {};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ stdenv.mkDerivation {
|
||||||
configurePhase = ''
|
configurePhase = ''
|
||||||
'';
|
'';
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
nasm -f elf main.asm
|
nasm -f elf main_start.asm
|
||||||
ld -m elf_i386 main.o -o main
|
ld -m elf_i386 main_start.o -o main
|
||||||
'';
|
'';
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
|
|
92
src/lib.asm
92
src/lib.asm
|
@ -7,13 +7,13 @@ slen:
|
||||||
push ebx
|
push ebx
|
||||||
mov ebx, eax
|
mov ebx, eax
|
||||||
|
|
||||||
slen_nextchar:
|
.loop:
|
||||||
cmp byte [eax], 0
|
cmp byte [eax], 0
|
||||||
jz slen_finished
|
jz .fin
|
||||||
inc eax
|
inc eax
|
||||||
jmp slen_nextchar
|
jmp .loop
|
||||||
|
|
||||||
slen_finished:
|
.fin:
|
||||||
sub eax, ebx
|
sub eax, ebx
|
||||||
pop ebx
|
pop ebx
|
||||||
ret
|
ret
|
||||||
|
@ -25,12 +25,12 @@ slen_finished:
|
||||||
|
|
||||||
clear_bss:
|
clear_bss:
|
||||||
cmp byte [eax], 0
|
cmp byte [eax], 0
|
||||||
jz clear_bss_finished
|
jz .fin
|
||||||
mov [eax], byte 0
|
mov [eax], byte 0
|
||||||
inc eax
|
inc eax
|
||||||
jmp clear_bss
|
jmp clear_bss
|
||||||
|
|
||||||
clear_bss_finished:
|
.fin:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; *******************************
|
; *******************************
|
||||||
|
@ -41,27 +41,52 @@ clear_bss_finished:
|
||||||
scmp:
|
scmp:
|
||||||
push ecx
|
push ecx
|
||||||
|
|
||||||
scmp_nextchar:
|
.loop:
|
||||||
mov cl, byte [ebx]
|
mov cl, byte [ebx]
|
||||||
cmp byte [eax], cl
|
cmp byte [eax], cl
|
||||||
jnz scmp_bad
|
jnz .bad
|
||||||
cmp byte [eax], 0
|
cmp byte [eax], 0
|
||||||
jz scmp_good
|
jz .good
|
||||||
inc eax
|
inc eax
|
||||||
inc ebx
|
inc ebx
|
||||||
jmp scmp_nextchar
|
jmp .loop
|
||||||
|
|
||||||
scmp_good:
|
.good:
|
||||||
mov eax, 0
|
mov eax, 0
|
||||||
jmp scmp_finished
|
jmp .fin
|
||||||
|
|
||||||
scmp_bad:
|
.bad:
|
||||||
mov eax, 1
|
mov eax, 1
|
||||||
|
|
||||||
scmp_finished:
|
.fin:
|
||||||
pop ecx
|
pop ecx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; ************************
|
||||||
|
; sdecprint : String -> IO
|
||||||
|
; prints string 1 shorter
|
||||||
|
; ************************
|
||||||
|
|
||||||
|
sdecprint:
|
||||||
|
push edx
|
||||||
|
push ecx
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
call slen
|
||||||
|
dec eax
|
||||||
|
|
||||||
|
mov edx, eax
|
||||||
|
pop eax
|
||||||
|
mov ecx, eax
|
||||||
|
mov ebx, 1
|
||||||
|
mov eax, 4
|
||||||
|
int 80h
|
||||||
|
|
||||||
|
pop ebx
|
||||||
|
pop ecx
|
||||||
|
pop edx
|
||||||
|
ret
|
||||||
|
|
||||||
; *********************
|
; *********************
|
||||||
; sprint : String -> IO
|
; sprint : String -> IO
|
||||||
; prints string
|
; prints string
|
||||||
|
@ -104,6 +129,45 @@ sprintln:
|
||||||
pop eax ; initial
|
pop eax ; initial
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; *******************
|
||||||
|
; bprint : Byte -> IO
|
||||||
|
; prints 1 byte
|
||||||
|
; *******************
|
||||||
|
|
||||||
|
bprint:
|
||||||
|
push edx
|
||||||
|
push ecx
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov edx, 1
|
||||||
|
pop eax
|
||||||
|
mov ecx, eax
|
||||||
|
mov ebx, 1
|
||||||
|
mov eax, 4
|
||||||
|
int 80h
|
||||||
|
|
||||||
|
pop ebx
|
||||||
|
pop ecx
|
||||||
|
pop edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
; *********************
|
||||||
|
; bprintln : Byte -> IO
|
||||||
|
; prints 1 byte + 0Ah
|
||||||
|
; *********************
|
||||||
|
|
||||||
|
bprintln:
|
||||||
|
call bprint
|
||||||
|
push eax
|
||||||
|
mov eax, 0Ah
|
||||||
|
push eax
|
||||||
|
mov eax, esp
|
||||||
|
call bprint
|
||||||
|
pop eax
|
||||||
|
pop eax
|
||||||
|
ret
|
||||||
|
|
||||||
; ************
|
; ************
|
||||||
; exit : IO
|
; exit : IO
|
||||||
; exit program
|
; exit program
|
||||||
|
|
60
src/main.asm
60
src/main.asm
|
@ -1,9 +1,18 @@
|
||||||
%include 'lib.asm'
|
%include 'lib.asm'
|
||||||
|
|
||||||
SECTION .data
|
SECTION .data
|
||||||
welcome_message db 'Welcome to this test program! It is experimental and very subject to change.', 0h
|
s:
|
||||||
prompt db 'Enter a string to print: ', 0h
|
.welcome_message db 'Welcome to this test program! It is experimental and very subject to change.', 0h
|
||||||
exit_str db 'exit', 0Ah, 0h
|
.prompt db 'repl>', 0h
|
||||||
|
.error db '[ERROR] ', 0h
|
||||||
|
.command db 'command ', 0h
|
||||||
|
.not_found db ' not found', 0h
|
||||||
|
|
||||||
|
fn:
|
||||||
|
.exit_name db 'exit', 0Ah, 0h
|
||||||
|
|
||||||
|
.help_name db 'help', 0Ah, 0h
|
||||||
|
.help_content db 'this program has just 2 commands right now: help and exit', 0Ah, ' help - prints this message', 0Ah, ' exit - quits the program', 0Ah, 'Have fun!', 0h
|
||||||
|
|
||||||
SECTION .bss
|
SECTION .bss
|
||||||
; resb ; 0001 byte
|
; resb ; 0001 byte
|
||||||
|
@ -14,27 +23,25 @@ SECTION .bss
|
||||||
sinput: resb 255 ; 255 bytes
|
sinput: resb 255 ; 255 bytes
|
||||||
|
|
||||||
SECTION .text
|
SECTION .text
|
||||||
global _start
|
start:
|
||||||
|
|
||||||
_start:
|
|
||||||
pop ecx ; number of arguments
|
pop ecx ; number of arguments
|
||||||
|
|
||||||
pop eax ; dispose of first value, the exe
|
pop eax ; dispose of first value, the exe
|
||||||
dec ecx
|
dec ecx
|
||||||
|
|
||||||
mov eax, welcome_message
|
mov eax, s.welcome_message
|
||||||
call sprintln
|
call sprintln
|
||||||
|
|
||||||
next_arg:
|
.arg_loop:
|
||||||
cmp ecx, 0h
|
cmp ecx, 0h
|
||||||
jz prompt_loop
|
jz .repl
|
||||||
pop eax
|
pop eax
|
||||||
call sprintln
|
call sprintln
|
||||||
dec ecx
|
dec ecx
|
||||||
jmp next_arg
|
jmp .arg_loop
|
||||||
|
|
||||||
prompt_loop:
|
.repl:
|
||||||
mov eax, prompt
|
mov eax, s.prompt
|
||||||
call sprint
|
call sprint
|
||||||
|
|
||||||
mov eax, sinput
|
mov eax, sinput
|
||||||
|
@ -47,15 +54,34 @@ prompt_loop:
|
||||||
int 80h
|
int 80h
|
||||||
|
|
||||||
mov eax, sinput
|
mov eax, sinput
|
||||||
mov ebx, exit_str
|
mov ebx, fn.exit_name
|
||||||
call scmp
|
call scmp
|
||||||
cmp byte eax, 0
|
cmp byte eax, 0
|
||||||
jz done
|
jz exit
|
||||||
|
|
||||||
mov eax, sinput
|
mov eax, sinput
|
||||||
|
mov ebx, fn.help_name
|
||||||
|
call scmp
|
||||||
|
cmp byte eax, 0
|
||||||
|
jz fn_help
|
||||||
|
|
||||||
|
mov eax, s.error
|
||||||
call sprint
|
call sprint
|
||||||
|
mov eax, s.command
|
||||||
|
call sprint
|
||||||
|
mov eax, sinput
|
||||||
|
call sdecprint
|
||||||
|
mov eax, s.not_found
|
||||||
|
call sprintln
|
||||||
|
|
||||||
jmp prompt_loop
|
jmp .repl
|
||||||
|
|
||||||
done:
|
fn_help:
|
||||||
call exit
|
push eax
|
||||||
|
|
||||||
|
mov eax, fn.help_content
|
||||||
|
call sprintln
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
jmp start.repl
|
||||||
|
|
7
src/main_start.asm
Normal file
7
src/main_start.asm
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
%include 'main.asm'
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
global _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
jmp start
|
242
src/test_start.asm
Normal file
242
src/test_start.asm
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
%include 'lib.asm'
|
||||||
|
|
||||||
|
SECTION .data
|
||||||
|
ts:
|
||||||
|
.test_welcome db "Welcome to the test suite!", 0h
|
||||||
|
|
||||||
|
.running_test db "running test ", 0h
|
||||||
|
.ellipsis db "... ", 0h
|
||||||
|
.error db "[ERROR] ", 0h
|
||||||
|
.failed db " failed", 0h
|
||||||
|
.failed_code db " failed with exit code ", 0h
|
||||||
|
.all_good db "all tests passed", 0h
|
||||||
|
.divider db "--------------------------------", 0h
|
||||||
|
|
||||||
|
slen_zero_length:
|
||||||
|
.name db "slen_zero_length", 0h
|
||||||
|
.should db "slen should be 0", 0h
|
||||||
|
.result db "slen result is ", 0h
|
||||||
|
|
||||||
|
scmp_a_zero_length:
|
||||||
|
.name db "scmp_a_zero_length", 0h
|
||||||
|
.should db "scmp should be 1", 0h
|
||||||
|
.result db "scmp result is ", 0h
|
||||||
|
|
||||||
|
scmp_b_zero_length:
|
||||||
|
.name db "scmp_b_zero_length", 0h
|
||||||
|
.should db "scmp should be 1", 0h
|
||||||
|
.result db "scmp result is ", 0h
|
||||||
|
|
||||||
|
scmp_both_zero_length:
|
||||||
|
.name db "scmp_both_zero_length", 0h
|
||||||
|
.should db "scmp should be 0", 0h
|
||||||
|
.result db "scmp result is ", 0h
|
||||||
|
|
||||||
|
scmp_both_short_s:
|
||||||
|
.name db "scmp_both_short_s", 0h
|
||||||
|
.should db "scmp should be 0", 0h
|
||||||
|
.result db "scmp result is ", 0h
|
||||||
|
|
||||||
|
cases:
|
||||||
|
.zero_length db 0h
|
||||||
|
.short_s db "1 short Test String!", 0h
|
||||||
|
|
||||||
|
numerals db "0123456789", 0h
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
global _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
mov eax, ts.test_welcome
|
||||||
|
call sprintln
|
||||||
|
|
||||||
|
mov eax, ts.divider
|
||||||
|
call sprintln
|
||||||
|
mov eax, slen_zero_length.name
|
||||||
|
call sprintln
|
||||||
|
call slen_zero_length_test
|
||||||
|
|
||||||
|
mov eax, ts.divider
|
||||||
|
call sprintln
|
||||||
|
mov eax, scmp_a_zero_length.name
|
||||||
|
call sprintln
|
||||||
|
call scmp_a_zero_length_test
|
||||||
|
|
||||||
|
mov eax, ts.divider
|
||||||
|
call sprintln
|
||||||
|
mov eax, scmp_b_zero_length.name
|
||||||
|
call sprintln
|
||||||
|
call scmp_b_zero_length_test
|
||||||
|
|
||||||
|
mov eax, ts.divider
|
||||||
|
call sprintln
|
||||||
|
mov eax, scmp_both_zero_length.name
|
||||||
|
call sprintln
|
||||||
|
call scmp_both_zero_length_test
|
||||||
|
|
||||||
|
mov eax, ts.divider
|
||||||
|
call sprintln
|
||||||
|
mov eax, scmp_both_short_s.name
|
||||||
|
call sprintln
|
||||||
|
call scmp_both_short_s_test
|
||||||
|
|
||||||
|
mov eax, ts.divider
|
||||||
|
call sprintln
|
||||||
|
mov eax, ts.all_good
|
||||||
|
call sprintln
|
||||||
|
|
||||||
|
call exit
|
||||||
|
|
||||||
|
slen_zero_length_test:
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov eax, cases.zero_length
|
||||||
|
call slen
|
||||||
|
push eax
|
||||||
|
mov eax, slen_zero_length.should
|
||||||
|
call sprintln
|
||||||
|
mov eax, slen_zero_length.result
|
||||||
|
call sprint
|
||||||
|
pop eax
|
||||||
|
cmp eax, 0
|
||||||
|
jnz slen_zero_length_test.failed
|
||||||
|
add eax, numerals
|
||||||
|
call bprintln
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.failed:
|
||||||
|
mov ebx, slen_zero_length.name
|
||||||
|
call failed_with_code
|
||||||
|
|
||||||
|
scmp_a_zero_length_test:
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov eax, cases.zero_length
|
||||||
|
mov ebx, cases.short_s
|
||||||
|
call scmp
|
||||||
|
push eax
|
||||||
|
mov eax, scmp_a_zero_length.should
|
||||||
|
call sprintln
|
||||||
|
mov eax, scmp_a_zero_length.result
|
||||||
|
call sprint
|
||||||
|
pop eax
|
||||||
|
cmp eax, 1
|
||||||
|
jnz scmp_a_zero_length_test.failed
|
||||||
|
add eax, numerals
|
||||||
|
call bprintln
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.failed:
|
||||||
|
mov ebx, scmp_a_zero_length.name
|
||||||
|
call failed_with_code
|
||||||
|
|
||||||
|
scmp_b_zero_length_test:
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov eax, cases.short_s
|
||||||
|
mov ebx, cases.zero_length
|
||||||
|
call scmp
|
||||||
|
push eax
|
||||||
|
mov eax, scmp_b_zero_length.should
|
||||||
|
call sprintln
|
||||||
|
mov eax, scmp_b_zero_length.result
|
||||||
|
call sprint
|
||||||
|
pop eax
|
||||||
|
cmp eax, 1
|
||||||
|
jnz scmp_b_zero_length_test.failed
|
||||||
|
add eax, numerals
|
||||||
|
call bprintln
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.failed:
|
||||||
|
mov ebx, scmp_b_zero_length.name
|
||||||
|
call failed_with_code
|
||||||
|
|
||||||
|
scmp_both_zero_length_test:
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov eax, cases.zero_length
|
||||||
|
mov ebx, eax
|
||||||
|
call scmp
|
||||||
|
push eax
|
||||||
|
mov eax, scmp_both_zero_length.should
|
||||||
|
call sprintln
|
||||||
|
mov eax, scmp_both_zero_length.result
|
||||||
|
call sprint
|
||||||
|
pop eax
|
||||||
|
cmp eax, 0
|
||||||
|
jnz scmp_both_zero_length_test.failed
|
||||||
|
add eax, numerals
|
||||||
|
call bprintln
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.failed:
|
||||||
|
mov ebx, scmp_both_zero_length.name
|
||||||
|
call failed_with_code
|
||||||
|
|
||||||
|
scmp_both_short_s_test:
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov eax, cases.short_s
|
||||||
|
mov ebx, eax
|
||||||
|
call scmp
|
||||||
|
push eax
|
||||||
|
mov eax, scmp_both_short_s.should
|
||||||
|
call sprintln
|
||||||
|
mov eax, scmp_both_short_s.result
|
||||||
|
call sprint
|
||||||
|
pop eax
|
||||||
|
cmp eax, 0
|
||||||
|
jnz scmp_both_zero_length_test.failed
|
||||||
|
add eax, numerals
|
||||||
|
call bprintln
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.failed:
|
||||||
|
mov ebx, scmp_both_zero_length.name
|
||||||
|
call failed_with_code
|
||||||
|
|
||||||
|
failed:
|
||||||
|
mov eax, ts.ellipsis
|
||||||
|
call sprintln
|
||||||
|
mov eax, ts.error
|
||||||
|
call sprint
|
||||||
|
mov eax, ebx
|
||||||
|
call sprint
|
||||||
|
mov eax, ts.failed
|
||||||
|
call sprint
|
||||||
|
call exit
|
||||||
|
|
||||||
|
failed_with_code:
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov eax, ts.ellipsis
|
||||||
|
call sprintln
|
||||||
|
mov eax, ts.error
|
||||||
|
call sprint
|
||||||
|
mov eax, ebx
|
||||||
|
call sprint
|
||||||
|
mov eax, ts.failed_code
|
||||||
|
call sprint
|
||||||
|
pop eax
|
||||||
|
add eax, numerals
|
||||||
|
call bprintln
|
||||||
|
call exit
|
30
test.nix
Normal file
30
test.nix
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
nasm,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "asm-test";
|
||||||
|
src = ./src;
|
||||||
|
nativeBuildInputs = [
|
||||||
|
nasm
|
||||||
|
];
|
||||||
|
buildInputs = [
|
||||||
|
];
|
||||||
|
configurePhase = ''
|
||||||
|
'';
|
||||||
|
buildPhase = ''
|
||||||
|
nasm -f elf test_start.asm
|
||||||
|
ld -m elf_i386 test_start.o -o test
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp test $out/bin/test
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
license = lib.licenses.wtfpl;
|
||||||
|
mainProgram = "test";
|
||||||
|
};
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue