32位x86汇编栈局部变量在函数调用后值丢失问题咨询
问题根因
你遇到的重复打印问题本质是局部变量栈空间未预留,导致存储的字符串地址被后续入栈操作覆盖,具体栈帧逻辑如下:
- 进入
main函数执行pushl %ebp; movl %esp, %ebp后,ebp与esp指向同一位置,你并没有通过subl $N, %esp的操作为局部变量预留栈空间,此时-4(%ebp)对应的内存地址属于未被保留的栈区域。 - 你执行
movl $LC0, -4(%ebp)将world字符串地址写入该位置后,后续执行pushl $LC1操作时,pushl会先将esp减4,正好指向-4(%ebp)的地址,直接把你之前写入的LC0地址覆盖为LC1的地址。 - 第二次打印时读取
-4(%ebp)取到的是被覆盖的LC1地址,自然会重复打印Test Print。
你提到的“赋值后直接打印就正常”也能印证这个根因:赋值后没有其他入栈操作覆盖该地址,取出的自然是正确的LC0地址。
修复方案
只需要在main函数栈帧初始化后,给局部变量预留对应大小的栈空间即可,修改后的main代码如下:
main: pushl %ebp movl %esp, %ebp subl $4, %esp # 新增:为存储在-4(%ebp)的局部变量预留4字节空间 .section .data LC0: .string "world\n" LC1: .string "Test Print\n" .section .text movl $LC0, -4(%ebp) pushl $LC1 call print addl $4, %esp # 可选:符合cdecl调用约定,调用者清理入栈参数 pushl -4(%ebp) call print addl $4, %esp # 可选:同上清理参数 leave ret
额外优化建议
不要在.text代码段中穿插.section .data声明,建议把所有数据段内容统一放在代码最开头或末尾,避免汇编器处理段切换时出现不可预期的问题。
内容的提问来源于stack exchange,提问作者ilittlebig
相关产品推荐
相关产品推荐

