Pas*_*lis 5 assembly gcc arm inline-assembly
我想在不修改寄存器的情况下branch使用特定地址(不是标签).所以我选择而不是或.我希望这可以完成.ARM assemblyLRBBLBXGCC inline asm
这是文档,这是我尝试过的:
#define JMP(addr) \
__asm__("b %0" \
: /*output*/ \
: /*input*/ \
"r" (addr) \
);
Run Code Online (Sandbox Code Playgroud)
它是一个C宏,可以用一个调用address.当我运行它时,我收到以下错误:
error: undefined reference to 'r3'
错误是因为使用"r".我调查了一下,我发现它可能是gcc 4.9.*版本的错误.
顺便说一句,我使用的Android/Linux Gcc 4.9 cross compiler,上OSX.另外,我不知道我应该装什么东西Rm.
干杯!
编辑:
我将宏更改为此,我仍然得到undefined reference to r3 and r4:
#define JMP(addr) \
__asm__("LDR r5,=%0\n\t" \
"LDR r4,[r5]\n\t"\
"ADD r4,#1\n\t" \
"B r4" \
: /*output*/ \
: /*input*/ \
"r" (addr) \
: /*clobbered*/ \
"r4" ,"r5" \
);
Run Code Online (Sandbox Code Playgroud)
说明:将变量的地址加载到r5,然后将该地址的值加载到r4.然后将1加到LSB(ARM规范要求的emm?).最后分支到那个地址.
由于您使用 C 进行编程,因此您可以使用完全没有任何汇编的普通 C 方法:只需将保存指向您要跳转到的地址的指针的变量强制转换为函数指针并立即调用它:
((void (*)(void)) addr)();
Run Code Online (Sandbox Code Playgroud)
只是对这个方括号丛林的解释:使用此代码,您将addr指向一个指针(由星号表示),该指针指向(*)一个不带参数(第二个void意味着没有参数)并且也不返回任何内容(第一个void)的函数。最后最后两个括号是该函数的实际调用。谷歌搜索“C 函数指针”以获取有关该方法的更多信息。
但是,如果这对您不起作用并且您仍然想要采用汇编方法,那么您正在寻找的指令实际上是BX(不确定您最初为什么排除它。但我可以猜到名称“Branch and Exchange”误导您相信寄存器参数与程序计数器交换(并因此更改),事实并非如此,但它在开始时也让我感到困惑)。
为此,只需简单回顾一下说明:
B将标签作为参数。实际上,跳转将被编码为与当前位置的偏移量,它告诉处理器向前或向后跳转那么多指令(通常编译器、汇编器或链接器会为您计算该偏移量)。在执行过程中,控制流将简单地转移到该位置而不更改任何寄存器(这意味着链接寄存器LR也将保持不变)BX R0将从寄存器中获取绝对(因此不是偏移量)地址,在这种情况下R0,并在该地址继续执行。这也是在不更改任何其他寄存器的情况下完成的。BL和BLX R0是前两条指令的对应对应物。他们将在控制流方面做同样的事情,但最重要的是将当前程序计数器保存在链接寄存器中LR。如果被调用的函数稍后返回,则需要这样做。所以本质上,你需要做的是:
asm("BX %0" : : "r"(addr));
Run Code Online (Sandbox Code Playgroud)
指示编译器确保变量addr位于寄存器 ( r) 中,您承诺只读取该寄存器而不更改该寄存器。最重要的是,返回时您不会更改(破坏)任何其他寄存器。
有关内联汇编约束的更多信息,请参见此处 https://gcc.gnu.org/onlinedocs/gcc/Constraints.html。
为了帮助您理解为什么还有其他解决方案,这里有一些关于 ARM 架构的内容:
PC可用于作为常规寄存器访问的许多指令R15。它只是该确切寄存器编号的别名。BX LR这正是您想要做的:获取链接寄存器的内容(LR是 的别名R14)并跳转到该位置,有效地返回给调用者POP {R4-R11, PC}恢复调用者保存的寄存器并跳回调用者。这几乎肯定会PUSH {R4-R11, LR}在函数的开头有对应物:您将链接寄存器的内容(返回地址)推入堆栈,但将其存储回程序计数器,最终有效地返回给调用者B 分支到不同的函数,如果该函数以尾调用结束并将其留给该函数返回原始调用者。希望有帮助,马丁
您不能分支到寄存器,只能分支到标签。如果要跳转到寄存器中的地址,则需要将其移至 PC 寄存器 (r15)。
#define JMP(addr) \
__asm__("mov pc,%0" \
: /*output*/ \
: /*input*/ \
"r" (addr) \
);
Run Code Online (Sandbox Code Playgroud)