📜  8086程序减去两个带有或不带有借位的16位数字(1)

📅  最后修改于: 2023-12-03 14:38:54.344000             🧑  作者: Mango

8086程序减去两个带有或不带有借位的16位数字

在这个项目中,我们将学习如何使用8086汇编语言编写程序来减去两个带有或不带有借位的16位数字。我们将介绍如何处理进位和溢出,以及如何从用户那里接收并打印结果。

以下是我们要编写的程序的主要步骤:

  1. 接收两个16位数字(可能带有借位)
  2. 减去第二个数字从第一个数字
  3. 处理结果中的进位和溢出
  4. 打印结果

下面我们将逐步进行每个步骤的说明。

1. 接收两个16位数字

首先,我们需要能够从用户那里接收两个16位数字。我们将使用int 21h中的0Ah功能来读取用户的输入。在这里,我们使用'$'字符表示从标准输入设备(stdin)中读取字符串的结束标志,该设备的文件句柄是0。以下是输入两个数字的汇编代码:

mov  ah, 0ah   ; 设置输入子功能
lea  dx, num1  ; 存储第一个字符的偏移地址
int  21h       ; 读取第一个数字

lea  dx, num2  ; 存储第二个字符的偏移地址
int  21h       ; 读取第二个数字

在以上代码中,我们首先将输入子功能设置为0Ah,然后使用$num1和$num2来存储两个数字。我们使用lea指令来将变量的地址存储在dx寄存器中。

2. 减去第二个数字从第一个数字

接下来,我们需要将第一个数字减去第二个数字。我们将使用sub指令来完成此操作。以下是我们需要的汇编代码:

mov  ax, num1  ; 将第一个数字存储在ax中
sub  ax, num2  ; 从第一个数字中减去第二个数字
mov  result, ax ; 将结果存储在result变量中

在以上代码中,我们首先将第一个数字从num1变量中移动到ax寄存器中,然后使用sub指令将第二个数字从ax寄存器中减去。最后,我们将结果从ax寄存器中移动到result变量中。

3. 处理结果中的进位和溢出

执行减法可能导致进位或溢出。我们需要测试结果并在必要时进行适当的处理。以下是我们需要的汇编代码:

mov  bx, result     ; 将结果存储在bx寄存器中
mov  cx, 0          ; 初始化cx计数器为0
push bx             ; 压入结果以备后用
cmp  bx, 0          ; 检查结果是否为0
jge  check_overflow ; 如果结果不是负数,则检查溢出

; 溢出时调用处理器
mov  ah, 9
lea  dx, msg_overflow
int  21h
jmp  exit_program

check_overflow:     ; 检查是否有溢出
; 检查结果中是否有进位,如果有则将标志设置为1
mov  ax, result
and  ax, 8000h
jnz  set_carry

; 检查结果是否小于0,如果是则将标志设置为1
test result, 0FFFFh
jz   exit_check

set_carry:          ; 如果有进位,将进位标志设置为1
mov  carry_flag, 1

exit_check:         ; 释放结果并退出
pop  bx

在以上代码中,我们将结果存储在bx寄存器中,并将标志cx计数器初始化为0。我们首先测试结果是否为负数,如果是,则表示有溢出发生。在这种情况下,我们将显示一条消息来告诉用户溢出已经发生,并退出程序。如果结果不为负数,则我们将测试结果是否有进位。如果有,则我们将进位标志设置为1。

最后,我们释放结果并退出。

4. 打印结果

最后一步是将结果打印到屏幕上。我们将使用int 21h中的09h功能来打印结果。以下是我们需要的汇编代码:

; 打印结果
mov  ah, 2
mov  dl, '-'
int  21h

cmp  carry_flag, 1 ; 检查进位标志
jz   print_result  ; 如果没有进位,则立即打印结果

; 如果有进位,则先将结果加1(即補码加1),然后打印
not  result
mov  ax, 1
add  result, ax
print_result:
; 将结果转换为字符串
mov  bx, offset buffer
call word ptr [to_hex]

; 打印结果
lea  dx, buffer
int  21h

exit_program:

在以上代码中,我们首先将'-'字符打印到屏幕上,然后测试进位标志。如果没有进位,则可以立即打印结果。如果有进位,则我们将结果加1(即取補数加1),然后将结果转换为一个字符串,并打印该字符串。

到这里,我们已经完成了这个程序的所有步骤。以下是完整的8086汇编代码:

.model small
.stack 100h

.data
num1           db 0
num2           db 0
result         dw 0
carry_flag     db 0
msg_overflow   db 'Overflow occurred', 0
buffer         db 10 dup('$')

.code
main proc
; 输入第一个数字
mov  ah, 0ah
lea  dx, num1
int  21h

; 输入第二个数字
lea  dx, num2
int  21h 

; 减去第二个数字从第一个数字
mov  ax, num1
sub  ax, num2
mov  result, ax

; 处理进位和溢出
mov  bx, result
mov  cx, 0
push bx
cmp  bx, 0
jge  check_overflow

; 溢出时调用处理器
mov  ah, 9
lea  dx, msg_overflow
int  21h
jmp  exit_program

check_overflow: ; 检查是否有溢出
; 检查结果中是否有进位,如果有则将标志设置为1
mov  ax, result
and  ax, 8000h
jnz  set_carry

; 检查结果是否小于0,如果是则将标志设置为1
test result, 0FFFFh
jz   exit_check

set_carry:      ; 如果有进位,将进位标志设置为1
mov  carry_flag, 1

exit_check:     ; 释放结果并退出
pop  bx

; 打印结果
mov  ah, 2
mov  dl, '-'
int  21h

cmp  carry_flag, 1 ; 检查进位标志
jz   print_result  ; 如果没有进位,则立即打印结果

; 如果有进位,则先将结果加1(即補码加1),然后打印
not  result
mov  ax, 1
add  result, ax

print_result:
; 将结果转换为字符串
mov  bx, offset buffer
call word ptr [to_hex]

; 打印结果
lea  dx, buffer
int  21h

exit_program:
mov  ah, 4ch
mov  al, 0
int  21h
main endp

to_hex proc near
; 将16位十进制数转换为十六进制字符串
push bp
mov  bp, sp
push bx
push dx
push cx

mov  bx, [bp + 4]
mov  dx, 1000h
mov  cx, 4

convert_loop:
; 将每个4位数转换为16进制数字
mov  ax, bx
and  ax, dx
shr  ax, cl
cmp  ax, 9
jbe  less_than_9
add  al, 7
less_than_9:
add  al, 30h

mov  [bx], al
add  bx, 1
shl  dx, 4
sub  cx, 4
jnz  convert_loop

pop  cx
pop  dx
pop  bx
pop  bp
ret
to_hex endp
end main

请注意,这只是一个示例程序,可以根据不同的需求进行修改和改进。

Enjoy coding!