3

I am messing around with my new raspberry pi and I am fairly new to assembly. I have scoured Google and SO for a solution to this, and this was the closest I got to having a running program.

main.s (comments are from explanations I've found on the internet)

.section .text
.global _start

_start:
    mov x0, #0 // return value 0 for success
    mov x7, #1 // 1 is exit in the vector table
    svc 0      // execute the system call to exit the program

I then assemble with as main.s -o main.o and link with ld main.o -o main. Running with ./main outputs "Illegal instruction (core dumped)".

It's a Raspberry Pi Model B running ARM Arch Linux on a 64-bit quad-core ARM Cortex-A53.

Goal: Have an ARM assembly program compiled and linked with only as and ld that will exit successfully

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
ibstevieb123
  • 96
  • 10
  • Try adding this to the top `.section .text` – user8908459 Feb 22 '18 at 01:21
  • @user8908459 same result :( – ibstevieb123 Feb 22 '18 at 01:47
  • Got a chance to look at this closer. You are moving the value 0 to memory address 0. You can't just write to arbitrary memory locations. The program is failing because it is trying to write to a memory region that it does not own. Try moving it to a valid register instead. `mov r1, #0` – user8908459 Feb 22 '18 at 03:34
  • 1
    Use `strace ./main` to trace system calls. Perhaps it faults after `svc 0` returns with failure instead of exiting (so execution falls into whatever's next). But IDK the AArch64 system-call ABI so IDK if `svc 0` is even the right instruction. I think it is for 32-bit ARM. – Peter Cordes Feb 22 '18 at 05:02
  • 1
    @PeterCordes you just saved the day. I read `man syscall`. Turns out on arm64, it's x8 that you put the argument in, and I was doing random googling and found this random github which had, under "exit" the number 93. I'll put the solution in the question for future suckers. Again, thank you for your wisdom. – ibstevieb123 Feb 22 '18 at 05:47
  • Post the answer *as an answer*, and roll back your edit to the question. That's how we do things on Stack Overflow. There's an "answer my own question" button for a reason. – Peter Cordes Feb 22 '18 at 13:41

3 Answers3

2

In the man page for syscall, it states that the arm64 architecture calling convention for syscalls is: "argument: x8" and "instruction: svc #0". On this github project, the syscall argument for 'exit' is defined as '93'. Therefore, this is a working, exiting, and succeeding arm program compiled using only as and ld...

.section .text
.global _start

_start:
    mov x0, #0  // exit with status 0
    mov x8, #93 // svc argument goes in x8, and the argument for 'exit' is 93
    svc #0      // executes a syscall in arm64

Another answer on SO with useful info on system calls

ibstevieb123
  • 96
  • 10
  • 1
    `x0` is also the first arg to a system call. Right now you're making a `sys_exit(x0)` system call with x0 set to whatever value it has at the beginning of `_start`. Linux (the kernel) zeros registers before starting a fresh process, but if you dynamically linked your process the dynamic linker might leave it non-zero. – Peter Cordes Feb 22 '18 at 15:59
  • @PeterCordes you are super right, I have changed it – ibstevieb123 Feb 22 '18 at 17:21
0

You are moving the value 0 to memory address 0. You can't just write to arbitrary memory locations. The program is failing because it is trying to write to a memory region that it does not own. Try moving it to a valid register instead.

There are also plenty of good tutorials:

https://azeria-labs.com/writing-arm-assembly-part-1/

http://www.peter-cockerell.net/aalp/html/frames.html

https://www.coranac.com/tonc/text/asm.htm

And videos:

https://www.youtube.com/watch?v=Sm6v9UyhCkA

user8908459
  • 537
  • 5
  • 24
  • I changed it to x0 because every time I used r0, `as` would give me `Error: operand 1 must be an integer register -- \`mov r1,#0\``. I'm sure that has something to do with the problem. Would that be like an `as` configuration issue, or am I missing something with Arch Linux? – ibstevieb123 Feb 22 '18 at 04:25
  • When using gdb, it gets to the svc line and says "0x0000000000400084 in ?? ()" and the "Cannot find bounds of current function" – ibstevieb123 Feb 22 '18 at 04:31
  • 1
    @ibstevieb123: AArch64 doesn't have an `r1` register. 32-bit registers are named like `w1`, and 64-bit registers are named like `x1`. This answer is wrong. I don't see a store to memory in those instructions. – Peter Cordes Feb 22 '18 at 05:00
  • @ibstevieb123: Use `layout reg` in GDB to get a disassembly window that disassembles around the current instruction pointer. – Peter Cordes Feb 22 '18 at 05:04
  • 1
    @PeterCordes Whoa! I didn't know that was a thing. I did it and it looks like when it does the `svc` instruction, it outputs "0x0400084 in ?? ()" and then it just moves right past it to a (junk) instruction which produces "Cannot find bounds of current function". I suppose it would then just keep doing that until it went out of the bounds of the program causing a processor exception which produced the "Illegal instruction (core dumped)". Wow. Thank you so much for showing me that. – ibstevieb123 Feb 22 '18 at 05:22
0
.section .text
.global _start

_start:
    //mov r0, #0 // ARM 32-bit version
    mov x0, #0   // ARM 64-bit version
    //mov r7, #1 // ARM 32-bit version of this (Raspbian)
    mov x8, #93  // ARM 64-bit version of this (Ubuntu 64-bit, Arch64)
    svc 0        // execute the system call to exit the program