diff --git a/more/apple_silicon/apple-linux-convergence.S b/more/apple_silicon/apple-linux-convergence.S new file mode 100644 index 0000000..3661e80 --- /dev/null +++ b/more/apple_silicon/apple-linux-convergence.S @@ -0,0 +1,110 @@ +// Macros to permit the "same" assembly language to build on ARM64 +// Linux systems as well as Apple Silicon systems. +// +// Perry Kivolowitz +// A Gentle Introduction to Assembly Language + +#if defined(__APPLE__) + +// Apple makes a distinction between loading something close by +// versus something global. Note the use of GOTPAGE rather then +// PAGE. +// +// Note: this macro dereferences the label getting what is at +// the label's address. + +.macro GLD_PTR xreg, label // Dereference a global * + adrp \xreg, _\label@GOTPAGE + ldr \xreg, [\xreg, _\label@GOTPAGEOFF] +.endm + +.macro GLD_ADDR xreg, label // Get a global address + adrp \xreg, _\label@GOTPAGE + add \xreg, \xreg, _\label@GOTPAGEOFF +.endm + +// This macro loads the address of a nearby label. + +.macro LLD_ADDR xreg, label // Load a local address + adrp \xreg, \label@PAGE + add \xreg, \xreg, \label@PAGEOFF +.endm + +.macro GLABEL label + .global _\label +.endm + +.macro MAIN +_main: +.endm + +.macro CRT label + bl _\label +.endm + +#else // LINUX + +.macro GLABEL label + .global \label +.endm + +.macro MAIN +main: +.endm + +.macro CRT label + bl \label +.endm + +// This macro treats label as a pointer and dereferences it. +// That is, it puts into the xreg what is found at the address +// of the label. + +.macro GLD_PTR xreg, label // Dereference a global * + ldr \xreg, =\label + ldr \xreg, [\xreg] +.endm + +// This macro loads the address of a nearby label. + +.macro LLD_ADDR xreg, label + ldr \xreg, =\label +.endm + + +.macro LD_ADDR xreg, label +.endm + +#endif + +.macro START_PROC // after starting label + .cfi_startproc +.endm + +.macro END_PROC // after the return + .cfi_endproc +.endm + +.macro PUSH_P a, b + stp \a, \b, [sp, -16]! +.endm + +.macro PUSH_R a + str \a, [sp, -16]! +.endm + +.macro POP_P a, b + ldp \a, \b, [sp], 16 +.endm + +.macro POP_R a + ldr \a, [sp], 16 +.endm + +.macro MIN src_a, src_b, dest + csel \dest, \src_a, \src_b, GT +.endm + +.macro MAX src_a, src_b, dest + csel \dest, \src_a, \src_b, LT +.endm diff --git a/more/apple_silicon/stub.S b/more/apple_silicon/stub.S index e239e81..e6c7e42 100644 --- a/more/apple_silicon/stub.S +++ b/more/apple_silicon/stub.S @@ -1,40 +1,45 @@ -#include "macros.S" +#include "apple-linux-convergence.S" +/* This is a short demonstration of the macro suite in development + to enable writing AARCH64 assembly language once and be able to + build on both Apple Silicon and Linux machines. + + Documentation can be found at: + https://github.com/pkivolowitz/asm_book + + Perry Kivolowitz +*/ .align 2 .text GLABEL main -// adrp loads an address using a page number containing the variable - - MAIN START_PROC - stp x21, x30, [sp, -16]! - str x29, [sp, -16]! - mov x29, sp + PUSH_P x21, x30 + PUSH_R x29 + mov x29, sp - mov x0, 8 // allocating a long - CRT malloc // call malloc() - mov x1, 0xFF // load payload - str x1, [x0] // store payload - LD_ADDR x1, ptr - str x0, [x1] + mov x0, 8 // allocating a long's worth of RAM + CRT malloc // call malloc() + mov x1, 0xFF // load payload + str x1, [x0] // store payload + LLD_ADDR x1, ptr // local load address + str x0, [x1] - LD_ADDR x0, fmt // loads the address of fmt - LD_ADDR x1, ptr // loads **ptr - ldr x1, [x1] // dereferences **ptr to make *ptr - ldr x2, [x1] // dereferences *ptr to get value + LLD_ADDR x0, fmt // loads the address of fmt + LLD_ADDR x1, ptr // loads **ptr + ldr x1, [x1] // dereferences **ptr to make *ptr + ldr x2, [x1] // dereferences *ptr to get value #if defined(__APPLE__) - stp x1, x2, [sp, -16]! - CRT printf - add sp, sp, 16 + PUSH_P x1, x2 + CRT printf + add sp, sp, 16 #else - CRT printf + CRT printf #endif - - mov x0, xzr - ldr x29, [sp], 16 - ldp x21, x30, [sp], 16 + POP_R x29 + POP_P x21, x30 + mov x0, xzr ret END_PROC