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

汇编代码无限循环问题求助:用Push/Pop保护ECX实现20次迭代

修复ECX丢失导致的无限循环问题

问题根源很明确:x86汇编中LOOP指令依赖ECX作为循环计数器,如果你在循环体内调用了会修改ECX的函数(比如C标准库的rand,或者其他会改动ECX的操作),原来的循环计数会被覆盖,导致LOOP永远检测不到ECX为0,进而触发无限循环。

用Push/Pop解决的核心思路就是在修改ECX前保存其值,操作完成后恢复,具体实现如下:

完整修复代码示例

; 功能:生成指定长度的大写随机字符串
; 输入:EAX = 字符串长度L,ESI = 目标字节数组指针
; 返回:EAX = 原始数组指针(若需返回末尾指针可调整)
generate_upper_string:
    push esi            ; 保存原始指针,用于最终返回
    mov ecx, eax        ; 将长度L加载到循环计数器ECX
    jecxz .exit         ; 如果长度为0,直接退出

.loop_start:
    ; 保存当前ECX值到栈,避免后续操作覆盖
    push ecx

    ; 生成0-25的随机数,转换为大写字母(ASCII 0x41-0x5A)
    call rand           ; EAX = 随机数
    mov ebx, 26
    xor edx, edx
    div ebx             ; EDX = EAX % 26
    add dl, 0x41        ; 转换为大写字母

    ; 将字符写入目标数组
    mov [esi], dl
    inc esi             ; 移动指针到下一个位置

    ; 恢复ECX的循环计数,继续循环
    pop ecx
    loop .loop_start    ; ECX递减,不为0则重复循环

.exit:
    pop eax             ; 弹出原始ESI指针作为返回值
    ret

关键细节说明

  1. ECX的保存与恢复:
    在循环体内调用rand(或任何会修改ECX的操作)前,执行push ecx把当前循环计数器的值压入栈;操作完成后用pop ecx把值从栈中恢复,确保LOOP指令能正确递减计数并终止循环。
  2. 边界处理:
    用jecxz .exit处理长度为0的情况,避免无意义的循环。
  3. 返回值调整:
    示例中返回原始数组指针,若需要返回指向字符串末尾的指针,只需在exit标签处把esi赋值给eax即可,无需提前保存ESI。

额外注意

如果你的随机数生成逻辑是自定义的,只要该逻辑会修改ECX,就必须执行相同的Push/Pop操作来保存计数器值。另外,若调用的函数遵循特定调用约定(比如cdecl),需确认哪些寄存器会被破坏,按需保存其他寄存器(比如EBX、EDX等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:27:29