Pho*_*non 10 c assembly arm gnu-assembler cortex-a8
我正在Android设备上编写针对ARM Cortex-A的代码(使用GNU汇编器和编译器),我正在尝试在Assembly和C之间进行接口.特别是,我有兴趣调用用C语言编写的函数.我尝试了很多东西,包括.extern指令,用asm和__asm__等声明C函数,但是没有一个工作,所以我正在寻找一个这样做的最小例子.对这样的例子的引用同样值得欢迎.
你需要阅读ARM ARM和/或知道指令集是全部,通常你会想做这样的事情
asm:
bl cfun
c:
void cfun ( void )
{
}
Run Code Online (Sandbox Code Playgroud)
你可以自己试试.对于gnu as和gcc,这很好用,如果你使用clang来获取对象的c代码和gnu和汇编程序,它也应该工作得很好.不确定你在用什么.
上面的问题是bl的范围有限,
if ConditionPassed(cond) then
if L == 1 then
LR = address of the instruction after the branch instruction
PC = PC + (SignExtend_30(signed_immed_24) << 2)
Run Code Online (Sandbox Code Playgroud)
知道bl指令将链接寄存器设置为bl指令后的指令,那么如果你读到程序计数器寄存器:
For an ARM instruction, the value read is the address of the instruction
plus 8 bytes. Bits [1:0] of this
value are always zero, because ARM instructions are always word-aligned.
Run Code Online (Sandbox Code Playgroud)
所以,如果你让你的asm看起来像这样:
mov lr,pc
ldr pc,=cfun
Run Code Online (Sandbox Code Playgroud)
你得到
d6008034: e1a0e00f mov lr, pc
d6008038: e51ff000 ldr pc, [pc, #-0] ; d6008040
...
d6008040: d60084c4 strle r8, [r0], -r4, asr #9
Run Code Online (Sandbox Code Playgroud)
汇编器将保留一个内存位置,在ldr pc指令的范围内(如果可能,否则会产生错误),它将为指令放置完整的32位地址.链接器稍后将使用外部地址填充此地址.这样你就可以到达地址空间中的任何地址.
如果你不想玩这样的汇编游戏并希望控制,那么你创建位置来保存函数的地址并自己加载到电脑中:
mov lr,pc
ldr pc,cfun_addr
...
cfun_addr:
.word cfun
Run Code Online (Sandbox Code Playgroud)
编译:
d6008034: e1a0e00f mov lr, pc
d6008038: e51ff000 ldr pc, [pc, #-0] ; d6008040 <cfun_addr>
...
d6008040 <cfun_addr>:
d6008040: d60084c4 strle r8, [r0], -r4, asr #9
Run Code Online (Sandbox Code Playgroud)
最后,如果你想进入ARM和拇指混合或可以的现代ARM世界(例如使用bx lr而不是mov pc,lr)那么你会想要使用bx
add lr,pc,#4
ldr r1,cfun_addr
bx r1
...
cfun_addr:
.word cfun
Run Code Online (Sandbox Code Playgroud)
当然,如果你想保留它们,你需要另外一个寄存器才能这样做,并记得在你打电话给C之前和之后推送和弹出你的链接寄存器和另一个寄存器.