【问题标题】:Stack problems when calling printf from an ARM assembly function从 ARM 汇编函数调用 printf 时的堆栈问题
【发布时间】:2014-07-12 07:13:02
【问题描述】:

我有一个从 C 函数调用的 ARM 汇编函数。

在某些时候,我会做这样的事情:

.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% 确定这是一个堆栈——还是对齐? -- 事情,根据这个Printf Change values in registers, ARM Assembly 和这个Call C function from Assembly -- the application freezes at "call printf" and I have no idea why

任何人都可以提供一些关于如何运行上述代码块的具体想法,或者在这里提供最佳实践的一般想法吗?理想情况下,我希望能够在我的程序集文件中多次调用相同的输出函数,以便随时调试。

提前致谢!

【问题讨论】:

  • 堆栈需要 8 字节对齐。只是推动lr,打破了这一点。在 lr 旁边推送一些东西以使推送 8 字节对齐(您也可以在函数的序言中这样做)。为什么不在函数调用之前和之后打印堆栈值以查看它崩溃的位置。由于您正在使用裸机,您还可以处理不同的 CPU 模式并打印寄存器值,例如当 CPU 进入 ABORT 时的崩溃处理程序。不久前我为 printf 做了类似的事情:github.com/auselen/arm-printf
  • 我建议你不要使用printf来调试汇编器。编写您自己的轮询 UART 例程。还有一些简单的例程可以将 int 转换为十六进制字符。 printf 需要大量机器才能正常工作。轮询的 UART 例程甚至可能不需要堆栈。看看here for some implementation。如果你走 auselen 的路线,我建议你获得一个 snprintf 实现并将缓冲区传递给轮询的 UART。
  • 如果你坚持现有的,我建议你把lr保存和恢复和寄存器保存一起。查看ARM link and frame pointer 了解一些汇编程序。你的回报就是ldmia sp!, {r4-r11,pc}。您可能应该更新fp,因为printf 可能想要使用它并且可能出于某种原因踩到您的堆栈。即,C 代码使用[fp] 访问本地“C”变量和其他机器。

标签: debugging assembly stack arm printf


【解决方案1】:

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

  1. .align 2(可以是 3 或更高的值)在函数入口点之前 (myfunc:)
.align 2 // guarantee that instruction address is 4B aligned
myfunc:
  1. 如 cmets 中所述,堆栈应为 8B 对齐。 push {lr} 打破了这一点。

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

既然是裸机,请检查堆栈是否设置正确并为其保留足够的空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-04
    • 2018-04-28
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多