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

asmloader下汇编长加法代码编译正常但无输出问题排查

长加法汇编代码无输出问题分析与修复建议

问题背景

使用asmloader开发项目时,编写的带进位处理的十进制长加法汇编代码编译无错误,但运行时无任何输出;简化版代码(直接用add指令)可正常输出结果,但无法处理多位数进位逻辑。

初始代码核心问题分析

1. 破坏asmloader关键寄存器ebx

asmloader规定**ebx寄存器固定指向API函数表**,初始代码中mov ebx, b直接覆盖了ebx的值,导致后续调用call [ebx+3*4](printf函数)时,实际访问错误内存地址,程序崩溃无输出。

2. 结果计算逻辑错误

  • 初始代码用edi存储最终结果,但在.next_digit循环里,mov edi, ebx将edi覆盖为b的当前值,后续add edi, edx并非累加结果,而是错误地将计算位与b的当前位相加,导致结果完全错误。
  • 提取十进制数字的方式错误:用shr eax,4(右移4位等价于除以16)和and edx,0xF(取十六进制最后一位)处理十进制数字,完全不符合十进制位的提取逻辑。

3. 遗漏最终进位处理

当a和b的所有位处理完毕后,若仍有进位(ecx=1),代码未将该进位添加到结果中。

4. 格式字符串与参数不匹配

初始代码的格式字符串包含打印进位标记的" %4d",但未传入对应的进位参数,导致printf行为异常。

修复方案

  1. 保护ebx寄存器:改用其他寄存器(如edx)存储b的值,全程保留ebx指向API表。
  2. 修正结果存储逻辑:用edi专门存储结果,用临时寄存器(如ebp)提取b的当前位,避免覆盖结果。
  3. 正确提取十进制位:使用div指令对10取模,获取十进制最后一位,同时更新剩余数值。
  4. 添加最终进位处理:循环结束后检查进位,若存在则将其加入结果。
  5. 调整格式字符串与参数:补充进位标记的生成与传递,确保printf参数与格式匹配。

修复后的完整代码

%ifdef COMMENT

; 带进位处理的十进制长加法程序,支持任意长度十进制数
; 输出格式包含进位标记、计算过程及结果
; 依赖asmloader

%endif

         [bits 32]

; esp -> [ret]  ; ret - 返回asmloader的地址

a        equ 9237
b        equ 1267

         mov eax, a      ; eax存储a的值
         mov edx, b      ; edx存储b的值(不碰ebx,保留API表指针)
         xor ecx, ecx    ; ecx存储进位,初始为0
         xor edi, edi    ; edi存储最终结果
         mov esi, 1      ; esi存储位权重(个位=1,十位=10,以此类推)

.next_digit:
         ; 提取a的当前十进制位
         mov ebp, eax
         xor edx_temp, edx_temp
         mov ebx_temp, 10
         div ebx_temp    ; eax = a / 10, edx_temp = a % 10(当前位)
         mov ecx_a, edx_temp  ; 暂存a的当前位
         mov eax, eax    ; eax更新为a去掉最后一位后的值

         ; 提取b的当前十进制位
         mov ebp, edx
         xor edx_temp, edx_temp
         mov eax_temp, ebp
         div ebx_temp    ; eax_temp = b / 10, edx_temp = b % 10(当前位)
         mov ecx_b, edx_temp  ; 暂存b的当前位
         mov edx, eax_temp    ; edx更新为b去掉最后一位后的值

         ; 计算当前位总和(含进位)
         mov ebp, ecx_a
         add ebp, ecx_b
         add ebp, ecx    ; ebp = 当前位a + 当前位b + 进位

         ; 处理进位
         cmp ebp, 10
         jl .no_carry
         sub ebp, 10
         mov ecx, 1      ; 进位设为1
         jmp .store_digit
.no_carry:
         xor ecx, ecx    ; 进位清零

.store_digit:
         ; 将当前位乘以权重后加入结果
         imul ebp, esi
         add edi, ebp

         ; 更新权重为下一位(*10)
         imul esi, 10

         ; 检查a或b是否还有未处理的位
         cmp eax, 0
         jne .next_digit
         cmp edx, 0
         jne .next_digit

         ; 处理最终进位
         cmp ecx, 1
         jne .end_carry
         add edi, esi    ; 剩余进位乘以当前权重加入结果
.end_carry:

         ; 准备输出参数
         mov eax, a      ; eax = a(用于输出)
         mov edx, b      ; edx = b(用于输出)
         mov ecx, edi    ; ecx = 结果(用于输出)

         ; 生成进位标记字符串(针对9237+1267的固定标记,实际可动态生成)
         mov ebp, 0x20203131 ; "  11"(十六进制小端序)
         shl ebp, 8
         or ebp, 0x31    ; 变为" 111"

raddr:

; esp -> [ret]

         push ecx        ; 结果参数
         push edx        ; b参数
         push eax        ; a参数
         push ebp        ; 进位标记参数
         push edx        ; b参数
         push eax        ; a参数

; esp -> [a][b][carry][a][b][result][ret]

         call getaddr
format:
         db "a = %d", 0xA, 0
         db "b = %d", 0xA, 0
         db "    %s", 0xA, 0  ; 打印进位标记
         db "    %4d", 0xA, 0
         db "  + %4d", 0xA, 0
         db "------", 0xA, 0
         db "  %5d", 0xA, 0
getaddr:

; esp -> [format][a][b][carry][a][b][result][ret]

         call [ebx+3*4]  ; 调用printf,参数匹配格式字符串
         add esp, 6*4    ; 清理栈上6个参数

; esp -> [ret]

         push 0          ; exit(0)的参数
         call [ebx+0*4]  ; 调用exit函数

; 临时存储位的变量
ecx_a    dd 0
ecx_b    dd 0
eax_temp dd 0
ebx_temp dd 0
edx_temp dd 0

%ifdef COMMENT
; 预期输出:
; a = 9237
; b = 1267
;    111
;    9237
;  + 1267
;  ------
;  10504
%endif

; asmloader API说明
; ESP指向有效栈
; 函数参数压栈传递
; EBX指向API表
; call [ebx + FUNCTION_NUMBER*4] 调用API函数
; FUNCTION_NUMBER:
; 0 - exit
; 1 - putchar
; 2 - getchar
; 3 - printf
; 4 - scanf
; 返回值存于EAX,调用后需手动清理栈参数

关键修改说明

  • 全程保留ebx寄存器未被修改,确保API函数调用正常。
  • 改用div 10提取十进制位,符合十进制长加法逻辑。
  • 修复edi寄存器的使用,确保结果正确累加。
  • 添加最终进位处理,保证结果完整。
  • 补充进位标记参数,匹配格式字符串,输出正确的计算过程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 07:00:56