5 stable releases
Uses new Rust 2024
| 1.0.4 | Dec 26, 2025 |
|---|---|
| 1.0.0 | Dec 25, 2025 |
| 0.1.0 |
|
#89 in Programming languages
262 downloads per month
155KB
3K
SLoC
LASM - Lucia Assembly Language
LASM (Lucia Assembly) is a Rust crate that provides JIT (Just-In-Time) compilation of a custom assembly language to native machine code via Cranelift. Its key features are high-performance JIT execution and seamless variable interaction between Rust and LASM code.
Why LASM?
JIT Compilation: Unlike interpreted languages, LASM compiles to native machine code at runtime using Cranelift, providing near-native performance with minimal overhead.
Variable Bridge: Seamlessly pass data between high-level Rust code and low-level assembly, enabling performance-critical sections while maintaining safety.
Modern Assembly: Register-based architecture with convenient syscalls, eliminating the boilerplate of traditional assembly programming.
Rust Integration: Drop LASM code anywhere in your Rust application for instant performance boosts.
Purpose: LASM was developed as the low-level execution backend for the Lucia Programming Language. It powers the lasm module, allowing performance-critical sections of an otherwise interpreted language to execute at near-native speed through JIT compilation.
Installation
As a Cargo Crate
Add to your Cargo.toml:
[dependencies]
lasm = { version = "1", package = "lucia-lasm" }
Or use the latest version from crates.io:
cargo add lucia-lasm
Building from Source
git clone https://github.com/SirPigari/lasm
cd lasm
cargo build --release
Usage
As a Library
use lasm::{compile, call, Target};
use std::collections::HashMap;
fn main() {
let code = r#"
mov 42, r0
syscall print_int
mov "\n", r1
mov 1, r0
mov 1, r2
syscall write
mov 0, r0
syscall exit
"#;
let target = Target::Native;
let compiled = compile(code, target).expect("Compilation failed");
let variables = HashMap::new();
let (exit_code, _) = call(&compiled, &variables).expect("Execution failed");
assert_eq!(exit_code, 0);
}
Command Line Tool
The crate includes a CLI binary for testing and development:
cargo run --bin lasm -- examples/hello.lasm
Or after building:
./target/release/lasm examples/hello.lasm
Library API
Basic Usage
use lasm::{compile, call, Target};
use std::collections::HashMap;
fn main() {
let code = r#"
mov 42, r0
syscall print_int
mov "\n", r1
mov 1, r0
mov 1, r2
syscall write
mov 0, r0
syscall exit
"#;
let target = Target::Native;
let compiled = compile(code, target).expect("Compilation failed");
let variables = HashMap::new();
let (exit_code, _) = call(&compiled, &variables).expect("Execution failed");
assert_eq!(exit_code, 0);
}
Variable Interaction
One of LASM's most powerful features is seamless variable passing between Rust and LASM code:
use lasm::{compile, call, Target, Value};
use std::collections::HashMap;
fn main() {
let code = r#"
; Load input variables
load input, r0 ; Load 'input' variable into r0
add r0, 10 ; Add 10 to it
push r0, output ; Store result in 'output' variable
mov 0, r0
syscall exit
"#;
let target = Target::Native;
let compiled = compile(code, target).expect("Compiling failed");
let mut variables = HashMap::new();
variables.insert("input".to_string(), Value::Int(42));
let (exit_code, updated_vars) = call(&compiled, &variables).expect("Execution failed");
if let Some(Value::Int(result)) = updated_vars.get("output") {
assert_eq!(*result, 52);
}
}
Variable Instructions
load "var_name", reg- Load a variable from Rust into a registerpush reg, "var_name"- Store a register value back to a Rust variable
Variables can be of type Int, Float, String, Ptr, or Null.
Architecture
Registers
- General Purpose: r0-r15 (64-bit)
- Stack Pointer: rsp
- Base Pointer: rbp
Instructions
Data Movement
mov <src>, <dst>- Move value from source to destinationldr <reg>, [<reg>]- Load from memory address in registerstr <reg>, [<reg>]- Store to memory address in registerload "var", <reg>- Load Rust variable into registerpush <reg>, "var"- Store register value to Rust variable
Arithmetic
add <dst>, <src>- Addsub <dst>, <src>- Subtractmul <dst>, <src>- Multiplydiv <dst>, <src>- Dividemod <dst>, <src>- Modulo
Floating Point Arithmetic
fadd <dst>, <src>- Add floatsfsub <dst>, <src>- Subtract floatsfmul <dst>, <src>- Multiply floatsfdiv <dst>, <src>- Divide floatsfmod <dst>, <src>- Modulo floats
Logic
and <dst>, <src>- Bitwise ANDor <dst>, <src>- Bitwise ORxor <dst>, <src>- Bitwise XORnot <dst>- Bitwise NOTshl <dst>, <src>- Shift leftshr <dst>, <src>- Shift right
Control Flow
cmp <left>, <right>- Compare registers/valuesbeq <label>- Branch if equalbne <label>- Branch if not equalblt <label>- Branch if less thanbgt <label>- Branch if greater thanble <label>- Branch if less or equalbge <label>- Branch if greater or equaljmp <label>- Unconditional jumpcall <label>- Call subroutineret- Return from subroutine
Stack Operations
pushr <reg>- Push register onto stackpopr <reg>- Pop from stack into register
Operands
Instructions can take:
- Immediate values: Numbers like
42or strings like"hello" - Registers:
r0,r1, etc. - Labels: For jumps and calls
Syscalls
LASM provides high-level syscalls that abstract away low-level system calls:
I/O
syscall write- Write to file descriptor (fd in r0, buffer in r1, count in r2)syscall read- Read from file descriptorsyscall print_int- Print integer (value in r0)syscall print_float- Print float (bits in r0)syscall print_str- Print null-terminated string (pointer in r0)syscall flush- Flush output stream (fd in r0)
Memory
syscall malloc- Allocate memory (size in r0, returns pointer in r0)syscall free- Free memory (pointer in r0)syscall memcpy- Copy memory (dst in r0, src in r1, len in r2)syscall memset- Set memory (dst in r0, val in r1, len in r2)
Strings
syscall strcmp- Compare strings (str1 in r0, str2 in r1, returns comparison in r0)syscall strcpy- Copy string (dst in r0, src in r1, returns dst in r0)syscall strlen- Get string length (str in r0, returns length in r0)syscall starts_with- Check if string starts with prefix (str in r0, prefix in r1, returns 1/0 in r0)syscall streq- Check if strings are equal (str1 in r0, str2 in r1, returns 1/0 in r0)syscall ends_with- Check if string ends with suffix (str in r0, suffix in r1, returns 1/0 in r0)syscall trim- Trim whitespace (str in r0, out in r1, returns length in r0)syscall trim_start- Trim leading whitespace (str in r0, out in r1, returns length in r0)syscall trim_end- Trim trailing whitespace (str in r0, out in r1, returns length in r0)syscall isws- Check if string is all whitespace (str in r0, returns 1/0 in r0)
Conversion
syscall atoi- String to integer (str in r0, returns int in r0)syscall atof- String to float (str in r0, returns float bits in r0)syscall itoa- Integer to string (int in r0, buffer in r1, size in r2, returns length in r0)syscall ftoa- Float to string (bits in r0, buffer in r1, size in r2, returns length in r0)syscall itof- Integer to float (int in r0, returns float bits in r0)syscall ftoi- Float to integer (bits in r0, returns int in r0)
Math
syscall fadd- Add floats (a bits in r0, b bits in r1, returns result bits in r0)syscall fsub- Subtract floatssyscall fmul- Multiply floatssyscall fdiv- Divide floatssyscall fmod- Modulo floats
Time & Random
syscall time- Get current time (returns nanoseconds in r0)syscall fmt_time- Format time (total_nanos in r0, format in r1, buffer in r2, returns length in r0)syscall rand- Generate random float (seed in r0, returns float bits in r0)
Utilities
syscall sleep- Sleep for milliseconds (ms in r0)syscall system- Execute system command (cmd in r0, returns exit code in r0)
System
syscall exit- Exit program (status in r0)
Examples
Hello World
; Hello World
mov "Hello, World!\n", r1
mov 1, r0
mov 14, r2
syscall write
mov 0, r0
syscall exit
Calculator
; Simple calculator
mov 10, r0
mov 20, r1
add r0, r1 ; r0 = 30
syscall print_int
mov "\n", r1
mov 1, r0
mov 1, r2
syscall write
mov 0, r0
syscall exit
Running Examples
The repository includes example LASM programs in the examples/ directory:
# Hello World
cargo run -- examples/hello.lasm
# Calculator
cargo run -- examples/calculator.lasm
# Time display
cargo run -- examples/time.lasm
# Interactive shell
cargo run -- examples/shell.lasm
Or after building the release binary:
./target/release/lasm examples/hello.lasm
Syntax Details
- Comments: Start with
;and continue to end of line - Labels: End with
:and can be jumped to - Strings: Enclosed in double quotes, null-terminated automatically
- Numbers: Decimal integers, can be used as immediates
- Case Sensitive: All keywords and register names are case sensitive
Error Handling
LASM provides clear error messages for:
- Syntax errors
- Undefined labels
- Invalid register names
- Unsupported syscalls
- File I/O errors
Performance
LASM's JIT compilation provides significant performance advantages for compute-intensive tasks:
use lasm::{compile, call, Target, Value};
use std::collections::HashMap;
fn main() {
// Simple variable manipulation example
let simple_lasm = r#"
load "input", r0 ; Load input value
add r0, 100 ; Add 100
push r0, "output" ; Store result
mov 0, r0
syscall exit
"#;
// Compile once, reuse for multiple runs
let target = Target::Native;
let compiled = compile(simple_lasm, target).expect("Compile failed");
// Execute with different inputs
for input in 0..10 {
let mut vars = HashMap::new();
vars.insert("input".to_string(), Value::Int(input));
let (exit_code, result_vars) = call(&compiled, &vars).expect("Execution failed");
if let Some(Value::Int(result)) = result_vars.get("output") {
println!("Input: {}, Output: {}", input, result);
}
}
}
JIT compilation enables dynamic code generation while maintaining high performance.
Limitations
- 64-bit architecture only (x86_64, AArch64)
- No floating point registers (floats stored as bits in general registers)
- No direct hardware access
- Stack operations are simulated
Testing
Run the test suite:
cargo test
The tests include various LASM programs demonstrating different features and syscalls.
Contributing
Contributions are welcome! This is a Rust crate that can be extended in several ways:
- Additional Syscalls: Add new high-level operations
- Optimization: Improve code generation and performance
- Error Handling: Better error messages and recovery
- Documentation: More examples and tutorials
- Cross-Platform: Support for additional operating systems
- Features: New instructions or language constructs
Development Setup
git clone https://github.com/SirPigari/lasm
cd lasm
cargo build
cargo test
Publishing
To publish to crates.io:
cargo publish
Make sure to update the version in Cargo.toml and tag the release.
License
Dependencies
~10–21MB
~268K SLoC