我在这个论坛上阅读了很多主题,并在这个主题上找到了很多答案。我实现了从汇编代码中将5个参数传递给C函数。为此,我使用了以下说明:
mov r0, #0
mov r1, #1
mov r2, #2
mov r3, #3
mov r4, #4
STR r4, [sp, #-4]!
BL displayRegistersValue
但今天我试图将整个寄存器传递给C函数以将它们保存在C结构中。我尝试了这条指令:
STMDB sp!, {registers that i want to save}
我的C函数:
displayRegistersValue(int registers[number_of_registers])
char printable = registers[0] + (int)'0'; // Convert in a printable character
print_uart0(&printable);
但我的表现并不好。那么,我如何访问C代码中的寄存器呢?
答案 0 :(得分:5)
非常确定ARM标准只允许R0-R3按值传递4个最大值。如果你需要更多的值,那么将它们推入堆栈并以这种方式访问它们 - 就像编译器那样。或者制作一个结构并传递它的地址。
好的,加倍cheked我是对的here是ARM调用约定的链接 - 在页面下面。
要执行您想要的操作,请将某个内存位置(数组)的地址传递到程序集例程中。一旦你有了这个地址,可能在r0之内,你可以stmdb!进入该位置所有寄存器值和该存储器将在C级别可见。
请注意,这可能不会按照您的想法去做。根据上面的调用约定链接,允许这些值发生很大变化。如果这是用于调试,最好使用调试器并以这种方式观察寄存器。
好的,你仍然不理解:
{
int registerValues[14];
myAsmRoutine(registerValues);
print_uart0(& registerValues);
}
myAsmRoutine:
stmia r0!, {r1-r14}
blx lr
我跳过了R0和PC,但你明白了。此外,您需要做一些复杂的操作,将值更改为可打印的格式 - sprintf或itoa os类似的东西。
答案 1 :(得分:2)
displayRegistersValue(int registers[number_of_registers])
这是一个数组而不是一个结构,并作为指针传递给一些不是很长的项目列表。结构btw也是如此。
通常最简单的方法是构造一个在asm中执行所需操作的C函数,然后查看编译器生成的内容,然后从那里开始(使用ABI文档进行确认等)。
#define NUMREGS 13
void displayRegistersValue(unsigned int registers[NUMREGS]);
void outer ( void )
{
unsigned int regs[NUMREGS];
displayRegistersValue(regs);
}
> arm-none-linux-gnueabi-gcc -O2 -c fun.c -o fun.o
> arm-none-linux-gnueabi-objdump -D fun.o
fun.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <outer>:
0: e52de004 push {lr} ; (str lr, [sp, #-4]!)
4: e24dd03c sub sp, sp, #60 ; 0x3c
8: e28d0004 add r0, sp, #4
c: ebfffffe bl 0 <displayRegistersValue>
10: e28dd03c add sp, sp, #60 ; 0x3c
14: e49df004 pop {pc} ; (ldr pc, [sp], #4)
你需要做类似的事情,通过添加到堆栈指针在堆栈上腾出空间,保存lr所以你不要用分支链接丢弃它,将你的寄存器复制到那个内存(堆栈)点r0到要传递的内存/数组的开头,然后调用该函数(r0是您传递给函数的第一个也是唯一的参数)。
push {lr}
mov lr,sp
stmdb sp!,{r0-r12}
mov r0,lr
bl displayRegistersValue
add sp,sp,#52
pop {lr}
答案 2 :(得分:0)
数组作为指针传递到单个寄存器中。如果你想要5个寄存器,那么你需要有5个参数(int i1,int i2等)。
答案 3 :(得分:0)
引用ARM APCS文档:
“前四个寄存器r0-r3(a1-a4)用于将参数值传递给子程序并从函数返回结果值。它们也可用于在例程中保存中间值(但是,一般来说,只在子程序调用之间。“
因此,如果要将超过4个值传递给C函数,则需要传递堆栈上的其余值。更好的想法是将寄存器值放在已静态分配的内存区域中,并将内存(指针)的地址传递给C函数。函数可以取消引用指针以获取寄存器值。