Lecture 12: 22 October 2024

  1. Interactive assembly writing
  2. simplest C program – examine with objdump, nolibc
  3. corresponding assembly program
  4. hello world from bootstraps
  5. What is this “syscall” or “svc” instruction?

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: