You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM汇编中使用scanf读取7位字符串存入数组的问题如何解决

错误原因澄清

你最初的猜测有误:scanf处理%s格式符时,不会把读取到的字符直接存到寄存器里,你传入的r1是用户缓冲区的地址,scanf会把读取到的字符串+末尾\0结束符写入该地址指向的内存空间,这部分参数传递逻辑是正确的。运行异常是以下两个核心问题导致的:

  1. 栈对齐不符合AAPCS规范:ARM 32位架构的调用约定要求,执行bl指令调用函数前,栈指针sp必须对齐到8字节边界。你调用getUserInput前执行了sub sp, sp, #28,28不是8的倍数,会导致后续调用scanf时栈未对齐触发异常。
  2. 格式串无长度限制存在溢出风险:你用%s读取字符串时没有限制长度,一旦用户输入超过7个字符,超出的内容会覆盖栈上的其他数据,也会导致运行异常。而且7位字符串需要额外1字节存储\0结束符,实际需要8字节存储空间。
修正方案
  • 调整栈分配大小:将栈分配的28字节改为32字节,32是8的倍数,满足栈对齐要求。
  • 修改格式串:把"%s"改为"%7s",限制最多读取7个非空白字符,自动在末尾补\0,刚好匹配你的需求,避免缓冲区溢出。
修正后的代码

函数实现部分

.cpu cortex-a72
.fpu neon-fp-armv8

.data
getinp: .string "%7s" @ 修改为带长度限制的格式串

.text
.align 2
.global getUserInput
.type getUserInput, %function

getUserInput:
    push {fp, lr} @ 存储fp和lr到栈
    add fp, sp, #4 

    mov r1, r0 @ 传入的缓冲区地址作为scanf第二个参数
    ldr r0, =getinp @ 格式串地址作为scanf第一个参数
    bl scanf

    sub sp, fp, #4
    pop {fp, pc}

调用部分

sub sp, sp, #32 @ 调整栈分配大小为32字节,满足8字节对齐要求
mov r0, sp
bl getUserInput

内容的提问来源于stack exchange,提问作者Arno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 04:18:03