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

如何在x86 Linux NASM汇编中实现两个不同长度数字的加法

汇编不同长度数字加法问题修复方案

我是汇编开发新手,目前在实现不同长度数字的基础计算时遇到了问题。我编写的加法代码仅支持3位及以内的等长数字加法运算,例如123+123可正常输出246,但计算12+123时会错误输出253。请问该如何修改代码使其支持不同长度数字的加法运算?


错误根源

  1. 输入的数字是高位在前、低位在后的字符串格式,原代码直接使用同一个偏移量读取两个数字的位,没有按最低位对齐;数字长度不一致时,短数字的高位会读取到缓冲区的换行符或垃圾值,导致计算错误
  2. 固定使用第二个数字的长度作为循环次数,没有取两个数字的最大长度作为循环边界
  3. sys_read返回的长度包含末尾的换行符,原代码没有正确剔除换行符计算有效数字长度
  4. 原代码最后缺少系统退出调用,执行结束会触发段错误

修复思路

  1. 读取输入后先减去1,得到剔除换行符的有效数字长度
  2. 取两个数字长度的最大值作为循环次数
  3. 给两个数字分别设置独立的索引指针,初始指向各自的最低位(字符串最后一个有效字符),超出自身长度的高位统一补0计算
  4. 循环结束后检查进位标志,有进位则补充到结果的最高位
  5. 补充系统退出逻辑避免崩溃

完整修复后代码

sys_exit equ 1
sys_read equ 3
sys_write equ 4
stdin equ 0
stdout equ 1

section .data
    newLine db 10
    cquestion db 'Enter a number: ', 0xa
    cqLen equ $ - cquestion
    answer db 'Your answer is: '
    aLen equ $ - answer

section .bss
    number1 resb 4
    number2 resb 4
    number1Len resd 1
    number2Len resd 1
    answ resb 8

%macro write_string 2
    mov eax, 4
    mov ebx, 1
    mov ecx, %1
    mov edx, %2
    int 0x80
%endmacro

section .text
global _start
_start:
    ; 读取第一个数字
    write_string cquestion, cqLen
    mov eax, sys_read
    mov ebx, stdin
    mov ecx, number1
    mov edx, 4
    int 0x80
    dec eax ; 剔除换行符长度
    mov [number1Len], eax

    ; 读取第二个数字
    write_string cquestion, cqLen
    mov eax, sys_read
    mov ebx, stdin
    mov ecx, number2
    mov edx, 4
    int 0x80
    dec eax ; 剔除换行符长度
    mov [number2Len], eax

    write_string answer, aLen

    ; 取两个数字的最大长度作为循环次数
    mov ecx, [number1Len]
    cmp ecx, [number2Len]
    jge .set_cycle_len
    mov ecx, [number2Len]
.set_cycle_len:
    push ecx ; 暂存长度用于后续输出

    ; 初始化各数字的索引指针,指向最低位
    mov esi, [number1Len]
    dec esi
    mov edi, [number2Len]
    dec edi
    mov edx, ecx
    dec edx ; 结果缓冲区的索引指针

    clc ; 清空进位标志
.add_loop:
    ; 读取第一个数字的当前位,超出长度则补0
    mov al, 0
    cmp esi, 0
    jl .get_num2
    mov al, [number1 + esi]
    sub al, 30h ; ASCII转数值
.get_num2:
    ; 读取第二个数字的当前位,超出长度则补0
    mov bl, 0
    cmp edi, 0
    jl .do_add
    mov bl, [number2 + edi]
    sub bl, 30h ; ASCII转数值
.do_add:
    adc al, bl
    aaa ; 非压缩BCD调整
    pushf ; 保存进位标志避免后续操作修改
    or al, 30h ; 数值转回ASCII
    popf ; 恢复进位标志

    mov [answ + edx], al
    dec esi
    dec edi
    dec edx
    loop .add_loop

    ; 处理最后的进位
    jnc .output_ans
    mov byte [answ + edx], '1'
    dec edx

.output_ans:
    ; 计算结果实际长度
    pop ecx
    cmp edx, 0
    jge .add_carry_len
    jmp .write_result
.add_carry_len:
    inc ecx
.write_result:
    mov eax, sys_write
    mov ebx, stdout
    lea ecx, [answ + edx + 1]
    mov edx, ecx
    int 0x80
    
    ; 输出换行
    mov eax, sys_write
    mov ebx, stdout
    mov ecx, newLine
    mov edx, 1
    int 0x80

    ; 正常退出
    mov eax, sys_exit
    mov ebx, 0
    int 0x80

说明

  • 原代码中pushf、popf的作用是保存进位标志,避免or al,30h操作修改标志位导致后续adc计算错误
  • aaa是非压缩BCD调整指令,用于确保加法后的低4位是0~9的有效数字
  • 修复后支持3位及以内任意长度数字的加法,测试12+123可正常输出135

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:06:08