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

NASM汇编中函数调用内pop指令失效的原因及解决方法?

问题原因与解决方法

核心问题

call指令执行时会自动将返回地址压入栈顶,所以你执行push keystring+0x7c00后,栈内的顺序是:

  1. 栈顶:返回地址(call指令的下一条指令地址)
  2. 栈顶+4:你push的字符串指针

此时直接pop ecx拿到的是返回地址,而非字符串指针,自然无法正确打印。

解决方法

方法1:暂存返回地址再取出参数

先弹出返回地址暂存,取出参数后再把返回地址压回栈顶,保证ret能正确返回:

push keystring+0x7c00
call PrintString
jmp $

;====functions====

PrintString:
    pop eax          ; 弹出返回地址到eax暂存
    pop ecx          ; 弹出字符串参数到ecx
    push eax         ; 将返回地址重新压回栈顶,让ret正常工作

    mov ah, 0x0e
LoopHead:
    mov al, [ecx]
    test al, al      ; 检查当前字符是否为结束符0
    jz PrintEnd      ; 是结束符就退出循环
    int 0x10         ; BIOS中断打印字符
    inc ecx          ; 指针移到下一个字符
    jmp LoopHead
PrintEnd:
    ret

;====variables====

keystring:
    db "Press any key...", 0

;====padding====

times 510-($-$$) db 0
db 0x55, 0xAA

方法2:通过栈偏移直接访问参数

利用栈偏移读取参数,最后用ret 4清理栈上的参数:

push keystring+0x7c00
call PrintString
jmp $

;====functions====

PrintString:
    mov ecx, [esp+4] ; 直接从栈中读取参数(返回地址在esp,参数在esp+4位置)

    mov ah, 0x0e
LoopHead:
    mov al, [ecx]
    test al, al
    jz PrintEnd
    int 0x10
    inc ecx
    jmp LoopHead
PrintEnd:
    ret 4            ; 返回时同时弹出栈上的4字节参数,清理栈空间

;====variables====

keystring:
    db "Press any key...", 0

;====padding====

times 510-($-$$) db 0
db 0x55, 0xAA

额外说明

原代码中的循环逻辑存在问题:add bl, [ecx]的判断方式错误,应该直接检查当前字符是否为字符串结束符0,用test al, al配合jz指令是更标准的字符串遍历写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:22:56