Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Scalable Assembler System (SAS): A Modular Assembler Based on Rust

README: English | 中文

Introduction

The Scalable Assembler System (SAS) is an assembler designed in Rust. Its key feature is the use of uniformly designed data structures to accelerate the assembly process and simplify adaptation. Compared to existing assemblers, SAS features a cleaner, more efficient architectural design and can reduce assembly time in certain scenarios.

SAS is currently still in active development. We welcome anyone to participate in its development or offer valuable suggestions.

Currently Supported ISAs: AMD64, AArch64, RISC-V. For specific adaptation details and ELF file format support status, please refer to the "Support Status" section.

Key Highlights

  • Highly Abstracted Modular Design: Uses standardized data structures to store data required for the assembly process, providing a universal abstraction of the assembly workflow. This greatly reduces the difficulty of maintaining and extending a multi-ISA assembler.
  • Powered by Rust: Leverages Rust's memory safety features and zero-cost abstractions, combined with powerful compile-time optimizations from LLVM, to squeeze every drop of hardware performance.
  • Significant Compilation Acceleration: Compared to the existing GNU Assembler (GAS), SAS can deliver a 30% to 100% performance boost (depending on the target ISA).

Using SAS

Please make sure you have configured the Rust compilation environment and cargo, and have a stable Internet connection. Download SAS to your local computer, and then run cargo build --release in the SAS directory.

The generated sas binary file will be saved in the ./target/release/ directory. You can move it to any location and run it. The way to use SAS is similar to other assemblers. The currently supported parameters are as follows:

-o|--output Accepts several strings. Changes the output object file address. Defaults to "test.uap".
-l|--log Takes a string that specifies the log file location. Special locations include "stdout" for standard output and "muted" to disable logging.
-e|--level Accepts an i32 decimal number. Specifies the log level. The lower the level, the more detailed the logs printed. The default is 0.
-f|--format Takes a string. Specifies the output file format. Currently supported formats are "scalable_executable" and "executable_and_linkable". Defaults to "scalable_executable".
--amd64 Accepts several strings. Specifies the address of AMD64 assembly or object files. Defaults to empty, which means no AMD64 assembly or linking.
--arm64 Accepts several strings. Specifies the address of AArch64 assembly or object file. Defaults to empty, which means no AArch64 assembly or linking.
--riscv64 Accepts several strings. Specifies the address of the RISCV64 assembly or object file. Defaults to empty, which means no RISCV64 assembly or linking.
-h|--help No arguments (for now). Print help information.
-L|--link No parameters. Use this parameter to use the SAS built-in linker. Currently this parameter is invalid. You need to modify config.link in main.rs and recompile to implement this function.

For example, using sas --amd64 blocksort.s bzip2.s bzlib.s compress.s crctable.s decompress.s huffman.s randtable.s -o bzip2.uap will read blocksort.s bzip2.s bzlib.s compress.s crctable.s decompress.s huffman.s randtable.s and assemble, then link, finally generate file test.uap 。

SAS will support more parameters in the future.

Adding Support for SAS

Adding ISA Support

Thanks to SAS's unified data structure design, adding adaptations is quite simple. You only need to add the following to src/asmanager/${YOUR_ISA}/, and SAS will support your ISA:

  • (Required) ISA register information stored as the Register type. Recommended for src/asmanager/${YOUR_ISA}/arch.rs.
  • (Required) ISA instruction information stored as OperationDesc. Recommended for src/asmanager/${YOUR_ISA}/arch.rs.
  • (Required) An ISA object class implementing the ArchDesc interface and its constructor. The constructor must initialize the SAS lexer and parser, and include necessary syntax processing functions. Recommended for src/asmanager/${YOUR_ISA}/mod.rs.
  • (Required) Machine instruction classes implementing the OpCode interface. Recommended for src/asmanager/${YOUR_ISA}/mod.rs.
  • (Required) Implement any macro instructions exclusive to the ISA. Recommended for src/asmanager/${YOUR_ISA}/mod.rs.
  • (Required) Add the ISA ID in src/asmanager.rs and append the initialization function to ARCH_VEC. The ISA ID corresponds to its position in ARCH_VEC, so conflicts must be avoided.
  • (Recommended) Implement necessary unit tests.
  • (Recommended) Write documentation, stored in src/asmanager/${YOUR_ISA}/info.md.
  • (Recommended) Consolidate necessary constants in src/asmanager/${YOUR_ISA}/data.rs.
  • (Recommended) Leave helpful suggestions for other SAS maintainers.

Next, let's introduce some of SAS's core data structures:

The Register class describes a register, including its name, number, and other information. The specific implementation is as follows.

pub struct Register{
    pub name:&'static str,//register name
    pub resource:u32,//reserved for future use
    pub id:u16,//Stores the register number, and this field will be filled into the instruction during assembly.
    pub class:u8,//Stores the register category number, which is defined by the ISA
    pub flag:u8,
}

The Operand class describes an operand, which provides up to two register addressing and an immediate or label addressing, and provides custom flags for ISA use. It is defined as follows:

pub enum MemoryOffset {
    None,             // No additional addressing
    Label(Box<str>),  // Identifier-related addressing
    Value(i64),       // Constant-related addressing
    // Float(f64),    // Unused
}

pub struct Operand {
    pub base: Option<&'static Register>,  // Base address for memory addressing, or target register for register addressing
    pub scale: Option<&'static Register>, // Scale register for indexed addressing
    pub offset: MemoryOffset,             // Holds other addressing mode data (defined above)
    pub flag: u32,
    pub class: u16,                       // Operand class. 0-127: memory-related (e.g., base addressing), 128-255: register addressing, 256: immediate addressing. The register addressing ID is universally defined as `register class ID | 128`. Further definitions are up to the ISA.
}

OperationDesc类依赖于Qualifier、OperandType类,具体实现如下:

pub enum OperandType {
    // [Signed | Negative |     | u64 | u32 | u16 | u8 | ? | 1 | 0]
    // [15..              4 | 3 | 2   | 1   | 0]
    Immediate([u8; 2]),                           // Accepted immediate value info
    Register(u64),                                // Accepted register class bitmask
    Memory(u64),                                  // Accepted memory addressing bitmask
    Default(&'static Operand),                    // Default operand
    Force(&'static Register),                     // Forced/mandatory operand
    Judger(fn(opr: &[Operand], id: usize) -> bool), // Custom judger function (implement if necessary)
    Same(usize),                                  // Requires matching a specific element in the operand list
}

pub struct Qualifier {
    pub target: &'static [OperandType],           // Target operand type description required by this instruction variant
    pub modifier: u64,                            // Modification operation description required by this variant, defined by ISA
}

pub struct OperationDesc {
    pub name: &'static str,                       // Instruction name
    pub operands: &'static [u16],                 // Description of how operands are filled into the instruction template
    pub qualifiers: &'static [Qualifier],         // All instruction variants for the template
    pub operation: u64,                           // Instruction template base. (For VLIW, use an array for secondary referencing)
    pub support: &'static [u64],                  // Supported target systems description. Defined by ISA
    pub flag: u64,                                // Template flag bit. A value of -1 (u64::Max) means this is a macro instruction needing further processing.
}

The ArchDesc class provides encapsulation for the ISA. Documentation for this is to be added.

SyntaxManager might be refactored in the future. However, since the instruction matching and encoding processes are completely agnostic to the syntax handling process, this shouldn't cause major issues.

Adding File Support for SAS

Instruction to complete.

Support Status

ISA Support status

Due to time and testing equipment limitations, we have only conducted limited testing on the devices and cannot guarantee that SAS generates correct instructions. We welcome anyone to participate in testing SAS and provide feedback. Suggestions for improvements are especially appreciated. SAS has ported some test scripts from LLVM-MC. You can run them using cargo test.

AMD64: Does not support X87, MMX, or 3DNow!. AVX512 is not yet supported but is planned for future updates. Other instructions need further testing to determine usability.
AArch64: Does not support SVE/SME, but support is planned for future updates. Other instructions need further testing to determine usability.
RISC-V64: Needs further testing to determine usability.
LoongArch: Not yet adapted, but adaptation is planned for the next phase.

File Support status

ELF: Limited support for amd64,aarch64 and riscv64.

License

This project is licensed under the GNU GPLv3. We would be honored if this project could be accepted by GNU.

Notes

Sometimes, Rust is referenced as Genshin Impact in programming language.

You're right, But Rust is a compilation-time fighting game proudly presented by Mozilla.
In the world of Cargo -- where the referenced pointer will be granted the power of "lifetime" to guide object safety.
You will play a mysterious character named "Rustacean" and encounter all kinds of amazing tsundere bugs in the fight with "Rustc".
Conquer them, compile them, and gradually discover the truth behind the crash of the "C++" program.

Therefore, as a software designed in Rust language, SAS will use the characters in game Genshin Impact to name the version.

Version 1.0 will be codenamed "Amber".

About

An assembler written in Rust language.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages