NASM中未用push指令,跳转至标签后栈为何异常增长?
未使用push指令,执行到test标签后栈为何增长?如何实现栈增长的可预测性?
我在以下汇编代码示例中未使用任何push指令,但执行至test标签后栈出现了增长。我需要对栈进行精细控制以确保可靠性,我的代码架构是非常规的,这是有意为之。若此为预期行为,是否有方法规避以实现栈增长的可预测性?
Makefile
test: nasm -g -F dwarf -felf64 test2.asm -o test.o ld -m elf_x86_64 --omagic test.o -o test
test2.asm
global _start section .text _start: xor rax, rax xor rbx, rbx mov rsi, knitter mov rdi, intermediary test: mov al, byte [rsi + rbx] end: jmp end len_array equ 4096 intermediary: resb len_array knitter: db "zend:", 10, \ 0 ; End of string
GDB调试输出
(gdb) make -e test make: 'test' is up to date. (gdb) b _start Breakpoint 2 at 0x400080: file test2.asm, line 6. (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/nico/Dropbox/Projects/datalp/test Breakpoint 2, _start () at test2.asm:6 6 xor rax, rax (gdb) n 7 xor rbx, rbx (gdb) 8 mov rsi, knitter (gdb) bt #0 _start () at test2.asm:8 (gdb) n 9 mov rdi, intermediary (gdb) bt #0 _start () at test2.asm:9 (gdb) n test () at test2.asm:11 11 mov al, byte [rsi + rbx] (gdb) bt #0 test () at test2.asm:11 #1 0x0000000000000001 in ?? () #2 0x00007fffffffe8ee in ?? () #3 0x0000000000000000 in ?? () (gdb)
问题原因
你看到的栈“增长”是GDB的误判,并非实际栈指针(rsp)发生了变化。核心问题有两个:
--omagic链接参数的影响:这个参数会让链接器把代码段设置为可读写且未对齐,破坏了标准程序的内存段结构,导致调试工具出现异常判断。- 无标准栈帧结构:你的代码没有遵循x86-64程序的启动约定,既没有使用
call/ret指令,也没有初始化栈帧指针rbp,GDB只能通过启发式规则猜测栈结构,最终输出了虚假的栈回溯条目。
实际执行中,栈指针rsp的值根本没有变化,所谓的“栈增长”只是GDB的错误显示。
规避方法(实现栈的可预测性)
修正GDB的栈回溯行为
在GDB中执行以下命令,关闭自动猜测栈结构的功能:set backtrace past-main off set backtrace past-entry off之后GDB只会显示当前执行点,不会生成虚假的栈条目。
显式控制栈指针
在_start开头直接指定栈顶地址,完全掌控栈的起始位置:_start: mov rsp, 0x7ffffff000 ; 根据你的内存布局需求调整地址 xor rax, rax ; 后续代码...注意要选择未被程序其他段占用的地址,避免内存冲突。
移除
--omagic参数(若允许)
这个参数会破坏正常的内存段权限和对齐规则,如果不需要代码段可写,去掉它能让程序更符合标准,减少调试工具的误判:ld -m elf_x86_64 test.o -o test手动初始化栈帧(可选)
如果需要GDB能正确识别栈结构,可以手动设置rbp构建栈帧:_start: mov rbp, rsp ; 初始化栈帧指针,固定栈基址 xor rax, rax ; 后续代码...这样GDB的栈回溯会更准确,不会出现无意义的条目。
内容的提问来源于stack exchange,提问作者Nico Verrijdt
相关产品推荐
相关产品推荐

