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

x86汇编乘法实现程序始终返回0的异常问题排查

问题原因分析与修正方案

1. 算法逻辑错误:你实现的不是两数乘法,而是初始值乘以2的ecx次方

你的代码逻辑是每次将ebx翻倍(add ebx, ebx等价于ebx *= 2),循环ecx次,最终结果是初始ebx值 × 2^ecx,而非你预期的ebx × ecx。

  • 比如你测试的ecx=0x2、ebx=0x3:循环2次后,ebx从3→6→12,对应3×2²=12,这和你想要的3×2=6完全不符。

2. 返回值被系统截断:exit系统调用仅保留低8位结果

Linux下使用int 0x80调用exit(eax=1)时,程序返回值只取ebx寄存器的低8位(范围0-255)。当计算结果超过255时,会自动对256取模:

  • 你第一次测试ecx=0x12(18)、ebx=0x2:最终ebx=2×2^18=524288,524288 ÷ 256 = 2048,余数为0,所以echo $?返回0。
  • 当结果增大到是256的倍数时,返回值就会是0,这就是你看到“增大参数后始终返回0”的原因。

修正方案

方案一:用加法模拟真正的两数乘法(a×b)

如果想手动实现ebx × ecx,需要把初始值累加ecx次,而非每次翻倍:

global _start

_start:
    mov ecx, 0x12    ; 乘数
    mov ebx, 0x2     ; 被乘数
    mov eax, 0       ; 结果寄存器,初始为0

label:
    add eax, ebx     ; 累加被乘数到结果
    dec ecx          ; 乘数减1
    cmp ecx, 0
    jg label         ; 乘数>0时继续循环

    ; 注意:返回值需限制在0-255,超过的话取低8位
    mov ebx, eax     ; 将结果移到ebx作为返回值
    mov eax, 1
    int 0x80

方案二:直接使用x86的乘法指令mul

x86汇编提供了专门的乘法指令,效率更高:

global _start

_start:
    mov eax, 0x2     ; 被乘数(mul指令默认使用eax作为其中一个操作数)
    mov ebx, 0x12    ; 乘数
    mul ebx          ; 结果存储在edx:eax中(32位乘法,高32位在edx,低32位在eax)

    ; 取结果低8位作为返回值(如果需要完整结果,可通过其他方式输出)
    mov ebx, eax     ; 这里如果结果超过255,依然会被截断,若要查看完整结果可改用write系统调用
    mov eax, 1
    int 0x80

注意事项

  • 如果需要返回超过255的结果,不能依赖exit的返回值,应使用write系统调用将结果打印到终端,因为echo $?只能显示0-255的范围。
  • 32位乘法mul ebx会把结果存在edx:eax,如果结果超过32位,edx会存储高位部分。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:52:10