typedef int (*fun)(int a , int b );
typedef struct _str
{
int a;
int b;
fun op;
} STR;
STR funop;
int fun2 ( int a, int b)
{
funop.a=a;
funop.b=b;
return(funop.op(a,b)+1);
}
00000000 <fun2>:
0: e59f3014 ldr r3, [pc, #20] ; 1c <fun2+0x1c>
4: e92d4010 push {r4, lr}
8: e5932008 ldr r2, [r3, #8]
c: e8830003 stm r3, {r0, r1}
10: e12fff32 blx r2
14: e2800001 add r0, r0, #1
18: e8bd8010 pop {r4, pc}
1c: 00000000
只需要它想要使用基址加偏移寻址来读取函数的地址然后调用它。 blx 进行调用,因此值是函数指针,因此代码与函数指针相关。如果没有该结构,它可能不会执行 base + offset 而是执行 pc 相对加载。
它不一定是全局的。
int (*fun)(int a , int b );
int fun2 ( int a, int b)
{
return((fun)(a,b)+1);
}
00000000 <fun2>:
0: e59f3018 ldr r3, [pc, #24] ; 20 <fun2+0x20>
4: e92d4010 push {r4, lr}
8: e5933000 ldr r3, [r3]
c: e1a0e00f mov lr, pc
10: e12fff13 bx r3
14: e8bd4010 pop {r4, lr}
18: e2800001 add r0, r0, #1
1c: e12fff1e bx lr
20: 00000000 .word 0x00000000
因为我把它设为全局,所以它必须做双重间接的事情,所以它仍然是一个基数加偏移量(零)。
int fun3(int a , int b );
int fun2 ( int a, int b)
{
int (*fun)(int a , int b );
fun=fun3;
return((fun)(a,b)+1);
}
00000000 <fun2>:
0: e92d4010 push {r4, lr}
4: ebfffffe bl 0 <fun3>
8: e8bd4010 pop {r4, lr}
c: e2800001 add r0, r0, #1
10: e12fff1e bx lr
链接器填充直接偏移量,因此没有寄存器加偏移量寻址。根本没有ldr,因为可以用分支链接处理。
我认为这些选择是在链接时解决的 bl 或在链接时解决的池值的双重间接。结构与否,它是一个带有寄存器加偏移量的 ldr(gnu 反汇编程序不显示偏移量,如果为零)。