汇编中如何实现符号幅度二进制数减法?以11110110和10101011为例
符号幅度二进制数的汇编减法实现及相关问题解答
一、符号幅度数的基本结构
符号幅度数(Sign-Magnitude)的最高位为符号位:
0代表正数,1代表负数- 剩余位是数值的绝对值(幅度部分)
以你给出的两个8位示例为例:
11110110:符号位1(负),幅度为1110110(十进制118)10101011:符号位1(负),幅度为0101011(十进制43)
二、符号位的提取方法
提取符号位无需使用SAL,直接通过位操作或标志位判断即可:
- 位掩码法:用
AND指令保留最高位,清零其他位; 假设数值存在AL寄存器中 MOV AH, AL AND AH, 080H ; AH仅保留符号位:0表示正,080H表示负 AND AL, 07FH ; AL仅保留幅度部分 - 标志位判断:执行
TEST AL, 080H后,若ZF=0则符号位为1(负),ZF=1则为0(正);也可直接读取SF(符号标志位),其值等于寄存器最高位(符号位)的拷贝。
三、SAL指令的正确使用及标志位判断
不要直接对完整的符号幅度数执行SAL,否则会移动符号位导致错误。正确流程是先分离符号位,仅对幅度部分执行SAL:
- 幅度是无符号的绝对值,左移时溢出会触发
CF(进位标志位),此时用JC指令判断溢出即可 JS指令是根据SF判断结果符号,对无符号的幅度来说没有意义,不要用它判断幅度左移的溢出
示例:对幅度1110110(存于AL)执行左移:
SAL AL, 1 ; 左移1位,等价于乘以2 JC OVERFLOW ; 若CF=1,说明幅度左移后超出7位范围(溢出)
四、符号幅度数的减法实现步骤
减法A - B可转化为A + (-B),再按符号幅度数的加法规则处理:
- 分离每个数的符号位和幅度:用上述位掩码法提取A的符号位
Sa、幅度Ma,B的符号位Sb、幅度Mb - 生成-B的表示:符号位取反(
Sb' = ~Sb),幅度保持Mb不变 - 分情况处理加法:
- 同号(Sa == Sb'):直接将幅度相加,符号位保持
Sa,需用JC判断幅度相加是否溢出 - 异号(Sa != Sb'):比较
Ma和Mb的大小,用大的幅度减小的,符号位取幅度较大的数的符号位
- 同号(Sa == Sb'):直接将幅度相加,符号位保持
针对你的示例的汇编代码(8086架构)
; 初始化:A=11110110(存于AL),B=10101011(存于BL) MOV AL, 0F6H ; 11110110 MOV BL, 0ABH ; 10101011 ; 提取A的符号位和幅度 MOV AH, AL AND AH, 080H ; Sa=080H(负) AND AL, 07FH ; Ma=76H(118) ; 提取B的符号位和幅度,再生成-B的符号位 MOV BH, BL AND BH, 080H ; Sb=080H(负) XOR BH, 080H ; -B的符号位Sb'=0(正) AND BL, 07FH ; Mb=2BH(43) ; 判断同号/异号 CMP AH, BH JE SAME_SIGN ; 异号情况:比较Ma和Mb CMP AL, BL JB B_LARGER ; Ma >= Mb,结果幅度=Ma-Mb,符号位=Sa SUB AL, BL MOV CL, AH JMP ASSEMBLE_RESULT B_LARGER: ; Mb > Ma,结果幅度=Mb-Ma,符号位=Sb' SUB BL, AL MOV AL, BL MOV CL, BH JMP ASSEMBLE_RESULT ; 同号情况:幅度相加 SAME_SIGN: ADD AL, BL JC OVERFLOW_HANDLER ; 处理幅度溢出逻辑 MOV CL, AH ; 组合符号位和幅度 ASSEMBLE_RESULT: OR AL, CL ; AL现在是最终结果:11001011(十进制-75) ; 溢出处理示例(可选) OVERFLOW_HANDLER: ; 此处添加溢出后的错误处理逻辑
五、关键注意事项
- 永远不要直接对完整的符号幅度数执行移位操作,必须先分离符号位和幅度
- 幅度是无符号数,判断其溢出用
CF和JC;符号位仅用来表示正负,不参与数值运算 - 减法转加法的思路能简化逻辑,避免直接处理减法的符号判断
内容的提问来源于stack exchange,提问作者Maryam Shomali
相关产品推荐
相关产品推荐

