AVR汇编SUB指令工作原理及8位减法运算规则解析
AVR汇编SUB指令核心工作逻辑
AVR架构的SUB是8位通用寄存器减法指令,硬件层面没有独立的减法运算电路,实现逻辑和通用CPU减法方案一致:对减数做8位位宽下的补码转换(按位取反后加1),再和被减数做加法运算,高于8位的进位直接截断,最终结果写入目标寄存器,同时根据运算过程更新状态寄存器SREG的对应标志位。
以1 - 2运算为例:
- 被减数1的8位二进制值为
0b00000001,减数2的8位二进制值为0b00000010 - 对减数取8位补码:按位取反得
0b11111101,加1后为0b11111110 - 两值相加:
0b00000001 + 0b11111110 = 0b11111111
最终寄存器存储的就是0b11111111,也就是-1的8位二进制补码,没有其他特殊存储形式。这次运算因为被减数小于减数,会产生借位,SREG的C标志位置1;结果最高位为1,N标志位置1;无零值、无有符号溢出,Z、V标志位为0。
大于128数值场景的运算说明
首先纠正一个认知偏差:不存在“补码表示把可计数范围减半”的说法。8位二进制位的位宽固定,能表示256种状态:
- 按无符号数解读,范围是0~255
- 按有符号补码解读,范围是-128~127
硬件执行SUB指令时完全不关心程序员对数值的解读规则,只按固定的位运算逻辑计算,最终通过不同的标志位给程序员提供判断依据:做无符号运算时看C标志判断是否有借位/溢出,做有符号运算时看V标志判断是否溢出。
以2 - 255运算为例,完整位运算过程如下:
- 两个操作数的8位寄存器存储值:被减数2为
0b00000010,减数255为0b11111111(注意255作为8位无符号值存储时不需要9位,本身就是全1的8位值;如果按有符号补码解读,这个值对应-1) - 对减数取8位补码:按位取反得
0b00000000,加1后为0b00000001——这里所有操作都在8位位宽内完成,取补码过程产生的高位进位直接丢弃,根本不需要9位存储 - 两值相加:
0b00000010 + 0b00000001 = 0b00000011,也就是十进制值3,推导的这个运算过程是完全正确的。
关于溢出判断要分场景看:
- 按无符号数运算:2减255的理论结果是-253,超出8位无符号0~255的表示范围,运算产生借位,C标志位置1,此时结果3是模256的运算结果(即2 - 255 + 256 = 3)
- 按有符号补码运算:实际是2 - (-1) = 3,结果3在-128~127的有符号表示范围内,不会触发有符号溢出,V标志位为0。
之前认为255的补码需要9位,本质是把255当成了8位有符号正数来计算补码——但8位有符号正数的最大值就是127,255本身就不可能作为8位有符号正数存在,自然不存在需要9位存补码的问题。
内容的提问来源于stack exchange,提问作者Tzanker
相关产品推荐
相关产品推荐

