【8086汇编程序设计指令总结】字符的输入输出、加减法、循环

发布于 22 天前  39 次阅读


大家好,我是ErikTse,我又来更新学科知识了,还有几天就要考8086汇编程序设计,现在开始一个预习。

因为只学了半天,所以很多东西理解并不到位,大家看个热闹好了~主要是自己记录一下。

一、INT 21H中断

INT 21H是指中断向量地址21H,用于DOS中的系统功能。具体是什么功能取决于AH标志位。

二、AH寄存器的标志

AH寄存器在输入输出和程序结束中十分关键,它用于定义INT 21H的中断含义。

  • MOV AH, 4CH 相当于C语言中的return 0;,用于表示程序结束。

  • MOV AH, 01H用于输入一个字符,存储到AL,相当于C语言中的AL = getchar(),这里ALAX寄存器的低8位,AH是高八位。

  • MOV AH, 0AH用于输入一个字符串到[DX],注意具体的输入逻辑是,将字符串输入到[DX + 2],将字符串长度保存到[DX + 1]位置,[DX]是用于定义的缓冲区长度,稍后会有代码介绍。

  • MOV AH, 02H用于输出[DL]中的字符。

  • MOV AH, 09H用于输出[DX]中的字符串内容,如果是字符串就一直输出直到遇到'$',相当于C语言中的'\0'。

在这些语句之后接上INT 21H即可实现调用DOS功能。

例如输出一个字符#:

        MOV DL, '#'
        MOV AH, 02H
        INT 21H

三、循环语句

循环语句一般默认用CX寄存器作为循环变量,利用JNZ指令和标记进行跳转,格式一般为:

        MOV CH, 00H;将CX高位CH置零
        MOV CL, AL;将AL内容送到CL,作为循环变量
        ;循环CX次
LP:     ;LP标记,有点goto语句内味

        ;循环内要做的事儿

        DEC CX;CX --
        JNZ LP;Jump if Not Zero,判断的是CX

当然你也可以通过CMP指令来指定JNZ所判断的寄存器,这个在后面双重循环中可以看到。

四、输入输出一个字符

我们来实现一个简单的程序,输入一个一位数整数n,输出n个字符'$'。

DATA    SEGMENT                                          

DATA    ENDS
CODE    SEGMENT      
        ASSUME    CS:CODE,DS:DATA
START:
        MOV AX, DATA
        MOV DS, AX
        ;以上为固定语句,意思是将DATA段的地址送到DS寄存器


        MOV AH, 01H;输入一个字符到[AL]
        INT 21H;中断

        ;注意此时AL为一个字符,需要转换为数字
        SUB AL, 30H;将AL减去48(30H),参考ASCII表

        MOV CH, 00H;将CX高位CH置零
        MOV CL, AL;将AL内容送到CL,作为循环变量
LP:

        ;在这里输出字符$
        MOV DL, '$';将字符$送到DL寄存器
        MOV AH, 02H;02H的作用是输出一个字符
        INT 21H

        DEC CX;CX --
        JNZ LP;Jump if Not Zero,判断的是CX


        ;以下为固定语句
        MOV AH, 4CH
        INT 21H

CODE    ENDS                             
END  START  

咱们再写一个双重循环,输出15行16列,10H~FFH所有字符。

DATA    SEGMENT                                          
        new_row DB 0DH, 0AH, '$'
        chr DB 10H
DATA    ENDS
CODE    SEGMENT      
        ASSUME    CS:CODE,DS:DATA
START:
        MOV AX, DATA
        MOV DS, AX

        MOV CX, 0FH;CX = 15
LP1:
        MOV BX, 10H;BX = 16
        LP2:

        MOV DL, [chr]
        MOV AH, 02H
        INT 21H

        INC [chr];每输出一次就[ch]+1

        ;输出一个空格
        MOV DL, ' '
        MOV AH, 02H
        INT 21H

        DEC BX;
        CMP BX, 00H
        JNZ LP2

        ;内层循环结束,输出换行
        LEA DX, new_row
        MOV AH, 09H
        INT 21H

        DEC CX
        CMP CX, 00H
        JNZ LP1


        MOV AH, 4CH
        INT 21H

CODE ENDS
END START

五、例题

这里写一个例题,来将一个8位二进制数转换为2位十六进制数:

DATA    SEGMENT   
        ARR DB 9, ?, 9 DUP('$')
        NEW_LINE DB 0DH, 0AH, '$' 
        NUM DB 0, 0
        CHR DB '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
DATA    ENDS
CODE    SEGMENT      
        ASSUME    CS:CODE,DS:DATA
START:
        MOV AX, DATA
        MOV DS, AX

        ;将字符串输入进ARR数组
        LEA DX, ARR
        MOV AH, 0AH
        INT 21H

        LEA DX, NEW_LINE
        MOV AH, 09H
        INT 21H

        MOV CX, 2
        LEA SI, ARR + 2;将输入的字符串首地址给SI
LP1:
        MOV AL, [SI]

        SHL NUM, 1
        SUB AL, 30H
        ADD NUM, AL     

        INC SI
        INC CX
        CMP CX, 5
        JNA LP1 

;处理得到[NUM + 1]
LP2:
        MOV AL, [SI]

        SHL NUM + 1, 1
        SUB AL, 30H
        ADD NUM + 1, AL     

        INC SI
        INC CX
        CMP CX, 9
        JNA LP2

        ;输出CHR[NUM + 0]
        LEA DI, CHR;将CHR的地址给DI
        MOV AH, 00H;将AX高8位置零
        MOV AL, NUM;将NUM内容给AL
        MOV SI, AX;将AX赋值给SI作为偏移量
        ADD DI, SI;计算地址
        MOV DL, [DI];将DI值给DL
        MOV AH, 02H;打印输出
        INT 21H

        ;输出CHR[NUM + 1]
        LEA DI, CHR;将CHR的地址给DI
        MOV AH, 00H;将AX高8位置零
        MOV AL, NUM + 1;将NUM内容给AL
        MOV SI, AX;将AX赋值给SI作为偏移量
        ADD DI, SI;计算地址
        MOV DL, [DI];将DI值给DL
        MOV AH, 02H;打印输出
        INT 21H


        MOV DL, 'H'
        MOV AH, 02H
        INT 21H


        MOV AH, 4CH
        INT 21H

CODE ENDS
END START
19岁,性别未知,ACM-XCPC退役选手,CCPC全国邀请赛金牌,ICPC亚洲区域赛银牌,武汉某院校计算机科学与技术专业本科在读。
最后更新于 2023-11-14