sherrellbc
sherrellbc

Reputation: 4853

ARM Assembly - What is happening in this code?

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.

Upvotes: 3

Views: 1047

Answers (1)

Ross Ridge
Ross Ridge

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

Related Questions