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_ASLRldr x16, =1111fbr x161111:#endif.endmLOCAL_FUNC vector_std_smc_entry , : , .identity_mapreadjust_pcbl 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, w0ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONEsmc #0b . /* 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, w00x0000000000400570 <+4>: 20 01 80 d2 mov x0, #0x9 // #94 {0x0000000000400574 <+8>: e3 03 01 2a mov w3, w15 register unsigned long reg0 asm("r0") = 0x82000009;0x0000000000400578 <+12>: 00 40 b0 f2 movk x0, #0x8200, lsl #166 register unsigned long reg1 asm("r1") = 1;0x000000000040057c <+16>: 21 00 80 d2 mov x1, #0x1 // #17 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 #0x010 }0x0000000000400584 <+24>: c0 03 5f d6 retEnd 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