ARM汇编中使用scanf读取7位字符串存入数组的问题如何解决
错误原因澄清
你最初的猜测有误:scanf处理%s格式符时,不会把读取到的字符直接存到寄存器里,你传入的r1是用户缓冲区的地址,scanf会把读取到的字符串+末尾\0结束符写入该地址指向的内存空间,这部分参数传递逻辑是正确的。运行异常是以下两个核心问题导致的:
- 栈对齐不符合AAPCS规范:ARM 32位架构的调用约定要求,执行
bl指令调用函数前,栈指针sp必须对齐到8字节边界。你调用getUserInput前执行了sub sp, sp, #28,28不是8的倍数,会导致后续调用scanf时栈未对齐触发异常。 - 格式串无长度限制存在溢出风险:你用
%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
相关产品推荐
相关产品推荐

