Last active
May 15, 2024 21:23
-
-
Save heybdj/7de51b41f514381b18033fac4253d585 to your computer and use it in GitHub Desktop.
Computer Enhance Part 3.8 Homework -- Linking Directly to ASM (on macOS/arm64)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @NOTE(BDJ): Resources: | |
// - ARM ABI: https://github.com/ARM-software/abi-aa (see "Procedure Call Standard for the Arm 64-bit Architecture") | |
// - Apple's ARM64 ABI: https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms | |
// - ARM instruction reference: https://developer.arm.com/documentation/dui0802/b/A64-General-Instructions | |
// - clang/GNU assembler syntax reference: https://developer.arm.com/documentation/100068/0622/Migrating-from-armasm-to-the-armclang-Integrated-Assembler/Overview-of-differences-between-armasm-and-GNU-syntax-assembly-code | |
// | |
// There are a few minor assembler syntax differences compared to NASM: | |
// | |
// - all label names have to be unique--including loop labels | |
// - no leading `.` in front of labels | |
// - `global` -> `.global` | |
// - `section .text` -> `.text` | |
// - the end of an assembly file is marked with `.end` | |
// - conventionally ARM assembly files have a `.s` file extension | |
// | |
// To satisfy Apple's ARM64 toolchain and ABI, we also need to: | |
// | |
// - prepend global symbol names with an underscore | |
// - align the first instruction in a function to an 8-byte boundary (using `.balign`) | |
.global _MOVAllBytesASM | |
.global _NOPAllBytesASM | |
.global _CMPAllBytesASM | |
.global _DECAllBytesASM | |
.text | |
// @NOTE(BDJ): On ARM64, the first 8 parameters to a function are passed | |
// in registers x0-x7. x9-x15 are available as temporary registers. So-- | |
// | |
// x0 holds the count | |
// x1 holds the base data pointer | |
.balign 8 | |
_MOVAllBytesASM: | |
eor x9, x9, x9 | |
loop_mov: | |
strb w9, [x1, x9] | |
add x9, x9, #1 | |
cmp x9, x0 | |
b.lo loop_mov | |
ret | |
// @NOTE(BDJ): There is no variable-length `nop` instruction in ARM64. But there are SOME variable-length instructions! | |
.balign 8 | |
_NOPAllBytesASM: | |
eor x9, x9, x9 | |
loop_nop: | |
nop | |
add x9, x9, #1 | |
cmp x9, x0 | |
b.lo loop_nop | |
ret | |
.balign 8 | |
_CMPAllBytesASM: | |
eor x9, x9, x9 | |
loop_cmp: | |
add x9, x9, #1 | |
cmp x9, x0 | |
b.lo loop_cmp | |
ret | |
.balign 8 | |
_DECAllBytesASM: | |
loop_sub: | |
sub x0, x0, #1 | |
cbnz x0, loop_sub | |
ret | |
.end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @NOTE(BDJ): Build steps: | |
// - Assemble: clang -arch arm64 -g -o arm64_assembly.o -c arm64_assembly.s | |
// - Archive: ar rcs libarm64_assembly.a arm64_assembly.o | |
// - Compile+Link: clang -L. -larm64_assembly test.c -o test | |
// | |
// Debug with Xcode or lldb as usual. In Xcode, be sure to check the menu option | |
// Debug >> Debug Workflow >> "Always Show Disassembly". Hold down the Control key | |
// when debugging to step by assembly instruction. | |
typedef int s32; | |
typedef unsigned char u8; | |
typedef unsigned long long u64; | |
extern void MOVAllBytesASM( u64 count, u8 *data ); | |
extern void NOPAllBytesASM( u64 count ); | |
extern void CMPAllBytesASM( u64 count ); | |
extern void DECAllBytesASM( u64 count ); | |
s32 main (s32 argument_count, char const* arguments[]) { | |
u8 buffer[ 1 << 16 ] = {0}; | |
MOVAllBytesASM( sizeof(buffer), buffer ); | |
NOPAllBytesASM( sizeof(buffer) ); | |
CMPAllBytesASM( sizeof(buffer) ); | |
DECAllBytesASM( sizeof(buffer) ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There are numerical local labels. You jump to them providing direction
f
- for forward,b
- for backward. You can have multiple of them in one file and they'd better be used in macro.https://developer.arm.com/documentation/100068/0618/Migrating-from-armasm-to-the-armclang-Integrated-Assembler/Numeric-local-labels?lang=en