ASM language tips
Table of Contents
Position-independent Call
下面这个片段很有意思,利用ldr指令来调整pc指针位置,来曲线实现PIE
https://github.com/OP-TEE/optee_os/tree/1c832d7c41cdb2f617bffa74c3d70f7c4a5667fc/core/arch/arm/kernel/generic_entry_a64.S#L28
.macro readjust_pc
#ifdef CFG_CORE_ASLR
ldr x16, =1111f
br x16
1111:
#endif
.endm
LOCAL_FUNC vector_std_smc_entry , : , .identity_map
readjust_pc
bl thread_handle_std_smc
/*
* Normally thread_handle_std_smc() should return via
* thread_exit(), thread_rpc(), but if thread_handle_std_smc()
* hasn't switched stack (error detected) it will do a normal "C"
* return.
*/
mov w1, w0
ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE
smc #0
b . /* SMC should not return */
END_FUNC vector_std_smc_entry
inline asm
下面就是内联汇编的原型定义了,共由4部份组成,见如下
asm ( assembler template
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
);
assembler template
这个部份用来写汇编代码的模板, 编写的模板会用来给汇编器生成最终的代码
output operands
输出参数列表
input operands
输入参数列表
list of clobbered registers
在汇编代码中使用到的临时寄存器需要在此处列出来, 用来告诉C编译器汇编代码中会使用到列表中的寄存器。
inline asm example
#include <stdint.h>
void smc_writel(uint32_t reg, uint32_t value)
{
register unsigned long reg0 asm("r0") = 0x82000009;
register unsigned long reg1 asm("r1") = 1;
register unsigned long reg2 asm("r2") = reg;
register unsigned long reg3 asm("r3") = value;
asm volatile("smc #0\n\t" :"+r" (reg0), "+r" (reg1), "+r" (reg2), "+r" (reg3));
}
int main(int argc, char *argv[])
{
smc_writel(0x40000000, 0x1);
return 0;
}
Dump of assembler code for function smc_writel:
./test.c:
4 {
5 register unsigned long reg0 asm("r0") = 0x82000009;
0x000000000040056c <+0>: e2 03 00 2a mov w2, w0
0x0000000000400570 <+4>: 20 01 80 d2 mov x0, #0x9 // #9
4 {
0x0000000000400574 <+8>: e3 03 01 2a mov w3, w1
5 register unsigned long reg0 asm("r0") = 0x82000009;
0x0000000000400578 <+12>: 00 40 b0 f2 movk x0, #0x8200, lsl #16
6 register unsigned long reg1 asm("r1") = 1;
0x000000000040057c <+16>: 21 00 80 d2 mov x1, #0x1 // #1
7 register unsigned long reg2 asm("r2") = reg;
8 register unsigned long reg3 asm("r3") = value;
9 asm volatile("smc #0\n\t" :"+r" (reg0), "+r" (reg1), "+r" (reg2), "+r" (reg3));
0x0000000000400580 <+20>: 03 00 00 d4 smc #0x0
10 }
0x0000000000400584 <+24>: c0 03 5f d6 ret
End of assembler dump.
refs
http://www.ethernut.de/en/documents/arm-inline-asm.html
https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
https://github.com/llvm-mirror/clang/blob/master/test/CodeGen/aarch64-inline-asm.c
https://developer.arm.com/documentation/100067/0610/armclang-Inline-Assembler/Inline-assembly-statements-within-a-function/Clobber-list