mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
Previously had wonky line pointer in asm_main. New interface simpler and more portable. Add tests for ASSERT_EQ_ and family in arm and aarch64, previously on x86_64. ASSERT_EQ_ and family in ARM can now either take =123, =addr or var, before this the = was added on macros so var was not possible. Define the main function directly in assembly, the C driver was useless.
70 lines
2.0 KiB
ArmAsm
70 lines
2.0 KiB
ArmAsm
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
|
|
|
#include <lkmc.h>
|
|
|
|
LKMC_PROLOGUE
|
|
|
|
/* 13 general purpose registers. */
|
|
mov r0, 0
|
|
mov r1, 1
|
|
mov r2, 2
|
|
mov r3, 3
|
|
mov r4, 4
|
|
mov r5, 5
|
|
mov r6, 6
|
|
mov r7, 7
|
|
mov r8, 8
|
|
mov r9, 9
|
|
mov r10, 10
|
|
mov r11, 11
|
|
mov r12, 12
|
|
|
|
/* * r11: aliased to FP (frame pointer, debug stack trace usage only)
|
|
* +
|
|
* I think FP is only a convention with no instruction impact, but TODO:
|
|
* not mentioned on AAPCS. aarch64 AAPCS mentions it though.
|
|
* * r13: aliased to SP (stack pointer), what push / pop use
|
|
* * r14: aliased to LR (link register), what bl writes the return address to
|
|
* * r15: aliased to PC (program counter), contains the current instruction address
|
|
*
|
|
* In ARMv8, SP and PC have dedicated registers in addition to
|
|
* the 32-general purpose ones. LR is still general purpose as before.
|
|
*
|
|
* Therefore, it is possible to use those registers in any place
|
|
* other registers may be used.
|
|
*
|
|
* This is not possible in ARMv8 anymore.
|
|
*
|
|
* For example, we can load an address into PC, which is very similar to what B / BX does:
|
|
* https://stackoverflow.com/questions/32304646/arm-assembly-branch-to-address-inside-register-or-memory/54145818#54145818
|
|
*/
|
|
ldr pc, =10f
|
|
LKMC_ASSERT_FAIL
|
|
10:
|
|
|
|
/* Same with r15, which is the same as pc. */
|
|
ldr r15, =10f
|
|
LKMC_ASSERT_FAIL
|
|
10:
|
|
|
|
/* Another example with mov reading from pc. */
|
|
pc_addr:
|
|
mov r0, pc
|
|
/* Why sub 8:
|
|
* https://stackoverflow.com/questions/24091566/why-does-the-arm-pc-register-point-to-the-instruction-after-the-next-one-to-be-e
|
|
*/
|
|
sub r0, r0, 8
|
|
|
|
/* pc-relative load also just work just like any other register. */
|
|
ldr r0, [pc]
|
|
b 1f
|
|
.word 0x12345678
|
|
1:
|
|
LKMC_ASSERT_EQ(r0, =0x12345678)
|
|
|
|
/* We can also use fp in GNU GAS assembly. */
|
|
mov r11, 0
|
|
mov fp, 1
|
|
LKMC_ASSERT_EQ(r11, =1)
|
|
LKMC_EPILOGUE
|