ATmega328汇编:仅用加法指令实现8位乘8位得16位结果求助
ATmega328汇编乘法代码MSB计算错误修正
我是大学汇编新手,用Atmel Studio模拟ATmega328架构,需要用add/adc指令实现两个8位数字(0b00111010和0b01010101)的乘法,得到16位结果。现在GPT生成的代码只能正确计算结果的LSB,MSB计算错误,怀疑问题出在adc r19, r1这一行,请求帮忙排查修正。
原代码:
; Input r16 (00111010), r17 (01010101) ; Output r18:r19 (risultato) ldi r16, 0b00111010 ; Load first number in r16 ldi r17, 0b01010101 ; Load second number in r17 ldi r18, 0 ; Initialize LSB's resoult to 0 ldi r19, 0 ; Initialize MSB's resoult to 0 ldi r20, 8 ; 8 bit counter multiply_loop: lsr r17 ; Shift to dx the first number brcc no_add ; Skip if the LSB is 0 add r18, r16 ; Add first number to the lower part of the resoult adc r19, r1 ; Add carry to the higher part of the resoult no_add: lsl r16 ; Left shift of first number dec r20 ; Decrease counter brne multiply_loop ; Repeat cycle until counter is 0 ; Final resoult in r18:r19
错误原因分析
- 被乘数存储位数不足:原代码仅用8位寄存器
r16存储被乘数,左移超过7位后,溢出的高位会被丢弃。例如计算58×64时,实际值为3712(十六进制0xE80),但r16只能存储低8位0x80,高位0xE丢失,导致相加时仅加了低8位,MSB计算缺失。 - 高位相加逻辑不完整:
adc r19, r1仅处理了add r18, r16产生的进位,但没有将被乘数移位后的高位部分加到结果MSB中,这也是MSB错误的直接原因。
修正后的代码
; Input r16 (00111010), r17 (01010101) ; Output r18:r19 (结果,r19为MSB,r18为LSB) ldi r16, 0b00111010 ; 被乘数低8位 ldi r15, 0 ; 被乘数高8位,初始化为0 ldi r17, 0b01010101 ; 乘数 ldi r18, 0 ; 初始化结果低8位 ldi r19, 0 ; 初始化结果高8位 ldi r20, 8 ; 8位循环计数器 multiply_loop: lsr r17 ; 乘数右移,LSB移入进位标志C brcc no_add ; 若C=0(原LSB为0),跳过相加步骤 add r18, r16 ; 结果低8位 += 被乘数低8位 adc r19, r15 ; 结果高8位 += 被乘数高8位 + 上一步的进位 no_add: lsl r16 ; 被乘数低8位左移,溢出位移入C adc r15, r1 ; 被乘数高8位 += 0 + C,完成16位整体左移 dec r20 ; 计数器减1 brne multiply_loop ; 计数器不为0则继续循环 ; 最终结果存储在r19:r18中
修正说明
- 用16位寄存器对
r15:r16存储被乘数,通过lsl r16+adc r15, r1实现完整的16位左移,保留移位后的所有高位。 - 相加时使用
add r18, r16+adc r19, r15,将16位的被乘数移位值完整加到结果寄存器对中,同时处理进位。 - 修正后代码执行结果为
r19=0x13、r18=0x42,对应十进制4930,与58×85的正确结果一致。
内容的提问来源于stack exchange,提问作者Alessandro Pascale
相关产品推荐
相关产品推荐

