判断质数汇编程序编写

Posted by farmer3-c on January 12, 2026

以下面的代码为例,说明如何用汇编语言判断一个数是否为素数,从而进行汇编语言的学习。

点击展开/折叠代码

.MODEL SMALL
.STACK 100H

.DATA
    msg_input  DB 'Please input a number: $'
    msg_prime  DB 0DH, 0AH, 'It is a prime number.$'
    msg_not    DB 0DH, 0AH, 'It is not a prime number.$'
    num        DW 0

.CODE
START:
    MOV AX, @DATA
    MOV DS, AX

    ; 1. 显示输入提示  
    LEA DX, msg_input
    MOV AH, 09H
    INT 21H

    ; 2. 读取数字 (读取一个十进制数)
    CALL READ_NUM
    MOV num, AX

    ; 3. 判断素数逻辑
    ; 如果 n < 2,不是素数
    CMP AX, 2
    JL  NOT_PRIME
    JE  IS_PRIME      ; 2 是素数

    ; 循环判断: 从 2 到 n-1
    MOV CX, 2         ; CX 是除数
CHECK_LOOP:
    MOV AX, num
    XOR DX, DX        ; 清除高位
    DIV CX            ; AX / CX, 余数在 DX
    
    CMP DX, 0         ; 如果余数为 0,说明被整除
    JZ  NOT_PRIME
    
    INC CX
    MOV AX, CX
    MUL AX            ; 计算 CX * CX
    CMP AX, num       ; 只需检查到 根号 n 即可优化
    JA  IS_PRIME      ; 如果 CX*CX > num 还没除尽,就是素数
    
    JMP CHECK_LOOP

IS_PRIME:
    LEA DX, msg_prime
    JMP DISPLAY

NOT_PRIME:
    LEA DX, msg_not

DISPLAY:
    MOV AH, 09H
    INT 21H

    ; 4. 退出程序
    MOV AH, 4CH
    INT 21H

; --- 子程序:读取十进制数字 ---
READ_NUM PROC
    XOR BX, BX
READ_CHAR:
    MOV AH, 01H       ; 读取字符到 AL
    INT 21H
    CMP AL, 0DH       ; 回车键退出
    JZ  DONE_READ
    SUB AL, '0'       ; 转换为数字
    JL  DONE_READ
    CMP AL, 9
    JG  DONE_READ
    
    MOV AH, 0
    PUSH AX
    MOV AX, 10
    MUL BX            ; BX = BX * 10
    POP DX
    ADD AX, DX
    MOV BX, AX
    JMP READ_CHAR
DONE_READ:
    MOV AX, BX
    RET
READ_NUM ENDP

END START
  • 首先是汇编程序的整体结构。
    • .MODEL SMALL:指定了程序的内存模型为 16 位。
    • .STACK 100H:定义了堆栈段的大小为 100H。
    • .DATA:定义了数据段,用于存储程序中的变量和常量。
    • .CODE:定义了代码段,用于存储程序的指令。
    • START:程序的入口点。
    • END START:结束程序的定义。
  • 数据段:
    • msg_input:提示用户输入的字符串。
    • msg_prime:输出素数的字符串。
    • msg_not:输出非素数的字符串。
    • num:用于存储用户输入的数字。
  • 代码段:
    • START:程序的入口点。
    • MOV AX, @DATA:将数据段的地址加载到 AX 寄存器中。
    • MOV DS, AX:将 AX 寄存器中的地址加载到 DS 寄存器中,设置数据段。
    • 显示输入提示:
      • LEA DX, msg_input:将 msg_input 的地址加载到 DX 寄存器中。
      • MOV AH, 09H:设置 AH 寄存器为 09H,用于显示字符串。
      • INT 21H:调用中断 21H,执行显示字符串的操作。
    • 读取数字:
      • 调用 READ_NUM 子程序,将用户输入的数字存储在 num 中。
    • 判断素数逻辑:
      • CMP AX, 2:比较 AX 寄存器中的值和 2。
      • JL NOT_PRIME:如果 AX 小于 2,跳转到 NOT_PRIME 标签。
      • JE IS_PRIME:如果 AX 等于 2,跳转到 IS_PRIME 标签。
      • 循环判断:
        • MOV CX, 2:将 2 加载到 CX 寄存器中,作为除数。
        • CHECK_LOOP:循环标签。
        • MOV AX, num:将 num 中的值加载到 AX 寄存器中。
        • XOR DX, DX:将 DX 寄存器清零,用于存储余数。
        • DIV CX:将 AX 寄存器中的值除以 CX 寄存器中的值,余数存储在 DX 寄存器中。
        • CMP DX, 0:比较 DX 寄存器中的值和 0。
        • JZ NOT_PRIME:如果 DX 等于 0,说明被整除,跳转到 NOT_PRIME 标签。
        • INC CX:将 CX 寄存器中的值加 1。
        • MOV AX, CX:将 CX 寄存器中的值加载到 AX 寄存器中。
        • MUL AX:将 AX 寄存器中的值乘以自身,结果存储在 AX 寄存器中。
        • CMP AX, num:比较 AX 寄存器中的值和 num 中的值。
        • JA IS_PRIME:如果 AX 大于 num,跳转到 IS_PRIME 标签。
        • JMP CHECK_LOOP:跳转到 CHECK_LOOP 标签,继续循环。
      • IS_PRIME:如果是素数,跳转到 IS_PRIME 标签。
      • NOT_PRIME:如果不是素数,跳转到 NOT_PRIME 标签。
    • 显示结果:
      • 根据判断结果,加载相应的字符串到 DX 寄存器中。
      • MOV AH, 09H:设置 AH 寄存器为 09H,用于显示字符串。
      • INT 21H:调用中断 21H,执行显示字符串的操作。
    • 退出程序:
      • MOV AH, 4CH:设置 AH 寄存器为 4CH,用于退出程序。
      • INT 21H:调用中断 21H,执行退出程序的操作。
  • 子程序:
    • READ_NUM:用于读取用户输入的数字。
      • XOR BX, BX:将 BX 寄存器清零,用于存储数字。
      • READ_CHAR:循环标签。
      • MOV AH, 01H:设置 AH 寄存器为 01H,用于读取字符。
      • INT 21H:调用中断 21H,执行读取字符的操作。
      • CMP AL, 0DH:比较 AL 寄存器中的值和回车键的 ASCII 码。
      • JZ DONE_READ:如果 AL 等于回车键的 ASCII 码,跳转到 DONE_READ 标签。
      • SUB AL, '0':将 AL 寄存器中的值减去 ‘0’ 的 ASCII 码,转换为数字。
      • CMP AL, 9:比较 AL 寄存器中的值和 9。
      • JG DONE_READ:如果 AL 大于 9,跳转到 DONE_READ 标签。
      • MOV AH, 0:将 AH 寄存器清零。
      • PUSH AX:将 AX 寄存器中的值压入堆栈。
      • MOV AX, 10:将 10 加载到 AX 寄存器中。
      • MUL BX:将 BX 寄存器中的值乘以 AX 寄存器中的值,结果存储在 AX 寄存器中。
      • POP DX:将堆栈中的值弹出到 DX 寄存器中。
      • ADD AX, DX:将 AX 寄存器中的值加上 DX 寄存器中的值,结果存储在 AX 寄存器中。
      • MOV BX, AX:将 AX 寄存器中的值加载到 BX 寄存器中。
      • JMP READ_CHAR:跳转到 READ_CHAR 标签,继续循环。
      • DONE_READ:读取数字完成,跳转到 DONE_READ 标签。
      • MOV AX, BX:将 BX 寄存器中的值加载到 AX 寄存器中。
      • RET:返回。
  • 总结:
    • 该程序实现了判断一个数是否为素数的功能。
    • 首先,程序显示输入提示,然后调用 READ_NUM 子程序读取用户输入的数字。
    • 接下来,程序判断输入的数字是否小于 2,如果是,则不是素数,跳转到 NOT_PRIME 标签。
    • 如果输入的数字等于 2,则是素数,跳转到 IS_PRIME 标签。
    • 如果输入的数字大于 2,则进入循环判断。
    • 在循环中,程序将输入的数字除以从 2 到 num-1 的每个数,如果存在能整除的数,则不是素数,跳转到 NOT_PRIME 标签。
    • 如果循环结束后没有找到能整除的数,则是素数,跳转到 IS_PRIME 标签。
    • IS_PRIME 标签中,程序显示素数的字符串,并跳转到 DISPLAY 标签。
    • NOT_PRIME 标签中,程序显示非素数的字符串,并跳转到 DISPLAY 标签。
    • DISPLAY 标签中,程序调用中断 21H,执行显示字符串的操作。
    • 最后,程序调用中断 21H,执行退出程序的操作。
    • 该程序使用了堆栈来存储临时变量,以及一些寄存器来保存中间结果。
    • 该程序的时间复杂度为 O(sqrt(n)),其中 n 为输入的数字。
    • 该程序的空间复杂度为 O(1),因为只使用了常数个变量。

设计编写汇编程序要注意的是合理分配堆栈空间,避免栈溢出。同时,要注意寄存器的使用,避免寄存器冲突。另外,要注意程序的可读性和可维护性,避免出现冗余代码。


参考

王爽网课