Chapter 1: Getting to Know ARM64

1.1 What is ARM64 all about?

Imagine learning a new language, but instead of chatting with people, you're conversing with computers. This, in essence, is what ARM64 assembly is – it's how we communicate with computers that use ARM64 chips.

Now, you've surely heard of Intel chips, haven't you? Well, ARM64 is another type of chip that's gaining immense popularity these days. You'll find it in numerous smartphones, tablets, and even some laptops and desktop computers.

The brilliant thing about ARM64 is its capacity to perform a great deal of work without consuming much power. It's rather like having a sports car that's incredibly fast but doesn't guzzle petrol. That's precisely why it's so popular in mobile devices – your phone's battery lasts much longer!

When we write in ARM64 assembly, we're providing the computer with extremely specific, step-by-step instructions. It's akin to giving a detailed recipe to a cook, ensuring every step is clear and precise.

What is Assembly Language for ARM64?

ARM 64 Assembly Language is an assembler code used in programming 64-bit (AArch64) architecture Arm devices. It allows programmers to directly access the ISA (instruction set architecture) enabling them to write codes which can be executed directly by the computer system processor.

1.2 A Brief History

ARM has its roots in the early 1980s and was originally an abbreviation for Acorn RISC Machine (and later Advanced RISC Machine). The first ARM processor was made by Acorn Computers for use in personal computers. Just last year, in 2011, ARM Holdings announced a version of ARMv8 that incorporates the first ever 64-bit ARM architecture.

The move to 64-bit wasn’t merely about bigger numbers; there were several improvements:

  • Larger address space: This meant programs could now directly use more than 4GB of memory.

  • More registers: That’s giving programmers additional flexibility and might also be beneficial for performance reasons.

  • New instructions: Which include better support for cryptography and advanced mathematics.

Key points about ARM64 assembly:

  • Architecture: It is a member of the wider family of processors called ARM (Advanced RISC Machine), which is known for its design as a RISC (Reduced Instruction Set Computing) machine.

  • Instruction Set: It uses fixed-length 32-bit instruction encoding that makes it easier to decode instructions and design pipelines.

  • Register Set: There are 31 general-purpose registers each capable of holding a 64-bit word, and also one special register called zero register having a constant value as zero.

  • Memory Access: The handling system supports different addressing modes hence efficient memory operations can be performed using any mode chosen at our convenience.

  • SIMD and Floating-Point: For vectorized operations, it has advanced SIMD (Neon) along with floating-point instructions.

  • Exception Handling: Provides full exception handling mechanism.

1.3 Setting Up Your Computer for ARM64 Work

For this guide, we'll use a Linux AArch64 system. If you're using Kali Linux on an ARM64 device, you're likely already set up. However, we'll ensure you have all the necessary tools installed.

Here are the main tools we'll use:

  1. as: This turns our assembly code into object files.

  2. ld: This links our object files into executable programs.

  3. gdb: This powerful tool allows us to run programs step-by-step and inspect memory and registers.

  4. nano: A simple text editor for writing our assembly code. You can use any text editor you're comfortable with.

  5. gcc: While not directly used for assembly, it's part of the GNU Compiler Collection and can be helpful for comparison.

To verify if these tools are installed, open a terminal and type:

as --version
ld --version
gdb --version
nano --version
gcc --version

If any of these commands don't work, you can install them using:

sudo apt update
sudo apt install binutils gdb nano gcc

Note: binutils package includes both as and ld.

1.4 Your Very First ARM64 Program: Saying "Hello!"

What is an Assembly File (ARM64)?

An Assembly File in the context of ARM64 (a 64-bit architecture developed by ARM Holdings) is a text file containing assembly language code specifically written for the ARM64 architecture. ARM64 assembly files typically have a .s or .asm extension. Syntax of ARM Assembly

ARM assembly language has a specific syntax for writing instructions. Here is the basic structure:

  • Instruction: The operation to be performed (e.g., MOV, ADD, SUB).

  • Operands: The data to be operated on (e.g., registers or immediate values).

Example Syntax:

INSTRUCTION DESTINATION, OPERAND1, OPERAND2

Example Code:

MOV R0, #5      ; Move the value 5 into register R0
ADD R1, R0, #3  ; Add the value in R0 (5) with 3, store result in R1

Key Components of an ARM64 Assembly Program

  1. Sections:

    • .text: Contains the actual code

    • .data: Contains initialized data

    • .bss: Contains uninitialized data

  2. Labels: Used to mark specific locations in the code, often for jumping or branching.

  3. Instructions: The actual operations the CPU will perform.

  4. Directives: Special commands for the assembler, not actual CPU instructions.

  5. Comments: Lines starting with ';' or '//' are comments.

In ARM64, specific registers are used to pass arguments to the OS when making a system call. For example:

  • X0 to X7 are used for passing arguments.

  • X8 is used to specify the system call number.

ARM64 system call numbers and their corresponding symbolic names: https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#arm64-64_bit Now, let's write our first program:

  1. Open your text editor and create a new file called hello.s.

  2. Type in the following code:

.data
    message: .ascii "Hello World!\n"
    len = . - message

.text
.global _start

_start:
    // Write the message to stdout
    mov x0, #1
    ldr x1, =message
    mov x2, len
    mov x8, #64
    svc #0

    // Exit the program
    mov x0, #0
    mov x8, #93
    svc #0

Let's break this down:

  • .data: This section is where we put our data, like the message we want to print.

  • .text: This is where our actual code goes.

  • _start:: This is where our program begins.

  • mov, ldr: These are instructions that move data into registers.

  • svc: This is how we make a system call.

What's happening in this program?

  1. We're setting up a system call to write our message:

    • mov x0, #1: We're saying "write to the screen" (1 means standard output).

    • ldr x1, =message: We're telling it where our message is.

    • mov x2, len: We're saying how long our message is.

    • mov x8, #64: 64 is the system call number for "write".

  2. Then we're setting up a system call to exit our program:

    • mov x0, #0: We're returning 0 (which means "everything went okay").

    • mov x8, #93: 93 is the system call number for "exit".

  3. svc #0: This actually makes the system call happen.

To run this program:

  1. Open a terminal where you saved hello.s.

  2. Type these commands:

    as hello.s -o hello.o
    ld hello.o -o hello
    ./hello
  • Explnation:

    • as hello.s -o hello.o

      • Assemble the source file:

        • as is the GNU assembler command.

        • hello.s is the assembly source file containing the human-readable instructions.

        • -o hello.o specifies the output file name hello.o.

      • Result:

        • Converts the assembly code into machine code stored in hello.o.

        • This object file is not yet executable but contains the necessary machine instructions.

    • ld hello.o -o hello

      • Link the object file:

        • ld is the GNU linker command.

        • hello.o is the object file generated from the previous step.

        • -o hello specifies the output file name hello.

      • Result:

        • Combines the object file with any necessary libraries and resolves any references to create a final executable.

        • This step ensures that all dependencies and addresses are correctly set up for the program to run.

    • ./hello

      • Run the executable:

        • ./hello executes the newly created executable file hello.

        • The ./ prefix tells the shell to look for the executable in the current directory.

      • Result:

        • The program runs and prints "Hello World!" to the terminal.

        • This output comes from the machine code instructions in hello, which were originally written in the hello.s assembly file.

You should see Hello World! printed on your screen.

Hello World!

Last updated