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

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)发生了变化。核心问题有两个:

  1. --omagic链接参数的影响:这个参数会让链接器把代码段设置为可读写且未对齐,破坏了标准程序的内存段结构,导致调试工具出现异常判断。
  2. 无标准栈帧结构:你的代码没有遵循x86-64程序的启动约定,既没有使用call/ret指令,也没有初始化栈帧指针rbp,GDB只能通过启发式规则猜测栈结构,最终输出了虚假的栈回溯条目。

实际执行中,栈指针rsp的值根本没有变化,所谓的“栈增长”只是GDB的错误显示。

规避方法(实现栈的可预测性)

  1. 修正GDB的栈回溯行为
    在GDB中执行以下命令,关闭自动猜测栈结构的功能:

    set backtrace past-main off
    set backtrace past-entry off
    

    之后GDB只会显示当前执行点,不会生成虚假的栈条目。

  2. 显式控制栈指针
    在_start开头直接指定栈顶地址,完全掌控栈的起始位置:

    _start:
        mov rsp, 0x7ffffff000  ; 根据你的内存布局需求调整地址
        xor rax, rax
        ; 后续代码...
    

    注意要选择未被程序其他段占用的地址,避免内存冲突。

  3. 移除--omagic参数(若允许)
    这个参数会破坏正常的内存段权限和对齐规则,如果不需要代码段可写,去掉它能让程序更符合标准,减少调试工具的误判:

    ld -m elf_x86_64 test.o -o test
    
  4. 手动初始化栈帧(可选)
    如果需要GDB能正确识别栈结构,可以手动设置rbp构建栈帧:

    _start:
        mov rbp, rsp  ; 初始化栈帧指针,固定栈基址
        xor rax, rax
        ; 后续代码...
    

    这样GDB的栈回溯会更准确,不会出现无意义的条目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:06:08