Skip to content

Releases: AsmXFoundation/AsmX-G3

v29.0.0-rev-1.0

05 Sep 02:29

Choose a tag to compare

🔥 `Publication of the AsmX G3 v29-rev1.0`

v28.0.0-rev-2.0

24 Aug 16:51

Choose a tag to compare

Changelog: rev 2.0

This release introduces a critical stability fix for the compiler and expands the supported amd64 instruction set. The revision is updated from 1.0 to 2.0 to reflect these significant improvements.


Bug Fixes

  • Compiler: Resolved a critical null reference error during instruction parsing.

    A recurring internal system error that caused an Unhandled Rejection has been fixed. This error occurred when the compiler's parser attempted to process instructions that have no operands.

    Symptom: The compiler would crash with the following error message, preventing the assembly of valid code that included operand-less instructions.

    ✘ Unhandled Rejection, Reason: Cannot read properties of undefined (reading 'type')
    

    Root Cause: The zcc_build_generic_instruction method directly accessed ast[0].type without first verifying that the ast[0] element existed. For instructions without operands, this ast[0] was undefined, leading to a TypeError and a compiler crash.

    Solution: The code has been patched to use optional chaining (?.). The condition is now ast[0]?.type, which safely checks for the existence of ast[0] and its type property before attempting to access it. This ensures that operand-less instructions are handled gracefully by the parser.

    Before:

      static zcc_build_generic_instruction(ast) {
        if (ast[0].type == TypeOfAtomicExpression.ARGUMENTS) { // Crashes if ast[0] is undefined
          return ast[0].body.values;
        }
        return ast;
      }

    After (Fix Implemented):

      static zcc_build_generic_instruction(ast) {
        if (ast[0]?.type && ast[0].type == TypeOfAtomicExpression.ARGUMENTS) { // Safely checks for existence
          return ast[0].body.values;
        }
        return ast;
      }

New Features

  • Instruction Set: Added support for common amd64 instructions without operands.

    To enhance low-level programming capabilities, the instruction set has been updated to include several fundamental amd64 instructions that do not take any operands.

    The following instructions are now fully supported:

    • nop: No Operation
    • fwait: Check pending unmasked floating-point exceptions
    • pushf: Push rFLAGS Register onto the Stack
    • popf: Pop Stack into rFLAGS Register
    • sahf: Store AH into Flags
    • lahf: Load Status Flags into AH Register

    Implementation: These instructions have been mapped within the compiler's instructionSet, allowing the assembler to correctly recognize and encode them.

Developer Impact

Developers can now write code utilizing these common, operand-less instructions without encountering a compiler crash. This fix removes a significant blocker and enables more flexible and direct low-level code generation.

v28.0.0-rev-1.0

23 Jul 06:30

Choose a tag to compare

AsmX G3: A New Generation of Assembly Programming

AsmX G3 marks a significant evolution from its predecessor, introducing a host of new features and architectural changes aimed at enhancing the development of high-performance applications. This update brings the ZGEN compiler for generating native ELF64 executables, an improved command-line interface, and a more robust compilation pipeline.

Key Enhancements in AsmX G3

Compilation and Architecture

AsmX G3 introduces a fundamental architectural shift, moving from a single-mode interpreter to a sophisticated dual-mode compilation system designed for both flexibility and high performance. This architecture is built upon two distinct pathways: the legacy JITC (Just-In-Time Compilation) mode and the new ZCC/ZGEN (Zero-latency Code Generation) mode. The JITC mode, inherited from G2, functions as a high-speed interpreter for scripts and rapid prototyping, processing a familiar Intel-style syntax. In contrast, the ZCC/ZGEN mode is a full-fledged Ahead-Of-Time (AOT) compiler that produces native, standalone 64-bit ELF executables specifically for the x86_64 architecture, utilizing an enhanced dialect of AT&T syntax.

The ZCC/ZGEN compilation pipeline is a modular and robust process orchestrated by several key components:

  1. Parser (parser.js): At the heart of the new architecture is the RecursiveDescentParser, which now operates in one of two modes: jcc (for JITC) or zcc (for ZGEN). This crucial separation ensures that each backend receives an Abstract Syntax Tree (AST) perfectly tailored to its needs. The zcc_parser generates a structured, detail-rich AST that contains all the necessary information for native code generation, avoiding the compromises of a one-size-fits-all approach.

  2. Compiler Driver (driver.js): Acting as the primary orchestrator for the x86_64 backend, the driver receives the zcc-optimized AST. It traverses the tree, identifies the type of each expression—such as a section (@section), a function declaration (@fn), or a machine instruction (@mov)—and dispatches tasks accordingly.

  3. Hardware Machine - HWM (hwm/main.cts): This component is a high-precision factory for machine code. It takes a single assembly mnemonic and its operands from the driver. By consulting a detailed instruction descriptor table (tbl), the HWM finds the precise binary representation for that instruction variant. Its core responsibilities include calculating and prepending necessary REX prefixes for 64-bit operations and extended registers, and encoding the complex ModR/M and SIB bytes required for advanced memory addressing. The output is a raw, binary Buffer containing the exact machine code for the instruction.

  4. Hardware Compiler - HWC (hwc/main.cts): The HWC is the final assembler and a built-in linker responsible for constructing the complete ELF64 file. It receives the instruction buffers from the HWM and performs the high-level tasks of structuring the executable. This includes creating standard ELF sections like .text (for code) and .rodata (for constants), managing symbol tables, and, critically, enabling dynamic linking by generating the Procedure Linkage Table (PLT) and Global Offset Table (GOT). This allows AsmX G3 programs to call external functions from shared libraries like libc. The HWC handles all necessary relocations, patching in the final addresses before writing the complete, executable file to disk.

  5. Assembly (assembly/assembly_main.ts): This is a specialized module for handling the strict structural and ABI (Application Binary Interface) requirements of specific code blocks. Its primary implementation, impl_assembly_fn_main, is an expert in constructing the main function. It automatically generates the standard function prologue (setting up the stack frame with %rbp) and epilogue. Most notably, it intelligently inspects the function body: if it is empty, the assembly component automatically injects a standard exit(0) syscall to prevent segmentation faults, ensuring that even the simplest program is safe and well-behaved by default.

Of course. Here is a more extensively detailed paragraph on the "New Features and Capabilities" of AsmX G3, meticulously incorporating information from all provided sources, including the diff file, the three markdown articles, and a specific focus on the often-overlooked enhancements to the JITC mode.

New Features and Capabilities

AsmX G3 represents a monumental leap in functionality, transforming the language from a high-speed interpreter into a comprehensive systems programming platform with a dual-mode compilation strategy. This evolution introduces a wealth of new capabilities focused on enhancing the developer experience, compiler intelligence, and direct hardware interaction, with significant improvements benefiting both the new ZGEN native compiler and the legacy JITC mode.

At the forefront of the developer experience is the introduction of a sophisticated Terminal Args Parser Interface (TAPI) (tapi.js). This entirely new component provides a robust and intuitive command-line interface that correctly parses a variety of argument styles, including single flags (-r), paired flags with values (-o my_app), and alias flags (-m for --march). Active development is underway to improve its flexibility further, such as correctly interpreting compound flags like --llvm-version as a single unit. This is complemented by a vastly improved diagnostics system. The compiler now generates intelligent, context-aware warnings and errors that pinpoint the exact location of an issue in the source code. On the roadmap are features standard in professional toolchains: a final summary count of all diagnostics (e.g., 4 Warnings, 0 Errors) and a -W flag to give developers granular control over which warnings are displayed. For performance analysis, the kernel (kernel.js) now integrates a profiling mechanism (__asmx_profile_stage_fn) which, when enabled with the --profiletime flag, precisely measures and reports the execution time of each compilation stage.

The flagship capability of G3 is the introduction of a full-featured native compilation pipeline with dynamic linking. The Hardware Compiler (HWC) component (hwc/main.cts) now functions as an integrated linker, capable of constructing complete, dynamically-linked ELF64 executables from scratch. When a program uses a directive like @include libc, the HWC automatically generates the necessary Procedure Linkage Table (PLT) and Global Offset Table (GOT) sections. This enables compiled AsmX G3 binaries to seamlessly call external functions from shared system libraries like libc.so.6. While the ultimate goal is a high-level, intuitive syntax such as @call libc::printf(...), the current experimental implementation requires the programmer to manually place function arguments into the correct registers according to the x86_64 ABI before issuing a @call printf instruction. This is a core part of the "Smart Compiler" philosophy, which is further demonstrated by the intelligent handling of the main function. The specialized assembly module (assembly/assembly_main.ts) will automatically inject a standard exit(0) syscall into an empty @fn pub main {} block, proactively preventing segmentation faults and ensuring that even the most minimal program is safe and correct by default. Data handling has also been expanded with the introduction of a functional .rodata section for constants and the in-progress development of a .data section for mutable global variables.

Crucially, the JITC mode has also received significant upgrades, inheriting many of the foundational improvements made for ZGEN. The entire hardware abstraction layer (hardware.js) has been rewritten, providing JITC with a more accurate and comprehensive simulation environment. This includes:

  • Expanded Register Support: JITC now recognizes and simulates a much wider array of registers, including the extended 64-bit general-purpose registers ($r8 to $r15), control registers ($cr0 to $cr15), debug registers ($dr0 to $dr15), and even the AVX-512 mask registers ($k0 to $k7).
  • More Accurate Register Behavior: The logic for register manipulation is now more precise. For example, writing a 32-bit value to $eax will correctly update the lower 32 bits of $rax while preserving the upper bits, and also modify the corresponding $ax, $ah, and $al registers, mirroring the behavior of a real CPU.
  • New Instructions: New instructions are being implemented for both backends simultaneously. The addition of the cpuid instruction (cpu-member.js), for instance, is available in both JITC and ZGEN, allowing programs in either mode to query processor features.
  • Clearer Mode Distinction: There is now a deliberate architectural separation of concerns. The @system instruction is designated as a JITC-specific, high-level feature, and its use in ZGEN mode will now trigger a compiler warning, guiding the developer to use the native @syscall instruction for direct OS interaction, thus improving code clarity and portability.

Collectively, these features—from the polished command-line interface and intelligent diagnostics to the powerful native compiler and a more faithful JITC simulation—elevate AsmX G3 from an experimental tool to a formidable platform for serious systems programming.

Of course. Here is an exceptionally detailed, book-like chapter on the "Kernel," drawing from every piece of provided information to paint a complete picture of its architectural evolution and new responsibilities in AsmX G3.


The Kernel: The Brain of the Operation

In the transition from AsmX G2 to G3, no single component has undergone a more profound transformation than the kernel (`ker...

Read more