Debugging 从ARM汇编函数调用printf时出现堆栈问题

Debugging 从ARM汇编函数调用printf时出现堆栈问题,debugging,assembly,stack,arm,printf,Debugging,Assembly,Stack,Arm,Printf,我有一个ARM汇编函数,它是从C函数调用的 在某个时候,我会这样做: .syntax unified .arm .text .globl myfunc .extern printf myfunc: stmdb sp!, {r4-r11} // save stack from C call 。。。做些事情 // (NOT SHOWN): Load values into r1 and r2 to be printed by format string above ldr

我有一个ARM汇编函数,它是从C函数调用的

在某个时候,我会这样做:

.syntax unified  
.arm
.text
.globl myfunc
.extern printf

myfunc:     
stmdb sp!, {r4-r11}     // save stack from C call
。。。做些事情

// (NOT SHOWN): Load values into r1 and r2 to be printed by format string above 
ldr     r0, =message  // Load format string above
push {lr}   // me attempting to preserve my stack
bl      printf  // actual call to printf
pop {lr}    // me attempting to recover my stack
ldmia sp!, {r4-r11} // recover stack from C call
mov r0, r2     // Move return value into r0
mov pc, lr     //  Return to C
.section data
 message:  
.asciz "Output: %d, %d\n"
.end
它有时运行,有时崩溃,运行几次然后崩溃,等等。它实际上是在准裸机上下文上运行的,所以我不能运行调试器。我99%确定这是一个堆栈-或对齐事情,就这样,这样

有人能提供一些关于如何运行上述代码块的具体想法吗?也许还有关于最佳实践的一般想法?理想情况下,我希望能够在我的汇编文件中多次调用相同的输出函数,以便在调试过程中进行调试


提前谢谢

我可以在代码中看到以下问题:

.align 2可以是函数入口点myfunc之前的3或任何更高的值: 正如在评论中所提到的,堆栈预期是8B对齐的。推{lr}会破坏这个

消息:不需要在“数据”部分。它可能放在“myfunc”后面的代码部分。检查链接器映射是否实际存在数据&加载到r0中的地址是否正确


由于这是一个裸金属,请检查堆栈是否设置正确,是否为其预留了足够的空间。

堆栈需要8字节对齐。只要按一下lr,就会打破它。在lr旁边推送一些东西,使推送8字节对齐,您也可以在函数的序言中这样做。为什么不在函数调用前后打印堆栈值,看看它在哪里崩溃呢。由于您使用的是裸机,所以还可以处理不同的CPU模式,并像崩溃处理程序一样打印寄存器值,例如当CPU进入中止状态时。不久前我对printf做了类似的事情:我建议您不要使用printf来调试汇编程序。编写自己的轮询UART例程。还有一些简单的例程可以将int字符转换为十六进制字符。printf需要很多机器才能正常工作。轮询的UART例程甚至可能不需要堆栈。看一看。如果按照auselen的方法,我建议使用snprintf实现,并将缓冲区传递给轮询的UART。如果您坚持现有的方式,我建议您将lr保存和还原与寄存器保存放在一起。请看一些汇编程序。那么您的回报就是ldmia sp!,{r4-r11,pc}。您可能应该更新fp,因为printf可能想要使用它,并且可能出于某种原因在堆栈上跺脚。即,C代码使用[fp]访问本地“C”变量和其他机器。
.align 2 // guarantee that instruction address is 4B aligned
myfunc: