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

Contact me via :)
虚怀乃若谷,水深则流缓。