Reputation: 4853
I was looking through some Android source and found the implementation of writev
to be entirely in assembly. I have a general working knowledge of ASM but am unfamiliar with the nuances of the ARM instruction set. Considering this code:
ENTRY(writev)
mov ip, r7
ldr r7, =__NR_writev
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(writev)
After some searching around I found the following:
__NR_writev = __NR_SYSCALL_BASE+146
__NR_SYSCALL_BASE = 0
What exactly is happening here? From what I could find, the ip
register is an alias for r12 and is further known as the scratch register. Nearly all of the ASM implementations I can find in the source have this general layout:
The code loads r7 into ip, r7 gets loaded with the actual memory address of the routine, then a software interrupt is issued. Although I do not know exactly what is happening, I can see that the remaining bit of code is checking for errors using the return values of the __NR_writev subroutine call.
Where is the actual implementation of writev if this ASM routine only redirects the call and checks for errors?
Why is r7 being saved here and why into ip(r12/scratch register)?
Why is the memory address of the actual implementation loaded into r7 prior to a SWI?
Upvotes: 3
Views: 1047
Reputation: 39581
The actual implementation of writev is somewhere in your operating system's kernel. The SWI instruction causes the CPU to switch to supervisor mode, and begin executing the kernel's exception handler. While in supervisor mode the kernel can do things that your user mode code can't do directly, like access devices.
The value of R7 is saved to IP (R12) because the calling convention being followed requires that the value of R7 be preserved across the call. It doesn't require that the IP register be saved.
The value loaded into R7 isn't an address, it's the number 146. Since other system calls also use SWI #0
, they all end up executing the the same exception handler in the kernel. The value in R7 is used determine which system call was invoked. The exception handler probably jumps to the system call's implementation in the kernel by using the value in R7 as a scaled offset into a table of addresses.
Upvotes: 3