added CLI

This commit is contained in:
afonya 2025-06-16 18:15:57 +02:00
parent bd5ce01234
commit 5d43674d0e
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
8 changed files with 395 additions and 357 deletions

View file

@ -1,7 +1,5 @@
use std::{any::Any, collections::HashMap, process, vec};
use crate::{enviroment, errors::{create_error, print_error, ErrorSubType, ErrorType}, Context};
const ASXVERSION: [u8; 3] = [0,1,0];
use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{create_error, print_error, ErrorSubType, ErrorType}, Context};
#[derive(Debug, Clone)]
pub enum VMMemory {
@ -54,36 +52,12 @@ pub struct VMMemoryNativeFunction {
pub variable_id: u32,
}
#[derive(Debug, Clone)]
struct DecompiledFunction {
body: Vec<DecompiledOperation>,
variables: Vec<Variable>,
strings: HashMap<u32, String>,
functions: HashMap<u32, u32>
}
#[derive(Debug, Clone)]
pub struct DecompiledOperation {
pub opcode: u8,
pub arg1: u8,
pub arg2: i64,
pub arg3: u8,
pub pos: usize,
}
#[derive(Debug, Clone)]
pub struct Register {
id: u8,
pointer: usize
}
#[derive(Debug, Clone)]
struct Variable {
name: String,
id: u32,
start: usize,
end: usize
}
pub struct CallStack {
pub func: usize,
pub return_reg: usize,
@ -101,55 +75,6 @@ pub struct Machine {
pub storage: Vec<Box<dyn Any>>,
}
fn read_be_num(input: &[u8]) -> usize {
let mut result: usize = 0;
for i in 0..input.len() {
result <<= 8;
result |= input[i] as usize;
}
return result;
}
fn read_str(input: &[u8]) -> String {
String::from_utf8(input.to_vec()).expect("Invalid UTF-8 sequence")
}
fn read_bin(input: &[u8]) -> String {
let mut result = String::new();
for &byte in input {
result.push_str(&format!("{:08b}", byte));
}
return result;
}
fn bin_to_num(bin: String) -> usize {
let mut result: usize = 0;
for (i, c) in bin.chars().rev().enumerate() {
if c == '1' {
result += 1 << i;
}
}
return result;
}
fn bin_to_snum(bin: String) -> i64 {
let mut result: i64 = 0;
let mut is_negative = false;
for (i, c) in bin.chars().rev().enumerate() {
if c == '1' {
if i == bin.len() - 1 {
is_negative = true;
} else {
result += 1 << i;
}
}
}
if is_negative {
result = -result;
}
return result;
}
fn get_register_by_id(registers: &Vec<Register>, id: u8) -> Option<&Register> {
for reg in registers {
if reg.id == id {
@ -226,44 +151,6 @@ fn get_mem_tbl_val(tbl: &VMMemoryTable, key: VMMemory) -> Option<&VMMemory> {
None
}
fn operation_to_name(opcode: u8) -> String {
match opcode {
0 => "HLT".to_string(),
1 => "LDS".to_string(),
2 => "LDM".to_string(),
3 => "LDI".to_string(),
4 => "LDB".to_string(),
5 => "LDF".to_string(),
6 => "LDN".to_string(),
7 => "ASS".to_string(),
8 => "UNB".to_string(),
9 => "MOV".to_string(),
10 => "ADD".to_string(),
11 => "SUB".to_string(),
12 => "MUL".to_string(),
13 => "DIV".to_string(),
14 => "POW".to_string(),
15 => "MOD".to_string(),
16 => "AND".to_string(),
17 => "OR".to_string(),
18 => "EQ".to_string(),
19 => "NEQ".to_string(),
20 => "GRE".to_string(),
21 => "GRQ".to_string(),
22 => "LES".to_string(),
23 => "LEQ".to_string(),
24 => "NOT".to_string(),
25 => "JMP".to_string(),
26 => "CJP".to_string(),
27 => "CAL".to_string(),
28 => "PSH".to_string(),
29 => "RET".to_string(),
30 => "GET".to_string(),
31 => "SET".to_string(),
_ => panic!("Unknown operation code: {}", opcode),
}
}
fn get_var_id(var: &VMMemory) -> u32 {
match var {
VMMemory::String(str) => str.variable_id,
@ -428,76 +315,6 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
memory[reg3_pointer] = result;
}
fn load_func(data: Vec<u8>, offset: &mut usize) -> DecompiledFunction {
let var_id_len = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
let mut variables: Vec<Variable> = vec![];
for _ in 0..var_id_len {
let name_len = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
let name = read_str(&data[*offset..*offset + name_len]);
*offset += name_len;
let var_id = read_be_num(&data[*offset..*offset + 3]) as u32;
*offset += 3;
let start = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
let end = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
variables.push(Variable { name: name, id: var_id, start: start, end: end });
}
let mut strings: HashMap<u32, String> = HashMap::new();
let string_count = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
for _ in 0..string_count {
let str_id = read_be_num(&data[*offset..*offset + 3]) as u32;
*offset += 3;
let str_len = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
let str_value = read_str(&data[*offset..*offset + str_len]);
*offset += str_len;
strings.insert(str_id, str_value);
}
let mut functions: HashMap<u32, u32> = HashMap::new();
let function_count = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
for _ in 0..function_count {
let func_id = read_be_num(&data[*offset..*offset + 3]) as u32;
*offset += 3;
let func_pos = read_be_num(&data[*offset..*offset + 4]) as u32;
*offset += 4;
functions.insert(func_id, func_pos);
}
let mut body: Vec<DecompiledOperation> = Vec::new();
let instr_len: usize = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
for _ in 0..instr_len {
let op = read_bin(&data[*offset..*offset + 10]);
*offset += 10;
let op_code = bin_to_num(op[0..5].to_string());
let arg1 = bin_to_num(op[5..9].to_string());
let arg2 = bin_to_snum(op[9..73].to_string());
let arg3 = bin_to_num(op[73..77].to_string());
let pos = read_be_num(&data[*offset..*offset + 4]);
*offset += 4;
body.push(DecompiledOperation {
opcode: op_code as u8,
arg1: arg1 as u8,
arg2: arg2,
arg3: arg3 as u8,
pos: pos,
});
}
println!("Variables: {:?}", variables);
println!("Strings: {:?}", strings);
println!("Functions: {:?}", functions);
return DecompiledFunction {
body: body,
variables: variables,
strings: strings,
functions: functions,
};
}
impl Machine {
pub fn new(ctx: Vec<Context>) -> Self {
let mut registers = Vec::new();
@ -525,19 +342,9 @@ impl Machine {
};
}
pub fn load(&mut self, data: Vec<u8>) {
if data[0..3] != *"ASX".as_bytes() {
panic!("Invalid ASX file header");
}
if data[3..6] != ASXVERSION {
panic!("Unsupported ASX version");
}
let _func_count = read_be_num(&data[6..10]);
let mut offset = 10;
while offset < data.len() {
let func = load_func(data.clone(), &mut offset);
self.functions.push(func);
}
pub fn load(&mut self, data: &Vec<u8>) {
let dec = process(data);
self.functions = dec.functions;
}
pub fn run(&mut self) {