What's Really Going on With b.ne?
20: 54ffff21 b.ne 4 <again> // b.any
This is an ARM64 conditional branch instruction. The encoding 54xxxxxx is the format for conditional branches.
The 19-bit signal immediate offset is part of the instruction, not an absolute address.
b.ne 4 means if the condition is met, branch to PC + 4 bytes
So, it's just that the disassembler reports the offset in decimal or hex with sign-extension.
How Does the Linker Know How to Fix Branches?
When assembling (as), branches to local lanes (again) are resolved within the same file. The assembler sees both the label and the brach, it emits a relocation if needed. So, the linker literally rewrites instruction bytes to fix up relative addresses (branches), symbol references, etc.
What if You Link Multiple Object Files?
If msg or again is in another object file:
The assembler can't resolve it.
A relocation record is created.
The linker, during ld or ld -r or during final linking, patches the actual address or offset.
For branches, it patches the offset field in the instruction word.