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

NASM自定义print函数打印EAX二进制位时出现段错误问题

段错误原因排查与修复方案

核心问题原因

  • 非法修改栈指针ESP:打印逻辑中mov esp,printDD_var_save直接改写了栈寄存器,导致后续恢复寄存器、执行ret指令时,栈指针指向的是你定义的字符缓冲区而非原始栈位置,读取的返回地址和寄存器值全部非法,直接触发段错误。获取缓冲区地址完全不需要修改ESP,直接计算有效地址赋值给ECX即可。
  • 缓冲区越界写入:写入字符时使用了dword(4字节)操作数,每次写操作会覆盖当前偏移后4个字节的内存,当esi遍历到28以上时,写入位置已经超出你预留的32字节缓冲区范围,会破坏后续内存数据。存储单个ASCII字符只需用byte(1字节)操作数即可。
  • 栈操作顺序不匹配:入栈顺序是push ebx -> push ecx -> push edx -> push esi -> push esp,栈是后进先出结构,出栈顺序应该完全反过来,你当前的出栈顺序和入栈顺序完全不对应,就算没有修改ESP的问题,恢复的寄存器值也是错误的。另外你没有用到保存的ESP值,完全不需要额外push/pop ESP。

修复后代码

;传入参数:待打印值存在eax寄存器
;需要提前定义:printDD_var_save resb 32,newline db 0xA

printDD_start:
    push ebx
    push ecx
    push edx
    push esi

    mov esi,0
printDD:
    cmp esi,31
    jg printDD_printStart

    test eax,1
    jz printDD_zero
printDD_one:
    mov byte [printDD_var_save + esi],49
    inc esi
    shr eax,1
    jmp printDD
printDD_zero:
    mov byte [printDD_var_save + esi],48
    inc esi
    shr eax,1
    jmp printDD

printDD_printStart:
    mov esi,31
printDD_print:
    cmp esi,0
    jl printDD_exit

    ; 直接计算要打印的字符地址赋值给ecx,完全不碰esp
    lea ecx, [printDD_var_save + esi]
    mov eax,4
    mov ebx,1
    mov edx,1
    int 80h

    dec esi
    jmp printDD_print

printDD_exit:
    mov eax,4
    mov ebx,1
    mov ecx,newline
    mov edx,1
    int 80h

    ; 出栈顺序和入栈严格相反
    pop esi
    pop edx
    pop ecx
    pop ebx
    ret

优化提示:如果追求性能可以一次性打印32个字符,不需要循环32次调用write系统调用,修改打印逻辑直接传入printDD_var_save地址、长度32即可,运行效率会高很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:36:04