All development is being done on a Linux based system (Debian), I am making use of scanf and printf to handle user input and output.
While the more correct way to load an address for a variable is:
adrp x0, variable
add x0, x0, :lo12:variable
I will be using:
ldr x0, =variable
// hello_world.s
.global main
.extern printf
.data
message:
.asciz "Hello World!\n"
.text
main:
// prolog // Used to store the current frame pointer and return addr before prog runs
stp x29, x30, [sp, -16]! // Store the frame pointer and the return addr to the stack
mov x29, sp // Load the frame pointer with the new stack pointer
// main code
ldr x0, =message // Load x0 with the address of the string
bl printf // Print the string
// cleanup
mov x0, #0 // Load x0 with an exit code. Zero for clean exit
ldp x29, x30, [sp], 16 // Restore the original frame pointer and return addr
RET // Return from our programme
This, very simple, application demonstrates the structure of the code as it will be demonstrated throughout this tutorial.
It also demonstrates some practices that will be required to ensure that running these apps does not clobber the OS as a whole.
The exact order of the code elements is not, generally, critical. Code in this tutorial will be laid out in the following way:
At the top of the code is:
// hello_world.s
This is a comment. Any text following a double forward slash is ignored by the assembler.
Below that are the following lines:
.global main
.extern printf
The .global main tells the assembler how to find the start of the application when it runs.
The .extern printf tells the assembler to include a link to the C printf function as it will be used in the code.
Below that are the following lines:
.data
message:
.asciz "Hello World!\n"
This section declares variables that will be used by the code. Memory is allocation on the heap for the variables.
In this case, a string of ascii values is stored. The base address of the string will be pointed to by the "message" variable.
Below that are the following lines.
.text
main:
// prolog // Used to store the current frame pointer and return addr before prog runs
stp x29, x30, [sp, -16]! // Store the frame pointer and the return addr to the stack
mov x29, sp // Load the frame pointer with the new stack pointer
// main code
ldr x0, =message // Load x0 with the address of the string
bl printf // Print the string
// cleanup
mov x0, #0 // Load x0 with an exit code. Zero for clean exit
ldp x29, x30, [sp], 16 // Restore the original frame pointer and return addr
RET // Return from our programme
The code is commented so no further commentary is required.