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";
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
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 = ''
|
||||
'';
|
||||
buildPhase = ''
|
||||
nasm -f elf main.asm
|
||||
ld -m elf_i386 main.o -o main
|
||||
nasm -f elf main_start.asm
|
||||
ld -m elf_i386 main_start.o -o main
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
|
|
92
src/lib.asm
92
src/lib.asm
|
@ -7,13 +7,13 @@ slen:
|
|||
push ebx
|
||||
mov ebx, eax
|
||||
|
||||
slen_nextchar:
|
||||
.loop:
|
||||
cmp byte [eax], 0
|
||||
jz slen_finished
|
||||
jz .fin
|
||||
inc eax
|
||||
jmp slen_nextchar
|
||||
jmp .loop
|
||||
|
||||
slen_finished:
|
||||
.fin:
|
||||
sub eax, ebx
|
||||
pop ebx
|
||||
ret
|
||||
|
@ -25,12 +25,12 @@ slen_finished:
|
|||
|
||||
clear_bss:
|
||||
cmp byte [eax], 0
|
||||
jz clear_bss_finished
|
||||
jz .fin
|
||||
mov [eax], byte 0
|
||||
inc eax
|
||||
jmp clear_bss
|
||||
|
||||
clear_bss_finished:
|
||||
.fin:
|
||||
ret
|
||||
|
||||
; *******************************
|
||||
|
@ -41,27 +41,52 @@ clear_bss_finished:
|
|||
scmp:
|
||||
push ecx
|
||||
|
||||
scmp_nextchar:
|
||||
.loop:
|
||||
mov cl, byte [ebx]
|
||||
cmp byte [eax], cl
|
||||
jnz scmp_bad
|
||||
jnz .bad
|
||||
cmp byte [eax], 0
|
||||
jz scmp_good
|
||||
jz .good
|
||||
inc eax
|
||||
inc ebx
|
||||
jmp scmp_nextchar
|
||||
jmp .loop
|
||||
|
||||
scmp_good:
|
||||
.good:
|
||||
mov eax, 0
|
||||
jmp scmp_finished
|
||||
jmp .fin
|
||||
|
||||
scmp_bad:
|
||||
.bad:
|
||||
mov eax, 1
|
||||
|
||||
scmp_finished:
|
||||
.fin:
|
||||
pop ecx
|
||||
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
|
||||
; prints string
|
||||
|
@ -104,6 +129,45 @@ sprintln:
|
|||
pop eax ; initial
|
||||
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 program
|
||||
|
|
60
src/main.asm
60
src/main.asm
|
@ -1,9 +1,18 @@
|
|||
%include 'lib.asm'
|
||||
|
||||
SECTION .data
|
||||
welcome_message db 'Welcome to this test program! It is experimental and very subject to change.', 0h
|
||||
prompt db 'Enter a string to print: ', 0h
|
||||
exit_str db 'exit', 0Ah, 0h
|
||||
s:
|
||||
.welcome_message db 'Welcome to this test program! It is experimental and very subject to change.', 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
|
||||
; resb ; 0001 byte
|
||||
|
@ -14,27 +23,25 @@ SECTION .bss
|
|||
sinput: resb 255 ; 255 bytes
|
||||
|
||||
SECTION .text
|
||||
global _start
|
||||
|
||||
_start:
|
||||
start:
|
||||
pop ecx ; number of arguments
|
||||
|
||||
pop eax ; dispose of first value, the exe
|
||||
dec ecx
|
||||
|
||||
mov eax, welcome_message
|
||||
mov eax, s.welcome_message
|
||||
call sprintln
|
||||
|
||||
next_arg:
|
||||
.arg_loop:
|
||||
cmp ecx, 0h
|
||||
jz prompt_loop
|
||||
jz .repl
|
||||
pop eax
|
||||
call sprintln
|
||||
dec ecx
|
||||
jmp next_arg
|
||||
jmp .arg_loop
|
||||
|
||||
prompt_loop:
|
||||
mov eax, prompt
|
||||
.repl:
|
||||
mov eax, s.prompt
|
||||
call sprint
|
||||
|
||||
mov eax, sinput
|
||||
|
@ -47,15 +54,34 @@ prompt_loop:
|
|||
int 80h
|
||||
|
||||
mov eax, sinput
|
||||
mov ebx, exit_str
|
||||
mov ebx, fn.exit_name
|
||||
call scmp
|
||||
cmp byte eax, 0
|
||||
jz done
|
||||
jz exit
|
||||
|
||||
mov eax, sinput
|
||||
mov ebx, fn.help_name
|
||||
call scmp
|
||||
cmp byte eax, 0
|
||||
jz fn_help
|
||||
|
||||
mov eax, s.error
|
||||
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:
|
||||
call exit
|
||||
fn_help:
|
||||
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