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

汇编语言中使用scanf获取双字符存入栈并打印的问题排查

问题

编写汇编程序时碰到这么个情况:
我要拿两个数字(按字符处理)存进栈里,之后逐个取出来打印。用scanf配"%c %c"的格式控制符读输入,但第二个字符总是读到换行符。
现在我是每次用subq $8, %rsp给每个字符分配栈空间,把栈地址分别传到%rsi和%rdx后调用scanf,但打印的时候只能输出第二个数字和换行符。我觉得分配的空间够,传的地址也对,但就是存不对内容,想知道怎么用scanf把字符正确存进栈里。

现有代码片段:

movq $scanf_c, %rdi
subq $8, %rsp
movq %rsp, %rsi
subq $8, %rsp
movq %rsp, %rdx
call scanf

解决方案

问题根因

你现在的问题主要出在两个地方:

  1. 栈地址传递顺序搞反了:栈是向下增长的,第一次subq $8, %rsp得到的地址比第二次的要高(更靠近栈顶),但scanf的参数顺序是%rsi对应格式串里第一个%c,%rdx对应第二个%c,你现在把低地址传给了第二个%c,等于把两个字符的存储位置弄反了。
  2. 虽然单个字符只需要1字节,你分配8字节完全没问题,但后续打印如果没正确取单个字节,也会输出垃圾数据。

修改后的代码示例

; 一次性分配16字节栈空间(满足栈对齐要求,同时存两个字符)
subq $16, %rsp
; 第一个%c的存储地址:当前rsp(较高地址),传给rsi
movq %rsp, %rsi
; 第二个%c的存储地址:rsp+1(连续的下一个字节),传给rdx
leaq 1(%rsp), %rdx
; 加载格式串地址到rdi
movq $scanf_c, %rdi
call scanf

; 打印测试(假设printf_c是"%c %c\n")
movq $printf_c, %rdi
; 取出第一个字符(用movb读单个字节)
movb (%rsp), %sil
; 取出第二个字符
movb 1(%rsp), %dl
call printf

; 释放栈空间
addq $16, %rsp

关键注意点

  • 栈是向下增长的,所以先分配的地址对应第一个输入字符,第二个字符直接存在下一个字节就行,没必要每次减8浪费空间。
  • 如果非要坚持每次减8的方式,那得把第一次减8后的地址传给%rdx,第二次减8后的传给%rsi,但这种方式会浪费栈空间,不推荐。
  • 打印的时候一定要用movb读取单个字节,别用movq,不然会把后面的7字节垃圾数据也读进去,导致输出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:12:13