diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/README.md | 1 | ||||
-rw-r--r-- | src/arch/armv7.md | 222 |
2 files changed, 223 insertions, 0 deletions
diff --git a/src/arch/README.md b/src/arch/README.md index b14cd98..088bbe7 100644 --- a/src/arch/README.md +++ b/src/arch/README.md @@ -2,3 +2,4 @@ - [x86_64](./x86_64.md) - [arm64](./arm64.md) +- [armv7](./armv7.md) diff --git a/src/arch/armv7.md b/src/arch/armv7.md new file mode 100644 index 0000000..5f4980e --- /dev/null +++ b/src/arch/armv7.md @@ -0,0 +1,222 @@ +# armv7a +keywords: arm, armv7, abi + +- ISA type: `RISC` +- Endianness: `little`, `big` + +## Registers +### General purpose registers +```markdown +bytes +[3:0] alt desc +--------------------------------------------- +r0-r12 general purpose registers +r11 fp +r13 sp stack pointer +r14 lr link register +r15 pc program counter +``` + +### Special registers +```markdown +bytes +[3:0] desc +--------------------------------------------- +cpsr current program status register +``` + +### CPSR register +```markdown +cpsr +bits desc +----------------------------- + [31] N negative flag + [30] Z zero flag + [29] C carry flag + [28] V overflow flag + [27] Q cummulative saturation (sticky) + [9] E load/store endianness + [8] A disable asynchronous aborts + [7] I disable IRQ + [6] F disable FIQ + [5] T indicate Thumb state +[4:0] M process mode (USR, FIQ, IRQ, SVC, ABT, UND, SYS) +``` + +## Instructions cheatsheet +### Accessing system registers +Reading from system registers: +```armasm +mrs r0, cpsr // move cpsr into r0 +``` + +Writing to system registers: +```armasm +msr cpsr, r0 // move r0 into cpsr +``` + +### Control Flow +```armasm +b <lable> // relative forward/back branch +bl <lable> // relative forward/back branch & link return addr in r14 (LR) + +// branch & exchange (can change between ARM & Thumb instruction set) +// bit Rm[0] == 0 -> ARM +// bit Rm[0] == 1 -> Thumb +bx <Rm> // absolute branch to address in register Rm +blx <Rm> // absolute branch to address in register Rm & + // link return addr in r14 (LR) +``` + +## Procedure Call Standard ARM ([`aapcs32`][aapcs32]) +### Passing arguments to functions +- integer/pointer arguments + ```markdown + reg arg + ----------- + r0 1 + .. .. + r3 4 + ``` +- a double word (64bit) is passed in two consecutive registers (eg `r1+r2`) +- additional arguments are passed on the stack. Arguments are pushed + `right-to-left (RTL)`, meaning next arguments are closer to current `sp`. + ```markdown + void take(..., int a5, int a6); + | | | ... | Hi + | +-->| a6 | | + +---------->| a5 | <-SP | + +-----+ v + | ... | Lo + ``` + +### Return values from functions +- integer/pointer return values + ```markdown + reg size + ----------------- + r0 32 bit + r0+r1 64 bit + ``` + +### Callee saved registers +- `r4` - `r11` +- `sp` + +### Stack +- full descending + - full: `sp` points to the last used location (valid item) + - descending: stack grows downwards +- `sp` must be 4byte aligned (word boundary) at all time +- `sp` must be 8byte aligned on public interface interfaces + +### Frame chain +- not strictly required by each platform +- linked list of stack-frames +- each frame links to the frame of its caller by a `frame record` + - a frame record is described as a `(FP,LR)` pair (2x32bit) +- `r11 (FP)` must point to the frame record of the current stack-frame + ```markdown + +------+ Hi + | 0 | frame0 | + +->| 0 | | + | | ... | | + | +------+ | + | | LR | frame1 | + +--| FP |<-+ | + | ... | | | + +------+ | | + | LR | | current | + r11 ->| FP |--+ frame v + | ... | Lo + ``` +- end of the frame chain is indicated by following frame record `(0,-)` +- location of the frame record in the stack frame is not specified +- `r11` is not updated before the new frame record is fully constructed + +### Function prologue & epilogue +- prologue + ```armasm + push {fp, lr} + mov fp, sp // FP points to frame record + ``` +- epilogue + ```armasm + pop {fp, pc} // pop LR directly into PC + ``` + +## ASM skeleton +Small assembler skeleton, ready to use with following properties: +- use raw Linux syscalls (`man 2 syscall` for ABI) +- no `C runtime (crt)` +- gnu assembler [`gas`][gas_doc] +```armasm +// file: greet.S + +#include <asm/unistd.h> // syscall NRs + + .arch armv7-a + + .section .text, "ax" + .balign 4 + + // Emit `arm` instructions, same as `.arm` directive. + .code 32 + .global _start +_start: + // Branch with link and exchange instruction set. + blx _do_greet + + mov r0, #0 // exit code + mov r7, #__NR_exit // exit(2) syscall + swi 0x0 + + // Emit `thumb` instructions, same as `.thumb` directive. + .code 16 + .thumb_func +_do_greet: + mov r0, #2 // fd + ldr r1, =greeting // buf + ldr r2, =greeting_len // &len + ldr r2, [r2] // len + mov r7, #__NR_write // write(2) syscall + swi 0x0 + + // Branch and exchange instruction set. + bx lr + + .balign 8 // align data on 8byte boundary + .section .rodata, "a" +greeting: + .asciz "Hi ASM-World!\n" +greeting_len: + .int .-greeting +``` +> man gcc: `file.S` assembler code that must be preprocessed. + +To cross-compile and run: +```bash +> arm-linux-gnueabi-gcc -o greet greet.S -nostartfiles -nostdlib \ + -Wl,--dynamic-linker=/usr/arm-linux-gnueabi/lib/ld-linux.so.3 \ + && qemu-arm ./greet +Hi ASM-World! +``` +> Cross-compiling on `Ubuntu 20.04 (x86_64)`, paths might differ on other +> distributions. Explicitly specifying the dynamic linker should not be +> required when compiling natively on arm. + +## References +- [Procedure Call Standard ARM][aapcs32] +- [ARMv7-A Programmer's Guide][armv7a_prog_guide] +- [ARMv7-A Architecture Reference Manual][armv7a_arm] +- [GNU Assembler][gas_doc] +- [GNU Assembler Directives][gas_directives] +- [GNU Assembler `ARM` dependent features][gas_arm] + + +[aapcs32]: https://github.com/ARM-software/abi-aa/blob/master/aapcs32/aapcs32.rst +[armv7a_prog_guide]: https://developer.arm.com/documentation/den0013/latest +[armv7a_arm]: https://developer.arm.com/documentation/ddi0406/latest +[gas_doc]: https://sourceware.org/binutils/docs/as +[gas_directives]: https://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops +[gas_arm]: https://sourceware.org/binutils/docs/as/ARM_002dDependent.html |