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

x86汇编Print函数添加ret指令后输出异常问题求助

问题:添加ret指令后打印输出多了一个.字符

我用NASM汇编器和GoLink链接器编写了一个打印单个字符的简单函数,代码如下:

STD_OUTPUT_HANDLE   equ -11
NULL                equ 0

global Start
extern ExitProcess, GetStdHandle, WriteConsoleA

section .bss
msg     resb    1

section .text

Start:
    push 'b'
    call Print

Print:
    ; Function Start
    push    ebp 
    mov     ebp,esp
    
    ; accepting the argument 
    mov     ebx , [esp + 8]
    mov     [msg],ebx
    
    ; eax = handle
    push    STD_OUTPUT_HANDLE
    call    GetStdHandle
    
    ; WriteConsoleA System call 
    push    NULL
    push    1
    push    msg
    push    eax
    call    WriteConsoleA 
    
    ; Funcion end
    mov     esp, ebp
    pop     ebp
    ret

遇到的问题:移除ret指令时,输出符合预期的b;但添加ret指令后,输出变为b.。请问这是什么原因?


原因分析

  1. 程序未主动终止:当Print函数通过ret返回后,程序回到Start中call Print的下一行,但Start之后没有任何终止程序的代码,CPU会继续执行内存中后续的随机垃圾指令。这些垃圾指令意外触发了额外的字符输出,刚好表现为.。
  2. 无ret时的巧合终止:移除ret后,Print执行完pop ebp后,EIP指向的是无有效指令的内存区域,操作系统直接回收进程,因此只输出了预期的b。

修复方案

方案1:主动调用ExitProcess终止程序

在Start的call Print之后,添加退出代码,确保程序执行完打印后正常终止:

Start:
    push 'b'
    call Print
    push NULL        ; 传递退出码给ExitProcess
    call ExitProcess

方案2:修复栈平衡(更规范的写法)

因为Print函数的参数是通过push传递的4字节数据,可修改Print的返回指令为ret 4,让函数自动清理参数栈(符合Windows stdcall调用约定):

; 将Print函数末尾的ret替换为:
ret 4

两种方案结合使用,程序就能稳定输出b且无额外字符。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:05:55