ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

实验4 8086标志寄存器及中断

2021-12-12 15:31:08  阅读:171  来源: 互联网

标签:8086 code di 中断 mov int si 寄存器 ax


目录

一、实验目的

  1. 理解标志寄存器用途,理解常用标志位CF, ZF, OF, SF, TF, IF的用途和意义。
  2. 理解条件转移指令je, jz, ja, jb, jg, jl等的跳转原理,掌握组合使用汇编指令cmp和条件转移指令实现分支和循环的用法
  3. 了解软中断指令的用法,体验和理解中断原理
  4. 综合应用寻址方式和汇编指令完成简单应用编程

二、实验结论

1. 实验任务1

task1.asm

assume cs:code, ds:data

data segment
   x dw 1020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h
   y dw 3210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h
data ends
code segment 
start:
    mov ax, data
    mov ds, ax
    mov si, offset x
    mov di, offset y
    call add128

    mov ah, 4ch
    int 21h

add128:
    push ax
    push cx
    push si
    push di

    sub ax, ax

    mov cx, 8
s:  mov ax, [si]
    adc ax, [di]
    mov [si], ax

    inc si
    inc si
    inc di
    inc di
    loop s

    pop di
    pop si
    pop cx
    pop ax
    ret
code ends
end start

问题

line31-line34的4条inc指令,能否替换成如下代码?

add si, 2
add di, 2

答:不能,因为inc指令不会影响CF进位标志位而add指令会,替换成add会对后面的adc指令产生影响,可能导致计算错误。

调试运行

数据段做加和之前:

数据段做加和之后:

可以看到原本x的位置变成x+y,原本y的位置不变。

2. 实验任务2

task2.asm

assume cs:code, ds:data
data segment
        str db 80 dup(?)
data ends

code segment
start:  
        mov ax, data
        mov ds, ax
        mov si, 0
s1:        
        mov ah, 1
        int 21h
        mov [si], al
        cmp al, '#'
        je next
        inc si
        jmp s1
next:
        mov ah, 2
        mov dl, 0ah
        int 21h
        
        mov cx, si
        mov si, 0
s2:     mov ah, 2
        mov dl, [si]
        int 21h
        inc si
        loop s2

        mov ah, 4ch
        int 21h
code ends
end start

调试运行

可以看到从键盘输入一串字符,输入#结尾后程序在下一行打印出输入的字符串。

问题

① line11-18实现的功能:先保存当前输入字符,再比较当前输入字符是否为'#',是跳转到next,不是继续输入下个字符;

②line20-22实现的功能:输出换行符;

③line24-30实现的功能:依次输出键入的一串字符(不包括结尾的#)。

3. 实验任务3

task3.asm

assume ds:data,cs:code,ss:stack
data segment
    x dw 91, 792, 8536, 65521, 2021
    len equ $ - x
data ends
stack segment
    db 80 dup(0)
stack ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov ax, stack
    mov ss, ax      ;栈段
    mov sp, 50h
    mov si, 0       ;数据段指针
    mov cx, 5       ;5个数,循环5次
    mov bx, 0ah     ;存除数10
s:
    push cx         ;cx在子程序中会用到,先存入栈
    mov ax, [si]    ;将待处理的数放入ax
    call printNumber    ;调用printNumber子程序,转换成10进制并输出
    call printSpace     ;调用printSpace子程序,输出空格
    add si, 2       ;指向下一个数
    pop cx          ;取出cx的值
    loop s
    jmp exit        ;退出程序


printNumber:        ;转换成10进制并输出
    mov di, 0       ;计数转化后的位数
s1:                 ;从低位到高位,每次求出一位
    mov dx, 0       
    div bx          ;除10
    push dx         ;余数入栈
    inc di          ;计数+1
    cmp ax, 0       ;当前商是否为0
    je s2           ;商为0,退出循环;不为0,继续除
    jmp s1          
s2:
    mov cx, di      
s3:                 ;开始出栈
    pop ax
    add ax, 30h     ;转化成对应字符ASCII码
    mov dl, al
    mov ah, 2
    int 21h         ;打印输出
    loop s3
    ret
printSpace:         ;打印空格
    mov ah, 2       
    mov dl, " "
    int 21h
    ret
exit:
    mov ah, 4ch
    int 21h
code ends
end start

调试运行

可以看到成功打印转换后的10进制数。

4. 实验任务4

task4.asm

assume ds:data,cs:code
data segment
    str db "assembly language, it's not difficult but tedious"
    len equ $ - str
data ends
code segment
start:
    mov ax, data
    mov ds, ax
    mov si, 0       ;数据段指针
    mov cx, len     ;字符串长度
    call strupr     ;调用小写转大写子程序
    jmp exit        ;退出程序

strupr:             
s:
    mov al, [si]    ;当前字符放入al
    cmp al, 61h     ;ASCII码在[61h,7ah]为小写字母
    jb s1
    cmp al, 7ah
    ja s1
    and al, 0dfh    ;二进制位第三位变为0,小写转大写
    mov [si], al
s1:
    inc si          ;下个字符
    loop s
    ret

exit:
    mov ah, 4ch
    int 21h
code ends
end start

调试运行

子程序调用前:

子程序调用后:

可以看到字符串中的小写字母成功转成大写字母。

5. 实验任务5

task5.asm

assume cs:code, ds:data

data segment
    str1 db "yes", '$'
    str2 db "no", '$'
data ends

code segment
start:
    mov ax, data
    mov ds, ax

    mov ah, 1
    int 21h                 ; 从键盘输入字符

    mov ah, 2
    mov bh, 0
    mov dh, 24              ; 设置光标位置在第24行
    mov dl, 70              ; 设置光标位置在第70列
    int 10h                 ; 设置光标位置

    cmp al, '7'
    je s1
    mov ah, 9
    mov dx, offset str2
    int 21h                 ; 显示标号str2处的字符串

    jmp over

s1: mov ah, 9
    mov dx, offset str1
    int 21h                 ; 显示标号str1处的字符串
over:  
    mov ah, 4ch
    int 21h
code ends
end start

调试运行

输入7:

输入其他字符:

可以看到,如果输入7,在24行70列处打印str1;输入其他字符,在24行70列打印str2。

程序分析

功能:从键盘键入一个字符,如果是7,在光标位置(24行70列)打印str1;是其他字符,在光标位置打印str2。

分析:

line13-14 键盘键入一个字符,存入al

line16-20 设置光标位置,24行70列

line22-26 al中字符不为7,在光标位置打印str2

line30-32 al中字符为7,在光标位置打印str1

6. 实验任务6

task6_1.asm

;功能:装入42号程序中断处理程序
assume cs:code

code segment
start:
    ; 42 interrupt routine install code
    mov ax, cs
    mov ds, ax
    mov si, offset int42  ; set ds:si

    mov ax, 0
    mov es, ax
    mov di, 200h        ; set es:di

    mov cx, offset int42_end - offset int42
    cld
    rep movsb

    ; set IVT(Interrupt Vector Table)
    mov ax, 0
    mov es, ax
    mov word ptr es:[42*4], 200h
    mov word ptr es:[42*4+2], 0

    mov ah, 4ch
    int 21h

int42: 
    jmp short int42_start
    str db "welcome to 2049!"
    len equ $ - str

    ; display string "welcome to 2049!"
int42_start:
    mov ax, cs
    mov ds, ax
    mov si, 202h

    mov ax, 0b800h
    mov es, ax
    mov di, 24*160 + 32*2

    mov cx, len
s:  mov al, [si]
    mov es:[di], al
    mov byte ptr es:[di+1], 2
    inc si
    add di, 2
    loop s

    iret
int42_end:
   nop
code ends
end start

task6_2.asm

assume cs:code

code segment
start:
    int 42

    mov ah, 4ch
    int 21h
code ends
end start

调试运行

对中断、软中断的理解

中断: 中断是指由于接收到外围硬件(相对于CPU与内存而言)的异步信号或者来自软件的同步信号而进行相应的硬件/软件处理 ;

软中断: 由软件本身发给操作系统内核的中断信号,称之为软中断 ;

中断处理:

(1)(从中断信息中)取得中断类型码;

(2)标志寄存器的值入栈(在中断过程中要改变标志寄存器的值);

(3)设置标志寄存器的第8位TF和第9位IF的值为0;

(4)CS、IP的内容依次入栈;

(5)从内存地址为中断类型码*4中断类型码*4+的两个字单元中读取中断处理程序的入口地址设置IP和CS。

自定义中断程序:41号中断码

中断例程功能:

使用的中断码为41号,中断例程功能为在屏幕中间显示“201983290041 zzyuan”

task6_3.asm

;装入中断处理程序
assume cs:code
code segment
start:
    ;ds:si指向中断处理程序
    mov ax, cs
    mov ds, ax
    mov si, offset int41

    ;es:di指向程序装入地址
    mov ax, 0
    mov es, ax
    mov di, 200h

    ;获取程序长度
    mov cx, offset int41end-int41
    cld
    rep movsb

    ;设置中断向量表
    mov ax, 0
    mov es, ax
    mov word ptr es:[41*4], 200h
    mov word ptr es:[41*4+2], 0
    
    mov ah, 4ch
    int 21h

;41号中断处理程序
int41:
    jmp short int41start
    db "201983290041 zzyuan"        ;存放要打印的字符串
int41start:
    ;ds:si指向待打印字符串
    mov ax, cs
    mov ds, ax
    mov si, 202h

    ;es:di指向屏幕中间
    mov ax, 0b800h
    mov es, ax
    mov di, 12*160+30*2

    ;cx字符串长度
    mov cx, 13h
s:  mov al, [si]
    mov es:[di], al                 
    mov byte ptr es:[di+1], 2       ;黑底绿字
    inc si
    add di, 2
    loop s

    mov ax, 4c00h
    int 21h

int41end:nop
code ends
end start

task6_4.asm

assume cs:code

code segment
start:
    int 41

    mov ah, 4ch
    int 21h
code ends
end start

调试运行

三、实验总结

  1. 有些指令的执行结果会影响到一些标志位,如add、sub等;有些不影响,如mov、push、pop、inc、dec;
  2. cmp指令和转移指令结合使用可以实现if逻辑;
  3. 寄存器不够用或使用冲突问题可以借助栈解决;
  4. 中断向量表存放在0000:0000~0000:03FF大小1KB的空间中,256个中断对应256个表项,每个表项占2个字,高位字存段地址,低位字存偏移地址;
  5. 可以利用中断向量表中的空闲单元存放中断处理程序,一般可用0000:0200~0000:02FF这256字节的空间;

标签:8086,code,di,中断,mov,int,si,寄存器,ax
来源: https://www.cnblogs.com/z-pluto/p/15679415.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有