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

x64汇编跳转指令异常:循环运行时长超出预期求助

Win64汇编循环异常:输出多余空值的问题排查与修复

问题根源分析

  • 非易失性寄存器未保存:Win64调用约定中,RBX属于非易失性寄存器,调用C标准库函数(如printf)前必须手动保存,否则函数会修改RBX的值,导致循环计数器错乱。你的代码直接用RBX作为循环计数器,调用printf后RBX被破坏,循环逻辑彻底失控。
  • 字符串缺少终止符:err字符串末尾未添加ASCII空字符(0),printf会持续读取内存直到遇到空字符,可能引发乱码或意外行为。
  • 未遵守Win64调用约定的RAX要求:调用printf这类可变参数函数时,需将RAX设为浮点参数的数量(此处无浮点参数,需置RAX=0),否则会导致寄存器或栈状态异常。
  • 循环逻辑冗余混乱:循环内重复判断rbx与r11的关系,跳转逻辑重复,进一步加剧了循环失控的问题。

修复后的代码

bits 64
default rel

section .data
    fmt db "%s", 0xd, 0xa, 0
    err db "Correct usage: echo <string>", 0  ; 补充字符串终止符

section .text
    extern printf
    extern ExitProcess
    global main

main:
    ; 建立栈帧与阴影空间
    push rbp
    mov rbp, rsp
    sub rsp, 32
    
    ; 保存命令行参数
    mov r11, rcx ; argc
    mov r12, rdx ; argv

    ; 检查参数数量是否合规
    cmp r11, 2
    jl .wrong_num_of_args_error

    ; 保存非易失性寄存器RBX(避免被printf修改)
    push rbx
    mov rbx, 1  ; 从argv[1]开始遍历(argv[0]为程序名)
.loop:
    cmp rbx, r11
    je .loop_end

    ; 准备printf参数并调用
    mov rdx, [r12 + rbx * 8]
    mov rcx, fmt
    xor rax, rax  ; 浮点参数数量为0,符合Win64约定
    call printf

    inc rbx
    jmp .loop

.loop_end:
    pop rbx  ; 恢复RBX寄存器
.end:
    xor rax, rax
    call ExitProcess

.wrong_num_of_args_error:
    ; 输出错误提示
    mov rcx, err
    xor rax, rax
    call printf
    
    xor rax, rax
    call ExitProcess

关键修复点说明

  • 保护非易失性寄存器:使用RBX前执行push rbx保存其值,循环结束后pop rbx恢复,避免printf破坏计数器。
  • 补全字符串终止符:给err字符串末尾添加, 0,确保printf能正确识别字符串边界。
  • 符合调用约定:每次调用printf前清零RAX,满足Win64对可变参数函数的寄存器要求。
  • 简化循环逻辑:移除重复的条件判断,统一用jmp .loop实现循环,逻辑更清晰可控。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:31:00