如何在Assembly 8086中使用带有SIGNED整数的ADD指令?

时间:2012-11-21 13:47:43

标签: assembly add x86-16

因此,如果我想添加两个无符号整数,我只需编写

dat1 db ff
dat2 db ff
res dw ?

并在代码段中:

mov ax, dat1
add ax, dat2
mov dl,0
adc dl,0 ;initialize the contents of dl and use it to store the carry flag
mov byte ptr res, ax
mov byte ptr res+1, dl

但是,如果我想添加两个SIGNED整数,代码会是什么样子?我可以以某种方式访问​​标志旗吗?

2 个答案:

答案 0 :(得分:2)

首先是错误:

  • 它从仅分配8位的变量中读取16位。
  • 写地址res + 1也没有意义(但是res + 2)。
  • 也试图写mov byte ptr addr, ax应该失败
    • 应为mov word ptr res, ax

对第一个问题的回答是:没什么特别的 add ax, bx并不关心他们是否签名。检查状态寄存器时会出现有趣的部分。你有进位标志标志标志溢出标志。 (以及25个以上不相关的标志)。作为旁注:如果carry_flag!= sign_flag 用于相同符号的加数,则设置溢出标志。这意味着两个负数的加/减可以解释为正数,或者添加两个正数可以解释为负数。对于不同符号(3)+( - 2)的加数,不会发生溢出。

可以通过比较和分支来访问签名标志:

add ax,bx  
jns process_unsigned   // or
js process_signed  

或者如果您担心将寄存器的符号位转移到其他地方,您可以   - mov cl, 16; sar ax, cl; //将符号位移到单词ax 上   - add ax, ax shl ax,1)//将符号位从AX的“左”侧移到进位

此外,可以pushf status flagpop ax将其发送到通用寄存器,并检查任何单个位。

答案 1 :(得分:1)

忽略示例代码中的错误(请参阅Aki的回答)......

如果您尝试添加一对24位数字;那么第一个24位数字是正数,因为这个数字的符号位在你进入DL的0的第7位(在mov dl,0指令中)。第二个24位数也是正数,因为它的符号位在您添加到DL的0的第7位(在adc dl,0指令中)。

在这种情况下,添加的结果将为正(添加2个正数将给出正结果),并且CPU的符号标志将正确显示添加24位数的结果为正。 CPU的进位标志和溢出标志也是正确的(并且都是清晰的);因此,您可以使用jsjgjo之类的说明正常测试它们(即使您知道它们都已清除,条件分支也可以删除或转换为{{1 }})。 CPU的奇偶校验标志和零标志可能是错误的(例如,零标志仅表示最高的8位是否全为零,并且不会告诉您整个24位是否都为零)。

但是,如果您认为您正在添加带符号的16位数字(并尝试获得24位结果),那么您做错了会得到错误的结果。要添加带符号的16位数字并获得24位结果,您必须对16位数字进行“符号扩展”以使它们成为24位而不是“零扩展”这些数字。例如,16位(负)数0xCDEF应变为24位(负)数0xFFCDEF而不是24位(正)数0x00CDEF。

另一种选择是像往常一样添加16位数字,然后将结果符号扩展为24位。这仅在16位加法不溢出时有效,如果加法不能溢出,则开始时不需要24位结果。