diff --git a/bootler/package.nix b/bootler/package.nix index 4e18816..c4faf29 100644 --- a/bootler/package.nix +++ b/bootler/package.nix @@ -14,14 +14,13 @@ in ${nasm}/bin/nasm asm/boot.asm -o boot.bin ${nasm}/bin/nasm asm/kernel.asm -o dummy.bin - dd if=/dev/zero of=${bootImg} bs=512 count=2 + dd if=/dev/zero of=${bootImg} bs=512 count=2880 dd if=boot.bin of=${bootImg} conv=notrunc dd if=dummy.bin of=${bootImg} bs=512 seek=1 conv=notrunc ''; installPhase = '' mkdir -p $out/bin cp boot.bin $out/bin - cp dummy.bin $out/bin cp ${bootImg} $out/bin # create emulation binary diff --git a/flake.nix b/flake.nix index a631534..1ce6341 100644 --- a/flake.nix +++ b/flake.nix @@ -19,15 +19,15 @@ }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; - pkgsWithRustOverlay = import nixpkgs { - inherit system; - overlays = [(import rust-overlay)]; - }; + pkgsWithRustOverlay = pkgs.extend (import rust-overlay); in { packages.${system} = { bootler = pkgs.callPackage ./bootler/package.nix {}; bootle = pkgsWithRustOverlay.callPackage ./bootle/package.nix { - naersk = naersk; + inherit naersk; + bootler = self.packages.${system}.bootler; + }; + twasm = pkgs.callPackage ./twasm/package.nix { bootler = self.packages.${system}.bootler; }; }; @@ -35,6 +35,7 @@ inputsFrom = [ self.packages.${system}.bootle self.packages.${system}.bootler + self.packages.${system}.twasm ]; }; }; diff --git a/twasm/README.md b/twasm/README.md new file mode 100644 index 0000000..c7a2786 --- /dev/null +++ b/twasm/README.md @@ -0,0 +1,32 @@ +# twasm + +this will be a self hosted, very minimal subset of 64 bit asm + +### goals + +I want to compile Bootler and Twasm with the Twasm assembler + +### memory map + +``` ++------ 0x00100000 ------+ +| hardware, bios stuff | ++------ 0x00080000 ------+ +| output binary | ++------ 0x00070000 ------+ +| token table | ++------ 0x00060000 ------+ +| | +| | ++------------------------+ +| input | ++------------------------+ this is lined up to a sector +| | and this is less than a sector ++------------------------+ +| assembler | ++------ 0x00010000 ------+ +| bootloader, bios, etc. | ++------------------------+ +``` + +each word represents a token on the token table. diff --git a/twasm/asm/main.asm b/twasm/asm/main.asm new file mode 100644 index 0000000..4cd4e1f --- /dev/null +++ b/twasm/asm/main.asm @@ -0,0 +1,161 @@ +LOAD_ADDR equ 0x00010000 ; address this program is loaded at + +TOKEN_TABLE_ADDR equ 0x00060000 ; address the token table is loaded at +TOKEN_TABLE_SIZE equ 0x1000 ; max length of table + +TEST_ARENA_ADDR equ 0x00060000 ; address to run tests at +TEST_ARENA_SIZE equ 0x1000 ; maximum size tests can use + +OUTPUT_ADDR equ 0x00070000 ; address of outputed binary +OUTPUT_SIZE equ 0x1000 ; max length of outputed binary + +[bits 64] +[org LOAD_ADDR] + +start: + mov rsi, msg_welcome + call print + + call run_tests + + jmp halt + +; +; tokenising +; + +; copy_token +; +; description: +; copies a token from one spot in memory to another +; and returns metadata about that token +; +; parameters: +; rdi -> start of asm command to be read +; rsi -> start of buffer to be written +; +; returned: +copy_token: + mov rax, rdi + .loop: + cmp al, " " + je .continue + jne .break + .continue: + call copy_byte + .break: + inc rax + ret + +; copy_byte +; +; description: +; copies a byte from one spot in memory to another +; +; parameters: +; rdi -> word to be read +; rsi -> word to be written +; +; returned: +; al = byte that was read +copy_byte: + mov al, [rdi] + mov [rsi], al + ret + +; +; utilities +; + +; print +; +; description: +; prints a null-terminated string +; +; parameters: +; rsi -> start of null-terminated string +; dx = port to output to +print: + .loop: + mov al, [rsi] + test al, al + jz .done + out dx, al + inc rsi + jmp .loop + .done: + ret + +; halt +; +; description: +; halts the program, silly :) +halt: + mov rsi, msg_halt + call print + hlt + jmp halt + +; +; tests +; + +; run_tests +; +; description: +; runs all tests +; +; parameters: +; dx = port to output to +run_tests: + mov rsi, .msg + call print + + call test_copy_byte + + ret + .msg db "running test suite...", 0x0D, 0x0A, 0x00 + +; test_copy_byte +; +; description: +; makes sure copy_byte function works by testing the following +; - that it copies one byte to a specified memory address +; - that it returns the copied byte in al +; +; parameters: +; dx = port to output to +test_copy_byte: + mov rsi, .msg + call print + + mov rdi, test_byte ; byte to be copied + mov rsi, TEST_ARENA_ADDR ; location of test + call copy_byte + + mov cx, [rsi] + cmp ax, cx ; compare returned byte to copied byte + jne .fail + je .pass + + .pass: + mov rsi, msg_pass + call print + ret + .fail: + mov rsi, msg_fail + call print + ret + .msg db "test_copy_byte...", 0x00 + +; +; data +; + +msg_welcome db "Welcome to Twasm", 0x0D, 0x0A, 0x00 +msg_halt db "halted.", 0x0D, 0x0A, 0x00 +msg_pass db "passed.", 0x0D, 0x0A, 0x00 +msg_fail db "failed.", 0x0D, 0x0A, 0x00 + +test_byte db "T" +test_token db "Test Token" ; two tokens, one followed by a space and one by nothing diff --git a/twasm/package.nix b/twasm/package.nix new file mode 100644 index 0000000..f621780 --- /dev/null +++ b/twasm/package.nix @@ -0,0 +1,41 @@ +{ + bootler, + stdenv, + nasm, + qemu, + ... +}: +stdenv.mkDerivation { + pname = "twasm"; + version = "0.1.0"; + src = ./.; + buildPhase = '' + ${nasm}/bin/nasm asm/main.asm -o out.bin + ''; + installPhase = '' + dd if=/dev/zero of=disk bs=512 count=2880 + dd if=${bootler}/bin/boot.bin of=disk conv=notrunc + dd if=out.bin of=disk bs=512 seek=1 conv=notrunc + + mkdir -p $out/bin + + cat<$out/bin/twasm + #!/usr/bin/env bash + + mkdir -p ./.bootle + cp $(echo $out)/bin/disk ./.bootle/disk + chmod a+w ./.bootle/disk + + ${qemu}/bin/qemu-system-x86_64 \ + -nographic \ + -drive file=./.bootle/disk,format=raw,index=0,media=disk + + rm ./.bootle -r + EOF + + chmod +x $out/bin/twasm + + cp out.bin $out/bin + cp disk $out/bin + ''; +}