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

ARM汇编实现BCD逐位带进位加法及结果存储与溢出判断

嘿,我来帮你解决BCD码逐位带进位相加的问题,包括ARM Thumb汇编的实现细节!

一、BCD码逐位带进位相加的核心逻辑

BCD码是用4位二进制表示0-9的十进制数,直接做二进制加法会出现无效值(10-15,即0xA-0xF),必须修正才能得到正确的BCD结果。具体步骤如下:

  • 对每一组4位(一个BCD数位)执行带进位的二进制加法:当前位和 = 数1的当前位 + 数2的当前位 + 进位
  • 判断是否需要修正:如果当前位和的低4位>9,或者加法过程中产生了进位(即当前位和≥16),就给当前位和加6(0x06)。这是因为6的二进制是0110,加上后会把无效的10-15“推”到下一位进位,同时低位变成正确的BCD值(比如0xA+6=0x10,对应BCD的10,低位0,进位1)
  • 把修正后的当前位存入结果的对应位置,更新进位标志,继续处理下一位,直到所有位处理完成
  • 最后如果最高位处理完还有进位,说明结果溢出了(比如两个8位BCD数相加超过99999999)
二、ARM Thumb汇编实现

根据你的需求,我们实现一个函数:接收两个BCD数、结果存储地址,把结果写入RAM,返回结果地址和溢出标志(0无溢出,1溢出)。以下是完整代码:

AREA mydata, DATA, READWRITE
    SUM DCD 0       ; 示例结果存储位置,也可以传入自定义地址

AREA mycode, CODE, READONLY
    THUMB
    EXPORT __main
    EXPORT bcd_add   ; 导出BCD加法函数

NUM1 DCD 0x275      ; 示例BCD数:275
NUM2 DCD 0x189      ; 示例BCD数:189,相加结果应为0x464(464)

__main
    ; 调用bcd_add函数:R0=待加数1, R1=待加数2, R2=结果存储地址
    LDR R0, =NUM1
    LDR R0, [R0]
    LDR R1, =NUM2
    LDR R1, [R1]
    LDR R2, =SUM
    BL bcd_add
    ; 此时R0=结果地址,R1=溢出标志
    ; 可以在这里添加调试输出或其他逻辑
LOOP
    B LOOP           ; 死循环保持程序运行

; BCD加法函数
; 输入:R0=待加数1(BCD格式), R1=待加数2(BCD格式), R2=结果存储地址
; 输出:R0=结果存储地址, R1=溢出标志(0=无溢出,1=溢出)
bcd_add
    PUSH {R3-R7, LR} ; 保存寄存器现场
    MOV R3, #0       ; R3存储最终结果
    MOV R4, #8       ; 循环计数器:32位共8个BCD位(4位/位)
    MOVS R5, #0      ; 初始化进位标志C为0(MOVS会更新C)

bcd_loop
    ; 取出两个数的当前低4位
    AND R6, R0, #0x0F
    AND R7, R1, #0x0F
    ; 带进位相加:R6 = R6 + R7 + C
    ADCS R6, R6, R7
    ; 判断是否需要修正:低4位>9 或 有进位
    MOV R5, R6
    AND R5, R5, #0x0F
    CMP R5, #9
    BHI bcd_correct  ; 如果低4位>9,跳转到修正
    BCS bcd_correct  ; 如果有进位(C=1),跳转到修正
    B bcd_store      ; 不需要修正,直接存储

bcd_correct
    ; 加6修正,同时更新进位
    ADDCS R6, R6, #0x06

bcd_store
    ; 将当前位放到结果的对应位置(左移对应位数)
    MOV R5, #4
    MUL R5, R5, R4
    SUB R5, R5, #4
    LSL R6, R6, R5
    ORR R3, R3, R6
    ; 右移两个数,处理下一位
    LSR R0, R0, #4
    LSR R1, R1, #4
    ; 计数器减1,循环
    SUBS R4, R4, #1
    BNE bcd_loop

bcd_end
    ; 存储结果到RAM
    STR R3, [R2]
    ; 设置溢出标志:如果最终进位C=1,R1=1;否则0
    MOV R1, #0
    BCC bcd_no_overflow
    MOV R1, #1
bcd_no_overflow
    ; 返回结果地址
    MOV R0, R2
    POP {R3-R7, PC}  ; 恢复现场并返回
代码说明
  • 寄存器使用:用R3暂存结果,R4做循环计数器,R6/R7处理当前BCD位,R5辅助计算位移和判断
  • 修正逻辑:通过BHI(高于9)和BCS(有进位)判断是否需要加6,确保每一位都是有效的BCD值
  • 溢出判断:循环结束后检查进位标志C,若C=1说明最高位相加后仍有进位,结果超出32位BCD范围(最大99999999),返回溢出标志1
  • 调用约定:符合Thumb指令集的寄存器使用规范,保存了非volatile寄存器(R3-R7),返回值用R0(结果地址)和R1(溢出标志)

你可以修改NUM1和NUM2的值测试不同情况,比如NUM1=0x9999、NUM2=0x0002,结果会是0x00010001,溢出标志为1,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:24:13