division program:
``c int main(int argc, char **argv) { int x = argc / (argc - 1);
return x; } ```
aarc64 barebones example:
.global _start
_start:
mov x8, #0x5e // #94 -- exit_group, could be #0x5d (93) -- exit
mov x0, #55
svc #0x0 // exit(55);
Doing the same thing in C:
#define my_syscall1(num, arg1) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
\
__asm__ volatile ( \
"svc #0\n" \
: "=r"(_arg1) \
: "r"(_arg1), \
"r"(_num) \
: "memory", "cc" \
); \
_arg1; \
})
#define exit(ret) my_syscall1(94, ret)
int main() { return 13; }
void _start() { exit(main()); }
Even more nice assembly: we import the kernel tools’ nolibc start from below
#define my_syscall1(num, arg1) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
\
__asm__ volatile ( \
"svc #0\n" \
: "=r"(_arg1) \
: "r"(_arg1), \
"r"(_num) \
: "memory", "cc" \
); \
_arg1; \
})
#define exit(ret) my_syscall1(94, ret)
void __attribute__((weak, noreturn, __no_stack_protector__, optimize("Os", "omit-frame-pointer"))) _start(void)
{
__asm__ volatile (
"and sp, x0, -16\n" /* sp must be 16-byte aligned in the callee */
"bl main\n" /* transfer to main */
);
__builtin_unreachable(); // assert we can't get here
}
int main(void) { exit(13); }
Useful links: