2

所以如果我想添加两个无符号整数,我会简单地写

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

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

4

2 回答 2

3

首先是错误:

  • 它从仅分配 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 状态标志pop ax它发送到通用寄存器,并检查任何单个位。

于 2012-11-21T14:41:16.550 回答
1

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

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

在这种情况下,加法的结果将为正(加 2 个正数将给出正结果),并且 CPU 的符号标志将正确显示将 24 位数字相加的结果为正。CPU 的进位标志和溢出标志也将正确(并且都将被清除);因此您可以使用js,jg和之类的指令正常测试它们jo(即使您知道它们都很清楚并且条件分支可以被删除或转换为jmp)。CPU 的奇偶校验标志和零标志可能是错误的(例如,零标志只会说明最高 8 位是否全为零,而不会告诉您整个 24 位是否全为零)。

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

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

于 2012-11-21T15:11:53.860 回答