LC-3汇编实现BMI公式:无MUL/DIV指令下的除法与乘法问题
LC-3汇编实现BMI计算公式问题解答
问题描述
需要实现BMI计算公式:BMI = (WEIGHT(lb) / HEIGHT(in)²) * 703,测试参数为体重196磅、身高76英寸,预期结果为23.855263...。当前遇到的问题:
- 除法仅能得到整数商和余数,不清楚如何处理小数部分以获得精确结果
- 所用软件不支持MUL和DIV指令,不知道如何实现乘以703的操作
- 附当前除法代码:
DIVISION ;R0 ;R1 ;R2 -> DIVIDEND / HEIGHT**2 ;R3 -> DIVISOR / WEIGHT ;R4 -> QUOTIENT ;R5 -> CHECKER ;R6 ;R7 JSR CLEAR_REG LD R1 DIVIDND ; HEIGHT -> 5776 LDR R2, R1, #0 AND R1, R1, #0 LD R1 INPUT_W ; WEIGHT -> 196 LDR R3, R1, #0 NOT R3, R3 ADD R3, R3, #1 ADD R5, R2, #0 LOOP ADD R5, R5, R3 BRn SAVE_DIVIDE ADD R2, R2, R3 ADD R4, R4, #1 BRp LOOP SAVE_DIVIDE LD R1, QUOTIENT ;-> x5050 STR R4, R1, #0 AND R1, R1, #0 LD R1, REMAINDER ; ->x6000 STR R2, R1, #0 BR TERMINATE
问题解决步骤
1. 修正除法参数逻辑
当前代码的被除数和除数搞反了:BMI公式是体重除以身高平方,即被除数应为体重196,除数应为身高平方5776。原代码把5776作为被除数、196作为除数,会导致商为0,完全不符合需求,需先调换两者的角色。
2. 优化计算顺序减少精度损失
直接先做除法再乘法会丢失小数部分,建议调整公式顺序为:BMI = (WEIGHT * 703) / HEIGHT²,先计算体重与703的乘积,再除以身高平方,能最大程度保留精度。
3. 无MUL指令下实现乘法
用加法模拟乘法,有两种实现方式:
方式1:重复加法(简单易写)
; 功能:计算R0(被乘数)* R1(乘数),结果存R2 MUL_ADD AND R2, R2, #0 ; 初始化结果寄存器 MUL_LOOP ADD R2, R2, R0 ; 累加被乘数 ADD R1, R1, #-1 ; 乘数减1 BRp MUL_LOOP ; 乘数大于0则继续循环 RET
调用时,将R0设为196,R1设为703,执行后R2即为196*703=137788。
方式2:移位加法(效率更高)
利用二进制分解乘数,703的二进制是1010111111,对应512+128+64+16+8+4+2+1,通过移位+加法快速计算:
; 功能:计算196*703,结果存R2 MUL_SHIFT AND R2, R2, #0 LD R0, INPUT_W ; R0=196 ; 加1*196 ADD R2, R2, R0 ; 加2*196(左移1位) ADD R0, R0, R0 ADD R2, R2, R0 ; 加4*196(左移1位) ADD R0, R0, R0 ADD R2, R2, R0 ; 加8*196(左移1位) ADD R0, R0, R0 ADD R2, R2, R0 ; 加16*196(左移1位) ADD R0, R0, R0 ADD R2, R2, R0 ; 加64*196(左移2位) ADD R0, R0, R0 ADD R0, R0, R0 ADD R2, R2, R0 ; 加128*196(左移1位) ADD R0, R0, R0 ADD R2, R2, R0 ; 加512*196(左移2位) ADD R0, R0, R0 ADD R0, R0, R0 ADD R2, R2, R0 RET
4. 修正后的除法逻辑
基于调整后的计算顺序,用减法循环实现除法,得到整数商和余数:
DIVISION_FIXED JSR CLEAR_REG ; 假设R2已通过乘法得到196*703=137788 LD R3, HEIGHT_SQ ; R3=5776(身高平方) NOT R3, R3 ADD R3, R3, #1 ; 取除数的负数,用于减法 AND R4, R4, #0 ; R4初始化商为0 ADD R5, R2, #0 ; R5存临时被除数 LOOP_FIXED ADD R5, R5, R3 BRn SAVE_DIVIDE_FIXED ADD R2, R2, R3 ADD R4, R4, #1 BRp LOOP_FIXED SAVE_DIVIDE_FIXED LD R1, QUOTIENT STR R4, R1, #0 ; 商为23,对应BMI整数部分 LD R1, REMAINDER STR R2, R1, #0 ; 余数为137788-23*5776=4940 BR TERMINATE ; 数据定义 HEIGHT_SQ .FILL #5776 INPUT_W .FILL #196 QUOTIENT .FILL x5050 REMAINDER .FILL x6000
5. 计算小数部分(获取精确值)
如果需要得到像预期的23.855...这样的小数结果,可通过余数迭代计算:
- 余数4940 ×10 = 49400,除以5776得商8(对应第一位小数),余数49400-5776×8=3192
- 余数3192 ×10 =31920,除以5776得商5(对应第二位小数),余数31920-5776×5=3040
- 重复此过程,直到达到所需精度
内容的提问来源于stack exchange,提问作者Carson Virgin
相关产品推荐
相关产品推荐

