【问题标题】:How can I fix the length of a string in printf when called from RISC-V assembly?从 RISC-V 程序集调用时,如何修复 printf 中字符串的长度?
【发布时间】:2021-01-10 22:54:17
【问题描述】:

我想使用 newlib 在 Spike 上的 pk 上运行 RISC-V 程序(程序集)获得一些输出。

我可以用空终止的字符串调用 printf,例如 (sn-p)

la a0 msg_
jal printf

.data
msg_ .ascii "MESSAGE IS \n"
.equ len_msg_, . - msg_

将打印出 MESSAGE IS - 但是如何将字符串的长度传递给调用?我已经尝试过 a1 - a7 并且它 似乎 不是它们,我也无法将我想要的长度放在堆栈上工作(我可能只是做错了,但无论如何更多或者更少,printf 函数似乎要做的第一件事就是在堆栈上保存大量寄存器,所以我认为这行不通。

为了增加我的困惑,我使用了编译器资源管理器 (https://godbolt.org/z/vscGPG),我看不到任何迹象表明任何长度的东西都在通过。我错过了什么?

【问题讨论】:

  • printf 不使用作为参数传递的字符串长度,它只是打印字符串的字符,直到它到达 C 样式的 nul 字符终止符。所以,如果你想使用printfputs,给它传递一个C 风格的以空字符结尾的字符串。 printf 需要格式化字符串以空字符结尾;它还需要添加参数字符串(例如,使用格式字符串中的%s 打印)以空字符终止。
  • 计算字符串的静态长度是由您使用的特定汇编程序决定的语法。
  • 我认为您需要使用.asciz 而不是.ascii 来使您的字符串以空值终止。正如 Erik 所说,如果你这样做,那么根本不需要处理长度问题。
  • 你可以试试this(确保你也检查了那里的cmets)。

标签: assembly c-strings libc calling-convention riscv


【解决方案1】:

你没有。你 null 终止 msg

我对这个程序集不太熟悉,但你想让它发出一个零字节。其中一项可能是正确的:

msg_ .ascii "MESSAGE IS \n\0"

msg_ .asciz "MESSAGE IS \n"

msg_ .ascii "MESSAGE IS \n"
     .byte  0

在任何情况下你都不需要len_msg_

【讨论】:

  • GNU 汇编器也接受.string,它还包括零字节。这就是 OP 的 Compiler Explorer 输出。
  • @NateEldredge: 除非对特定机器另有规定,否则汇编程序会用 0 字节标记每个字符串的结尾 - 所以显然在某些机器上,它是 .ascii.asciz。我建议始终使用.asciz 使其明确,因此读者不必尝试准确记住语义是什么。 GAS 有许多与各种 Unix 汇编程序兼容的指令别名,其中一些在清晰度方面客观上比其他的更好。虽然如果你想要 UTF-16 / UTF-32,string16 / string32 没有 .ascii/asciz 等价物。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多