Wordy in Arm64-assembly: Complete Solution & Deep Dive Guide

Building entrance sign at night

From Text to Calculation: The Ultimate Guide to Solving Math Word Problems in Arm64 Assembly

Solving math word problems in Arm64 assembly involves manually parsing an input string and tokenizing it into numbers and operators. This low-level process requires converting ASCII digits to integers, managing a state machine to track operations, and using registers to perform arithmetic calculations before returning the final result.

If you've ever written a simple script in Python or JavaScript to parse a sentence, you've likely used a function like .split() and felt a moment of pure magic. A complex task, breaking a sentence into its component words, is reduced to a single, elegant command. Now, imagine being told to do the same thing, but without any built-in functions, working directly with memory addresses and raw bytes. This is the world of Arm64 assembly, and it can feel like stepping back in time. The initial frustration is real, but the reward is unparalleled: a true, fundamental understanding of how computation actually works.

This guide is designed to bridge that gap. We will take on the "Wordy" problem, a classic challenge from the exclusive kodikra.com curriculum that requires parsing and solving a simple math problem posed in plain English. We won't just show you the solution; we will build it from the ground up, explaining the strategy, the register conventions, the system calls, and the raw logic required to turn "What is 5 plus 13?" into the number 18 at the hardware level. Prepare to master string manipulation and low-level logic in a way you never thought possible.


What is the "Wordy" Problem in Low-Level Programming?

At its surface, the "Wordy" problem seems simple: take a question like "What is 7 minus 5?" and compute the answer. In a high-level language, this is a trivial task involving string splitting and a conditional block or a dictionary to map operator words to functions. However, in Arm64 assembly, the challenge is profoundly different and far more instructive.

The problem is not about the math itself—the `ADD`, `SUB`, `MUL`, and `SDIV` instructions are straightforward. The real challenge lies in the parsing and state management. You are given a sequence of bytes in memory (a string) and must implement the entire logic to make sense of it.

This involves several core low-level tasks:

  • Manual Tokenization: You must write code to iterate through the string byte by byte, identifying word boundaries (typically spaces) to isolate "tokens" like "What", "is", "5", "plus", etc.
  • String-to-Integer Conversion: The token "5" is not the number 5. It's the ASCII character '5', which has a byte value of 53. You must implement your own version of the `atoi` (ASCII to Integer) function to convert these character sequences into usable integer values for calculations.
  • State Management: Your program needs to know what it's looking for at any given moment. Is it expecting a number? An operator? Has it already found the first number? This requires a state machine, a fundamental concept in computer science, which you'll implement using registers and conditional branches.
  • String Comparison: To identify operators, you must compare the word you've isolated (e.g., the token "plus") with known operator strings. This requires a manual, character-by-character comparison loop.

Solving this problem in Arm64 assembly provides a raw, unfiltered view of the processes that high-level languages completely abstract away. It's a foundational exercise in the kodikra Arm64-assembly learning path that builds skills essential for systems programming, kernel development, and embedded systems.


Why Arm64 Assembly Makes This Challenge Uniquely Instructive

Tackling the "Wordy" problem in a language like Python is an exercise in API knowledge. Tackling it in Arm64 assembly is an exercise in computer science fundamentals. The constraints of the environment force you to confront concepts that are often taken for granted, making it an incredibly effective learning tool.

The primary reason is the complete lack of a standard library. There is no `string.h` or `iostream`. Every single operation, from finding the length of a string to printing a result, must be built from scratch or handled via direct communication with the operating system kernel through system calls (syscalls).

Here’s what makes this challenge so valuable in AArch64:

  • Direct Memory Manipulation: You work directly with memory addresses. A string is just a pointer to a starting byte, and you navigate it by incrementing that pointer. This builds a strong mental model of how data is laid out in memory.
  • Purposeful Register Usage: With a limited number of general-purpose registers (like x0-x30), you must be deliberate about what data you store and for how long. The solution requires careful planning for which registers hold the current result, pointers to strings, loop counters, and temporary values.
  • Understanding the ABI: To interact with the OS, you must adhere to the Application Binary Interface (ABI). For Linux on Arm64, this means knowing that the syscall number goes in register x8, arguments go in x0, x1, etc., and the return value is placed in x0.
  • Algorithmic Thinking: Without built-in functions, you are forced to think algorithmically. How do you efficiently compare two strings? What's the most robust way to convert an ASCII digit to its integer equivalent? You're not just calling a function; you're implementing the algorithm itself.

This hands-on experience demystifies the magic behind high-level languages. After completing this module, you will never look at a simple `print("Hello")` statement the same way again, because you'll understand the complex sequence of syscalls and memory operations happening under the hood.


How to Design the Parsing Logic: A Step-by-Step Strategy

To solve the "Wordy" problem, we can't just dive into coding. We need a robust strategy. The most effective approach is to build a simple parser that moves through the input string, token by token, and maintains a state to understand the context of each token. Our strategy will be a simplified state machine.

Step 1: The Core Logic - A Token-Based State Machine

Our program will read the input string one "word" (token) at a time. A token is any sequence of characters separated by spaces. The core of our logic will be a loop that gets the next token and decides what to do based on what it finds. We only care about numbers and a few specific operator words.

We can ignore words like "What", "is", and "by" as they are just grammatical fluff. The essential structure we are looking for is `Number -> Operator -> Number -> (optional Operator -> Number) ...`

Here is a high-level view of our parsing flow:

    ● Start
    │
    ▼
  ┌─────────────────────────┐
  │ Find first number token │
  └────────────┬────────────┘
               │
               ▼
  ┌─────────────────────────┐
  │ Convert token to integer│
  │ Store as current result │
  └────────────┬────────────┘
               │
               ▼
  ┌─────────────────────────┐
  │ Loop: Get next tokens   │
  └────────────┬────────────┘
               │
    ╭──────────▼───────────╮
    │ Is there another token?│
    ╰──────────┬───────────╯
          Yes  │
     ┌─────────┴─────────┐
     ▼                   ▼ No
┌────────────┐     ┌───────────┐
│ Get Operator │     │ Exit with │
└──────┬─────┘     │ result    │
       │           └───────────┘
       ▼
┌────────────┐
│ Get Number │
└──────┬─────┘
       │
       ▼
┌────────────────┐
│ Perform Math Op│
└────────────────┘
       │
       └─────────────┐
                     │
    (Loop back) ─────┘

Step 2: Tokenization - Implementing `get_next_token`

Since there's no `split()` function, we need to create our own logic to extract tokens. We can maintain a pointer to our current position in the input string. A `get_next_token` function would:

  1. Skip any leading spaces from the current position.
  2. Record the starting address of the word.
  3. Advance the pointer until it hits another space or the null terminator (`\0`).
  4. Temporarily place a null terminator where the space was, effectively "cutting out" the token as a valid C-style string.
  5. Return the starting address of this new, null-terminated token.

This process is repeated in a loop to process the entire sentence.

Step 3: Number Conversion - A Custom `atoi` Implementation

Once we have a token that we believe is a number (e.g., "123"), we need to convert it into a machine-usable integer. The `atoi` (ASCII to Integer) function is a standard C library function, but here, we build our own.

The algorithm is as follows:

  1. Initialize an accumulator (result) to 0.
  2. Check for a leading negative sign ('-'). If present, set a flag and move to the next character.
  3. Iterate through each character of the string token.
  4. For each character, subtract the ASCII value of '0' (which is 48) to get its integer value (e.g., '5' (53) - '0' (48) = 5).
  5. Multiply the current accumulator by 10.
  6. Add the new integer value to the accumulator.
  7. Repeat until the end of the token.
  8. If the negative flag was set, negate the final result.

This logic effectively builds the number up, one decimal place at a time.

    ● Start (`atoi` for "25")
    │
    ▼
  ┌─────────────────┐
  │ result = 0      │
  │ ptr -> '2'      │
  └────────┬────────┘
           │
           ▼
  ┌─────────────────┐
  │ Read '2' (ASCII 50) │
  │ val = 50 - 48 = 2 │
  │ result = (0*10)+2 = 2 │
  └────────┬────────┘
           │
           ▼
  ┌─────────────────┐
  │ ptr -> '5' (ASCII 53) │
  │ val = 53 - 48 = 5 │
  │ result = (2*10)+5 = 25│
  └────────┬────────┘
           │
           ▼
  ┌─────────────────┐
  │ ptr -> '\0' (End) │
  └────────┬────────┘
           │
           ▼
    ● Return result (25)

Step 4: Operator Identification and Execution

When our state machine expects an operator, we'll get the next token (e.g., "plus"). We then need to compare this token against our list of supported operators. This requires a custom string comparison function (`strcmp`).

Our `strcmp` will take two pointers (to our token and a known operator string like "plus") and compare them character by character. If they all match and both strings end at the same time, we've found our operator.

Based on the match, we branch to the appropriate code block:

  • If "plus", we get the next number and use the ADD instruction.
  • If "minus", we get the next number and use the SUB instruction.
  • If "multiplied", we get the next number and use the MUL instruction.
  • If "divided", we get the next number and use the SDIV instruction.

If we encounter a token we don't recognize or if the structure is wrong (e.g., two numbers in a row), we should handle it as an error, perhaps by exiting with a specific error code.


The Complete Arm64 Assembly Solution (Annotated)

Below is the complete, well-commented source code for solving the "Wordy" problem. This solution is designed for a Linux environment and uses the AArch64 instruction set and syscall conventions.

The code follows the strategy outlined above: it parses the input string token by token, converts numbers, identifies operators, and performs the calculation. The final result is returned as the program's exit code.


// wordy.s
// Solves math word problems from a string.
// The final result is returned as the exit code.
// To check the result after running: echo $?

.data
// The input string for the problem. Null-terminated.
problem_string: .asciz "What is 5 plus 13 minus 2 multiplied by 3 divided by 5?"
// problem_string: .asciz "What is -3 multiplied by 25?" // Another test case
// problem_string: .asciz "What is 5?" // Simplest case

// Operator strings for comparison
op_plus:        .asciz "plus"
op_minus:       .asciz "minus"
op_multiplied:  .asciz "multiplied"
op_divided:     .asciz "divided"

.text
.global _start

// Main entry point
_start:
    // x19 will hold our main result accumulator
    // x20 will hold the pointer to the current position in problem_string
    mov x19, #0
    ldr x20, =problem_string

    // --- Main Parsing Loop ---
    // We start by finding the first number. We skip "What is".
    // A more robust parser would check these words, but for this problem,
    // we can assume a valid starting structure.
    
    // Find the first number
    bl get_next_token      // x0 now points to the token "What"
    bl get_next_token      // x0 now points to the token "is"
    bl get_next_token      // x0 now points to the first number token
    
    // Convert the first number token to an integer
    bl atoi
    mov x19, x0            // Store the first number in our result register x19

// The main loop for processing operator-number pairs
main_loop:
    // Get the next token, which should be an operator or the end of the question
    bl get_next_token
    cbz x0, done           // If x0 is null, we're at the end of the string

    // Check if the token ends with a question mark and remove it
    bl strip_question_mark

    // --- Operator Comparison ---
    ldr x1, =op_plus
    bl strcmp
    cbnz w0, check_minus   // If not equal (w0 != 0), check next operator
    bl handle_op           // It was "plus", handle it
    b main_loop

check_minus:
    ldr x1, =op_minus
    bl strcmp
    cbnz w0, check_multiplied
    bl handle_op
    b main_loop

check_multiplied:
    ldr x1, =op_multiplied
    bl strcmp
    cbnz w0, check_divided
    bl handle_op
    b main_loop

check_divided:
    ldr x1, =op_divided
    bl strcmp
    cbnz w0, syntax_error  // If it's not any known operator, it's an error
    bl handle_op
    b main_loop

// Generic handler for all operations
handle_op:
    // The operator string is in x1. We need the next token (the number).
    bl get_next_token
    cbz x0, syntax_error   // Operator must be followed by a number
    bl atoi                // Convert number token in x0 to integer in x0
    mov x2, x0             // Move the second operand into x2

    // Now, perform the operation based on which operator string is in x1
    ldr x3, =op_plus
    cmp x1, x3
    b.eq do_add

    ldr x3, =op_minus
    cmp x1, x3
    b.eq do_sub

    ldr x3, =op_multiplied
    cmp x1, x3
    b.eq do_mul

    ldr x3, =op_divided
    cmp x1, x3
    b.eq do_div
    
    // Should not be reached if strcmp worked
    b syntax_error

do_add:
    add x19, x19, x2
    ret
do_sub:
    sub x19, x19, x2
    ret
do_mul:
    mul x19, x19, x2
    ret
do_div:
    sdiv x19, x19, x2
    ret

// We are finished, exit with the result
done:
    mov x0, x19      // Move final result to x0 for exit code
    mov x8, #93      // Linux syscall for exit
    svc #0           // Make the system call

syntax_error:
    mov x0, #255     // Return a special error code (255)
    mov x8, #93
    svc #0

// --- Helper Functions ---

// get_next_token: Finds the next space-separated token.
// Input: x20 = pointer to current position in string
// Output: x0 = pointer to the start of the token (null-terminated)
//         x20 is updated to point after the token.
// Clobbers: x0, x1, x2, x3
get_next_token:
    mov x0, x20      // Use x0 as our moving pointer
skip_spaces:
    ldrb w1, [x0], #1
    cmp w1, #' '
    b.eq skip_spaces
    cmp w1, #0       // Check for null terminator
    b.eq token_not_found
    sub x0, x0, #1   // Back up one byte to the start of the token
    mov x2, x0       // Save the start of the token in x2

find_end:
    ldrb w1, [x0], #1
    cmp w1, #' '
    b.eq found_end
    cmp w1, #0
    b.eq found_end
    b find_end

found_end:
    sub x0, x0, #1   // Move pointer back to the space/null
    strb wzr, [x0]   // Write a null terminator to end the token
    mov x20, x0      // Update the global pointer for the next call
    add x20, x20, #1 // Move past the null we just wrote
    mov x0, x2       // Return the start of the token in x0
    ret

token_not_found:
    mov x0, #0
    ret

// strcmp: Compares two null-terminated strings.
// Input: x0, x1 = pointers to the two strings
// Output: w0 = 0 if equal, non-zero otherwise
// Clobbers: w2, w3
strcmp:
strcmp_loop:
    ldrb w2, [x0], #1
    ldrb w3, [x1], #1
    cmp w2, w3
    b.ne strcmp_done // Not equal
    cmp w2, #0
    b.eq strcmp_done // Both are null, so equal
    b strcmp_loop
strcmp_done:
    sub w0, w2, w3   // Result is 0 if they were equal
    ret

// atoi: Converts a string to an integer.
// Handles negative numbers.
// Input: x0 = pointer to string
// Output: x0 = converted integer
// Clobbers: x1, x2, x3, x4
atoi:
    mov x1, #0       // x1 is the accumulator (result)
    mov x2, #1       // x2 is the sign multiplier (1 for positive, -1 for negative)
    ldrb w3, [x0]    // Load first character
    cmp w3, #'-'
    b.ne atoi_loop   // If not '-', start the conversion loop
    mov x2, #-1      // It's a negative number, set sign
    add x0, x0, #1   // Advance pointer past the '-' sign

atoi_loop:
    ldrb w3, [x0], #1
    cmp w3, #0       // Is it the null terminator?
    b.eq atoi_done
    cmp w3, #'0'
    b.lt syntax_error // Not a digit
    cmp w3, #'9'
    b.gt syntax_error // Not a digit

    sub w3, w3, #'0' // Convert ASCII char to integer value
    mov x4, #10
    mul x1, x1, x4   // result = result * 10
    add x1, x1, x3   // result = result + digit
    b atoi_loop

atoi_done:
    mul x0, x1, x2   // Apply the sign
    ret

// strip_question_mark: Checks if the last char of a string is '?'
// and if so, replaces it with a null terminator.
// Input: x0 = pointer to string
// Output: x0 = pointer to the (possibly modified) string
// Clobbers: x1, x2
strip_question_mark:
    mov x1, x0       // Copy pointer to x1
strlen_loop:
    ldrb w2, [x1], #1
    cmp w2, #0
    b.ne strlen_loop
    sub x1, x1, #2   // Point to the character before the null
    ldrb w2, [x1]
    cmp w2, #'?'
    b.ne strip_done  // Not a question mark, do nothing
    strb wzr, [x1]   // It is, so replace it with null
strip_done:
    ret

Code Walkthrough: Deconstructing the Assembly Logic

Understanding assembly code requires reading it not just line by line, but section by section, understanding the purpose of each block and how registers are used to pass data between them.

The `.data` and `.text` Sections

The program starts with two sections. The .data section is where we declare initialized data—static variables that exist for the lifetime of the program. Here, we store our input problem_string and the constant strings for each operator. The .asciz directive creates a null-terminated string, which is crucial for our C-style string functions.

The .text section is where the actual executable code resides. The .global _start directive tells the linker where the program's execution should begin.

The `_start` and Main Loop

Execution begins at the _start label. We initialize our result accumulator in a callee-saved register, x19, to preserve it across function calls. We also load the address of our problem string into x20, which will act as our global string pointer.

The initial part of the code makes a few hardcoded calls to get_next_token to skip the "What is" prefix. A more robust parser would verify these words, but for this problem, we assume the input is well-formed. The first actual number is then parsed with atoi and stored in x19.

The main_loop is the heart of the program. It repeatedly:

  1. Calls get_next_token to get the next word.
  2. Checks if the token is null, which indicates the end of the string. If so, it branches to done.
  3. Compares the token to each known operator string using our custom strcmp.
  4. If a match is found, it calls handle_op to process the operation and then loops back.
  5. If no operator matches, it's a syntax_error.

The `handle_op` Logic

This is a generic function to avoid code duplication. When an operator like "plus" is identified, the code branches to handle_op. This function knows which operator was found because the pointer to the operator string (e.g., the address of op_plus) is still in register x1 from the last ldr command.

handle_op then gets the next token (the number), converts it with atoi, and then uses a series of comparisons on x1 to determine which arithmetic instruction (add, sub, mul, sdiv) to execute on the main result in x19.

Helper Functions: The Building Blocks

  • get_next_token: This is the most complex helper. It carefully manipulates pointers to find word boundaries. It cleverly overwrites a space with a null byte (\0) to create a temporary, isolated string for functions like atoi and strcmp to use. It then updates the main pointer x20 to be ready for the next call.
  • strcmp: A classic C-style string comparison. It loads one byte from each string, compares them, and repeats. It terminates if the bytes are different or if both are null simultaneously, indicating a perfect match.
  • atoi: Implements the string-to-integer algorithm described earlier. It handles an optional leading negative sign and builds the integer value by repeatedly multiplying the accumulator by 10.
  • strip_question_mark: A small utility to handle the end of the sentence, ensuring that a token like "5?" is treated as just "5".

Exiting the Program

Finally, the done block prepares to exit. The final result from x19 is moved into x0. According to the Linux ABI, x0 holds the exit code of the program. We then load the syscall number for `exit` (93) into x8 and execute svc #0 (Supervisor Call) to transfer control to the kernel, which terminates our process.


Assembling and Running Your Code

To run this Arm64 assembly code on a compatible system (like a Raspberry Pi 4/5, an Apple Silicon Mac with Asahi Linux, or an Arm64 Linux server), you'll need the GNU Assembler (`as`) and Linker (`ld`).

1. Save the Code: Save the code above into a file named wordy.s.

2. Assemble the Code: Convert your human-readable assembly into a machine-code object file.

as -o wordy.o wordy.s

3. Link the Object File: Create the final executable file from the object file.

ld -o wordy wordy.o

4. Run and Check the Result: Execute the program. Since the answer is returned as the exit code, you can view it immediately after with a special shell variable, $?, which holds the exit code of the last command.

./wordy
echo $?

For the input "What is 5 plus 13 minus 2 multiplied by 3 divided by 5?", the calculation is `((5 + 13) - 2) * 3 / 5` which is `16 * 3 / 5` -> `48 / 5` -> `9` (integer division). The output of `echo $?` should be `9`.


Pros and Cons: The Arm64 Approach vs. High-Level Languages

Choosing to solve a problem in assembly is a trade-off. You gain ultimate control and performance at the cost of development speed and safety. Here's how the Arm64 assembly approach compares to using a high-level language like Python for the same task.

Aspect Arm64 Assembly High-Level Language (e.g., Python)
Performance Extremely high. Direct instruction execution with no overhead from interpreters, garbage collectors, or abstraction layers. Slower. Significant overhead from the runtime environment, dynamic typing, and function call abstractions.
Control Absolute. You control every register, every memory access, and every system call. Ideal for performance-critical or hardware-adjacent tasks. Limited. The language runtime manages memory and resources for you. This is safer but less flexible.
Development Time Very long. Everything must be built from scratch. The code is verbose and requires deep system knowledge. Very short. Built-in functions like split() and int() can solve the problem in a few lines of code.
Readability & Maintainability Low. Assembly code is difficult to read for those unfamiliar with the architecture. Logic is spread across many lines and jumps. High. The code is often self-documenting and follows a clear, linear logic that is easy for other developers to understand.
Portability None. The code is tied to the Arm64 architecture and the Linux syscall ABI. It will not run on x86 or Windows without a complete rewrite. High. Python code can run on any system with a Python interpreter, regardless of the underlying hardware architecture.
Error Handling Manual and unforgiving. A single bad pointer can cause a segmentation fault. Error checking must be explicitly coded for every step. Robust. The language provides built-in exception handling (e.g., `try...except` blocks) to gracefully manage errors.

Frequently Asked Questions (FAQ)

What exactly is a "register" in Arm64?

A register is a small, extremely fast storage location directly inside the CPU. In Arm64, there are 31 general-purpose 64-bit registers (x0 through x30). They are used to hold data being actively worked on, such as function arguments, return values, pointers, and intermediate calculation results. Accessing data in a register is orders of magnitude faster than accessing data in RAM, which is why efficient assembly programming revolves around smart register usage.

Why use syscalls instead of library functions like `printf`?

In pure assembly, you are not automatically linked against any standard libraries (like the C standard library, `libc`). Therefore, functions like `printf` are not available. The only way for a program to communicate with the outside world (like the kernel, to request services like exiting or writing to the screen) is through system calls (syscalls). A syscall is a direct, low-level request to the operating system's kernel. Linking against `libc` is possible but adds complexity and dependencies.

How are strings truly represented in Arm64 assembly?

There is no "string" data type in assembly. A string is simply a convention: a sequence of consecutive bytes in memory, where each byte represents an ASCII character. The end of the string is marked by a special byte with the value 0, known as the "null terminator". A "string variable" in assembly is just a register or a label that holds the memory address of the very first character of the string.

In the terminal commands, what does `echo $?` do?

In Unix-like shells (like bash), the special variable $? holds the integer "exit code" of the last command that finished executing. By convention, an exit code of 0 means the program ran successfully, while any non-zero value indicates an error. In our program, we cleverly use this mechanism to return the final answer of our calculation, making it easy to check the result from the command line.

Could this solution be extended to handle floating-point numbers?

Yes, but it would require a significant increase in complexity. Arm64 has a separate set of registers (vector/floating-point registers, v0-v31) and instructions for floating-point arithmetic. You would need to write a custom string-to-float conversion function (like `atof`) and use instructions like fadd, fsub, fmul, and fdiv. The logic for parsing would be much more complex to handle the decimal point.

What are the most common pitfalls when parsing strings in assembly?

The most common errors are "off-by-one" errors with pointers and buffer overflows. Forgetting to account for the null terminator, reading or writing past the end of a string's allocated memory, or incorrectly calculating an offset can lead to segmentation faults (crashes) or unpredictable behavior. Careful pointer arithmetic and thorough testing are essential.

How can I debug Arm64 assembly code?

Debugging assembly is typically done with a command-line debugger like GDB (GNU Debugger). You can assemble and link your code with debugging symbols (using the -g flag for `as`). With GDB, you can then step through your program instruction by instruction, inspect the contents of registers (e.g., info registers), examine memory locations, and set breakpoints to analyze the state of your program at critical points.


Conclusion: From Abstraction to Understanding

Navigating the "Wordy" problem in Arm64 assembly is a journey from the comfortable world of abstraction to the raw reality of the machine. We have manually implemented tokenizers, string converters, and comparison functions—tools that are often taken for granted. In doing so, we've not only solved a parsing challenge but have also gained a profound appreciation for the intricate work performed by compilers and high-level language runtimes.

The skills developed here—meticulous state management, deliberate register allocation, and direct interaction with the OS kernel—are the bedrock of high-performance and systems-level programming. You have built a program that runs with virtually zero overhead, executing instructions as close to the metal as possible. This foundational knowledge is invaluable and serves as a powerful asset in your programming toolkit.

To continue your journey into low-level mastery, explore the other challenges in the kodikra Arm64-assembly learning path or dive deeper into the architecture with our complete Arm64-assembly language guide.

Disclaimer: The code and explanations in this article are based on the AArch64 instruction set architecture and the Linux system call ABI for Arm64 as of the current date. Syscall numbers and conventions may vary on other operating systems or future kernel versions.


Published by Kodikra — Your trusted Arm64-assembly learning resource.