📜  8086程序查找两个数字的GCD并打印GCD(1)

📅  最后修改于: 2023-12-03 15:29:13.070000             🧑  作者: Mango

8086程序查找两个数字的GCD并打印GCD

在计算机科学中,最大公约数(GCD)是两个或多个整数的最大公约数。在本篇文章中,我们将介绍如何使用8086汇编语言编写一个程序,查找两个数字的GCD并打印GCD。

程序设计思路

该程序设计思路如下:

  1. 获取用户输入的两个数字
  2. 判断两个数字之间的大小,确保大数在前,小数在后
  3. 计算两个数的余数
  4. 如果余数为0,则说明当前的除数就是最大公因数,程序结束
  5. 如果余数不为0,则交换除数和被除数,继续进行除法运算,回到步骤3.
代码实现

下面是使用8086汇编语言编写的程序,实现了上述的程序设计思路。

.MODEL SMALL
.STACK 100H
.DATA
MSG1 DB 'Enter first number: $'
MSG2 DB 'Enter second number: $'
MSG3 DB 'The GCD is: $'
NUMBER1 DW ?
NUMBER2 DW ?
REM DW ?
DIV DW ?
.CODE
MAIN PROC
    MOV AX, @DATA
    MOV DS, AX ; 初始化数据段

    ; 输入第一个数字
    MOV AH, 9
    MOV DX, OFFSET MSG1
    INT 21H
    MOV AH, 1
    INT 21H
    SUB AL, 30H ; ASCII转换
    MOV NUMBER1, AX

    ; 输入第二个数字
    MOV AH, 9
    MOV DX, OFFSET MSG2
    INT 21H
    MOV AH, 1
    INT 21H
    SUB AL, 30H ; ASCII转换
    MOV NUMBER2, AX

    ; 确保NUMBER1 > NUMBER2
    MOV AX, NUMBER1
    CMP AX, NUMBER2
    JGE NUMBER1_GREATER
    XCHG AX, NUMBER2
    MOV NUMBER1, AX
NUMBER1_GREATER:


    ; 计算NUMBER1 % NUMBER2
    MOV AX, NUMBER1
    MOV BX, NUMBER2
    MOV DX, 0 ; 存储余数
REPEAT:
    DIV BX
    MOV DIV, AX ; 存储商
    MOV REM, DX ; 存储余数
    CMP DX, 0 ; 如果余数为0,结束
    JE END_LOOP
    MOV AX, BX
    MOV BX, DX ; 更新AX和BX的值
    JMP REPEAT ; 回到REPEAT继续运行

END_LOOP:
    ; 打印结果
    MOV AH, 9
    MOV DX, OFFSET MSG3
    INT 21H

    MOV AX, BX ; 最大公因数存储在BX中
    ADD AX, 30H ; 转换为ASCII码
    MOV DL, AL
    MOV AH, 2
    INT 21H

    MOV AH, 4CH
    INT 21H ; 程序结束

MAIN ENDP
END MAIN
代码解释
.MODEL SMALL

这行指令告诉编译器,我们正在使用的是小系统(16位),并且需要把代码段和数据段分别存储在物理内存的不同位置上。

.STACK 100H

在程序运行时,需要保存和恢复处理器的状态信息,如程序计数器、栈指针等等。堆栈(stack)就是用来保存和恢复这些信息的一种数据结构。这行指令告诉编译器,我们需要一个大小为100H的堆栈空间。

.DATA

这行指令表示接下来的变量都应该存储在数据段中,并且在程序编译时就已经确定了大小。

MSG1 DB 'Enter first number: $'

这行指令定义了一个字符串变量 MSG1,其中 DB 表示该变量是一个字节型变量。'$' 表示该字符串的结束符。我们可以通过将偏移地址传递给INT 21H 的AH=9,来显示这个消息。

.CODE

这行指令表示接下来的代码都应该存储在代码段中,并且在程序运行时需要执行。

MAIN PROC

这行指令表示我们定义了一个名为MAIN的过程(procedure),其中包含了我们的程序代码。其中,PROC表示我们正在定义一个过程,而ENDP表示我们定义一个过程的结束。我们的程序从这里开始执行。

MOV AX, @DATA

这行指令将数据段的段地址加载到AX寄存器中。在小程序中,AX寄存器通常用于存储地址或临时数据等。

MOV DS, AX

接下来这条指令,将AX寄存器中的值加载到DS寄存器中。DS寄存器是段选择寄存器之一,用于存储当前数据段的段地址。

MOV AH, 9

这行指令将寄存器AH的值设置为9,这个操作码是调用中断21H的一部分,用于在屏幕上输出字符串。

MOV DX, OFFSET MSG1

中断21H需要一个指向要输出的字符串的指针,而DX寄存器是我们用来存储这个指针的寄存器。此处使用了OFFSET操作符,用来返回字符串MSG1的偏移地址。

INT 21H

这行代码触发中断21H,用于在屏幕上输出MSG1的文本。

MOV AH, 1
INT 21H
SUB AL, 30H
MOV NUMBER1, AX

这几行代码用于获取用户输入的数字并将其存储在变量NUMBER1中。INT 21H被调用两次,第一次输出一个带有光标的“_”(表示需要用户输入),然后等待用户输入的数字(asynchronous)。SUB指令将数字字符的ASCII码值转换为十进制数字值,并将其存储在寄存器AL中。最后,我们将AX寄存器的值存储在变量NUMBER1中。

ADD AX, 30H ; 转换为ASCII码
MOV DL, AL
MOV AH, 2
INT 21H

这几行代码用于在屏幕上显示变量的值。我们将寄存器AX中存储的10进制数字转换为ASCII码,并将其存储在DL寄存器中。接着将调用INT 21H中断,用于在屏幕上输出该数字。

运行程序

使用汇编器(如MASM)将程序编译成二进制代码之后,以系统管理员权限在DOS系统中运行该程序。程序将首先提示用户输入两个数字,然后输出这两个数字的GCD。