操作环境:emu8086
设从BUF开始存放有若干带符号字节数(8位),将它们相加并将结果(超过一个字节范围)存放到字单元SUM中
1、8位有符号数在寄存器中是以补码形式存在的,最高的一位为符号位。0100 0000 → 64 , 1000 0000 → -128。
2、两8位有符号数相加时会出现溢出:两正数相加的和超过127,两负数相加的和低于-128。如:0100 0000 + 0100 0000 会溢出,1000 0000 + 1000 0000 会溢出。OF = 1。
3、判断是否进位,看的是两数作为无符号数相加时和是否超过255,比如: 1000 0000 + 1000 0000 会进位,CF = 1。
为了防止8位有符号数相加时溢出,采cbw(符号扩展指令)指令将8位有符号数扩展为16位有符号数,再进行相加,这样较好的解决了问题。
方案一是将8位扩展到16位从而避免了溢出的出现。方案二不采用将8位扩展到16位的方法。
我们把8位看作16位
1、将ax置0,将BUF中的第一个8位有符号数加入al中。
2、将BUF中的下一个8位有符号数与al相加。若BUF中的数已加完,转操作5
3、相加时,如果没有出现溢出,转到操作2;否则转操作4
4、如果是两负数相加造成的溢出,OF = 1,CF = 1,令ah减1,如果是两正数相加造成的溢出,OF = 1, CF = 0 令ah加1。转操作2
5、判断al中8位有符号数的符号位,若符号位为1,令ah减1,否则不做操作
最后ax中的数就是我们要求的结果。
流程图:
1、负数相加溢出时ah减1,正数相加溢出时ah加1。
2、加完以后,al符号位为1时,ah减1。
举个具体实例。
ps:多出的8位只是表示我们把8位看作16位。
将我们希望的结果减去计算机计算结果可得到0000 0001 0000 0000
所以0100 0000 + 0100 0000 = 计算机计算结果+ 0000 0001 0000 0000(8位有符号加数 + 8位有符号加数 = 16位有符号加数 + 看成16位的有符号加数(实际上是8位有符号数))。所以当两正数相加溢出时,令ah加0000 0001。
当两负数相加溢出时
ps:多出的8位只是表示我们把8位看作16位。
将我们希望的结果减去计算机计算结果可得到1111 1111 0000 0000。
所以1000 0000 + 1000 0000 = 计算机计算结果 + 1111 1111 0000 0000。所以当负数相加溢出时,令ah加上1111 1111,即:令ah减1。
最后我们要得到我们希望的结果。那么我们得用 (ah) 0000 0000加上 计算机计算结果。
这个时候如果al符号位为1,计算机计算结果为 1111 1111 (al)。我们让 1111 1111 (al) + (ah) 0000 0000相当于让ah减1。
将两8位有符号数的和,用两16位有符号数(其中一个实际上是8位有符号数)的和表示。
有些人可能不知道为什么最后要判断al的符号位,然后对ah进行减1.这么问的应该是没有理解我的思路。这道题的思路简单地说,就是,SUM = a(8位)+b(8位) = c(16位) + d(8位),如果要再加上一个e(8位),此时SUM = c(16位) + 【d(8位) +
e(8位)】 = c(16位) + 【f(16位) + g(8位)】 = (16位) + (8位)。我们得到的结果并不是一个直接结果,而是一个间接的结果,要得到直接结果,我们得把(16位) 和(8位)相加 方可得到最终的结果。 当(8位)的符号位为1时,我们把(8位)看成(1111 1111)(8位),此时两者相加,相当于令ah减1.
; multi-segment executable file template.
data segment
; add your data here!
buf db 40h, 40h,80h
count dw $-buf
num dw 0000h
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
; add your code here
lea si, buf ;将buf的首地址放到si中
xor ax, ax ;将和放入ax中,因此先将ax置0
mov cx, count ;将数组的长度放入cx中
lo:
add al, [si]
jo overflow ;溢出跳转
jmp next
overflow:
jc carry ;负数相加溢出跳转
inc ah
jmp next ;加下一个数
carry:
dec ah
next:
inc si
loop lo
test al,80h
jz setnum
dec ah
setnum:
lea si, num
mov [si], al
inc si
mov [si], ah
mov ax, 4c00h ; exit to operating system.
int 21h
ends
end start
以上为自己的拙见,如有不足,还请指正。