diff --git a/.gitignore b/.gitignore index fb7ae50..c3e9b27 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ # asm gen testing /asm + +# output +/out diff --git a/src/asm_gen.rs b/src/asm_gen.rs index f2a7280..8ba37b5 100644 --- a/src/asm_gen.rs +++ b/src/asm_gen.rs @@ -6,21 +6,17 @@ pub fn generate(tokens: Vec) -> String { let mut output = String::new(); // reserving mem + // global start label + // create the pointer for our data output.push_str( "section .bss\n\ - data: resb 65536\n", - ); - - // global start label - output.push_str( - "global _start\n\ + data: resb 65536\n\ + global _start\n\ section .text\n\ - _start:\n", + _start:\n\ + mov rdx, data\n", ); - // create the pointer for our data - output.push_str("mov rdx, data\n"); - let mut loops = 0; let mut stack: VecDeque = VecDeque::new(); for token in tokens { diff --git a/src/compiler.rs b/src/compiler.rs index 15f832b..aecf7fe 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,4 +1,5 @@ -use std::{fs, io::Write, path::PathBuf}; +use core::panic; +use std::{env, fs, io::Write, path::PathBuf, process}; use crate::{asm_gen, tokenizer}; @@ -6,7 +7,57 @@ pub fn compile(program: Vec, name: String) { let tokens = tokenizer::tokenize(program); let asm = asm_gen::generate(tokens); - let path: PathBuf = [".", &format!("./{name}.asm")].iter().collect(); + let out_path: PathBuf = [".", "out"].iter().collect(); + fs::DirBuilder::new() + .recursive(true) + .create(out_path) + .unwrap(); + + let path: PathBuf = [".", "out", &format!("{name}.asm")].iter().collect(); let mut file = fs::File::create(path).unwrap(); file.write_all(asm.as_bytes()).unwrap(); + + if !is_program_in_path("nasm") { + panic!("No nasm binary found in PATH"); + } + + process::Command::new("nasm") + .args(["-felf64", &format!("./out/{name}.asm")]) + .output() + .expect("failed compile step"); + + if !is_program_in_path("ld") { + panic!("No ld binary found in PATH"); + } + + process::Command::new("ld") + .args([ + "-s", + "-o", + &format!("./out/{name}"), + &format!("./out/{name}.o"), + ]) + .output() + .expect("failed linking step"); + + process::Command::new("rm") + .args([ + "-r", + &format!("./out/{name}.asm"), + &format!("./out/{name}.o"), + ]) + .output() + .expect("failed removing artifcats step"); +} + +fn is_program_in_path(program: &str) -> bool { + if let Ok(path) = env::var("PATH") { + for p in path.split(":") { + let p_str = format!("{}/{}", p, program); + if fs::metadata(p_str).is_ok() { + return true; + } + } + } + false }