汇编8位有符号数相加

操作环境: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 

 

以上为自己的拙见,如有不足,还请指正。

  • 18
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值