In the Zig Language Reference, the
Assembly section includes some demos targetting the
x86_64
architecture for Linux. Here's the same code adapted for aarch64
(AKA arm64
) for macOS (Apple
Silicon M1 minimum):
Here's the file inline_assembly.zig
:
pub fn main() noreturn {
const msg = "hello world\n";
_ = syscall3(SYS_write, STDOUT_FILENO, @intFromPtr(msg), msg.len);
_ = syscall1(SYS_exit, 0);
unreachable;
}
pub const SYS_write = 4; // write = #4 on macOS
pub const SYS_exit = 1;
pub const STDOUT_FILENO = 1;
pub fn syscall1(number: usize, arg1: usize) usize {
return asm volatile ("svc #0x80"
: [ret] "={x0}" (-> usize),
: [number] "{x16}" (number),
[arg1] "{x0}" (arg1),
: .{ .x0 = true, .x5 = true });
}
pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
return asm volatile ("svc #0x80"
: [ret] "={x0}" (-> usize),
: [number] "{x16}" (number),
[arg1] "{x0}" (arg1),
[arg2] "{x1}" (arg2),
[arg3] "{x2}" (arg3),
: .{ .x0 = true, .x5 = true });
}
zig build-exe inline_assembly.zig -target aarch64-macos
Here's the file test_global_assembly.zig
:
// don't forget to prepend an underscore to the function name
comptime {
asm (
\\.global _my_func
\\_my_func:
\\ add x0, x0, x1
\\ ret
);
}
extern fn my_func(a: i32, b: i32) i32;
test "global assembly" {
try @import("std").testing.expect(my_func(12, 34) == 46);
}
zig test test_global_assembly.zig -target aarch64-macos -fllvm