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

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

实验任务1

任务点1

验证add对ZF和CF的影响


可以看到对ZF和CF都造成了影响

验证inc对ZF和CF的影响


只对ZF造成影响

测试代码如下

assume cs:code,ds:data
data segment
    db 16 dup(0)
data ends
stack segment
    db 128 dup(0)
    top equ $+1
stack ends
code segment
start:
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax
    mov sp,top

    mov ax,0ffffh
    add ax,1
    ;测试add对CF和ZF的影响

    mov ax,1
    add ax,1
    ;恢复测试之前的影响,即无进位

    mov ax,0ffffh
    inc ax
    ;测试inc对CF和ZF的影响
    mov ah,4ch
    int 21h
code ends
end start

任务点2

TASK_1.ASM代码

assume cs:code, ds:data

data segment
   x dw 1020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h;一个128位数字
   y dw 3210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h;一个128位数字
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

对于inc能否用add替换的回答

inc的结果

add的结果

可以看到没有任何区别,这是因为代码中给出的数据不会产生任何进位,所以addinc在这种特殊的情况下无区别
下面修改代码里面的数据,使其能产生进位

data segment
   x dw 9020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h
   y dw 9210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h
data ends

inc的结果

add的结果

这就有了区别了
后16位的运算需要用到前16位运算的进位值,所以不能用add
因为根据之前的实验,add会对CF标志寄存器造成影响,inc则不会。

运行并观察数据段的变化

做加法之前

做加法后

可以看到进行了加法,但并没有产生进位
接下来的运行结果类似,并没有产生进位

实验任务2

代码以及注释解析

assume cs:code, ds:data
data segment
        str db 80 dup(?);80个字节未初始化的内存空间
data ends

code segment
start:  
        mov ax, data
        mov ds, ax
        mov si, 0
s1:        
        mov ah, 1;int 21h中断的参数,表示输入单个字符
        int 21h;调用中断例程
        mov [si], al;将结果存入ds:[si]中
        cmp al, '#';与'#'比对,影响标志寄存器ZF,运算结果为0表示相同,则ZF标志寄存器变为ZR
        je next;if(al == '#'(ZF == ZR)) goto next
        inc si;偏移地址加一
        jmp s1;继续输入一个字符
next:
        mov ah, 2;int 21h中断的参数,表示打印一个ASCII字符
        mov dl, 0ah;换行
        int 21h;调用中断例程
        
        mov cx, si;将输入的字符的数量(不包括#)赋给cx寄存器
        mov si, 0;将si寄存器置零
s2:     mov ah, 2;int 21h中断的参数,表示打印一个ASCII字符
        mov dl, [si];将ds:[si]出内存的值赋给dl
        int 21h;调用中断例程
        inc si;偏移地址+1
        loop s2;循环,直到cx=0

        mov ah, 4ch;int 21h中断的参数,表示回到DOS
        int 21h;执行中断例程
code ends
end start

运行结果

实验任务2

代码

assume cs:code,ds:data
data segment
    x dw 91, 792, 8536, 65521, 2021
    len equ $ - x
data ends
stack segment
    db 64 dup(0)
    top equ $+1
stack ends
code segment
start:
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax
    mov sp,top

    mov cx,len/2
    mov bx,0
s1:  
    mov ax,ds:[bx]
    push bx
    push cx
    call printNumber
    call printSpace
    pop cx
    pop bx
    add bx,2
    loop s1

    mov ah,4ch
    int 21h

printNumber:
    ;ax dx
    ;ax 被除数,直到
    ;cx计有多少位,然后循环出栈输出
    mov bx,10
    mov cx,0
s2:
    mov dx,0
    div bx
    ;ax 商
    ;dx 余数
    push dx
    inc cx
    cmp ax,0
    jne s2

s3:
    mov ah,2
    pop dx
    or dl,30h
    int 21h
    loop s3
    ret

printSpace:
    mov ah,2
    mov dl,20h
    int 21h
    ret

code ends
end start

运行结果

实验任务4

代码

assume cs:code,ds:data
data segment
    str db "assembly language, it's not difficult but tedious"
    len = ($ - str)
data ends
stack segment
    db 128 dup(0)
    top equ $ + 1
stack ends
code segment
start:
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax
    mov sp,top

    mov si,0
    mov cx,len
    call strupr
    mov ah,4ch
    int 21h
strupr:
;0100 0001 A
;0110 0001 a
s:
    cmp byte ptr ds:[si],61h
    jb s1
    cmp byte ptr ds:[si],7ah
    ja s1
    mov dl,ds:[si]
    and dl,11011111B
    mov ds:[si],dl
s1: 
    inc si
    loop s
    ret
code ends
end start

运行结果

实验任务5

代码注释解析

assume cs:code, ds:data
;输入7,则屏幕显示yes
;否则输出no
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;int 10h 2号功能,设置光标位置
    mov bh, 0;页号
    mov dh, 24;行号
    mov dl, 70;列号
    int 10h;BIOS中断例程调用

    cmp al, '7'
    je s1;ZF == ZR 跳转,相等跳转
    mov ah, 9;输出字符串
    mov dx, offset str2;字符串首地址
    int 21h;DOS中断例程

    jmp over

s1: mov ah, 9;输出字符串
    mov dx, offset str1;字符串首地址
    int 21h;DOS中断例程
over:  
    mov ah, 4ch
    int 21h;DOS中断例程
code ends
end start

运行结果

实验任务6

实验子任务1

将例程直接内嵌进task6_1.asm的代码中了
运行结果如下

中断和软中断的区别

中断,其实就是中断源发出中断信号,CPU暂定当前的程序,转而去执行其他程序,即改变CS:IP
中断源有很多,CPU内部的中断源发出中断信号,外部设备发出的中断信号。
硬件中断指的就是外部设备发出的电信号中断信号,需要中断控制器,排队器等硬件电路实现。
软中(内)断就是CPU内部产生的中断信号,比如除法溢出,或者程序调用中断例程,感觉和call类似。

实验子任务2

实现了书本上对于0号中断例程的修改。

代码

assume cs:code

code segment
start:
    mov ax,0
    mov es,ax;目的段地址
    mov ax,cs
    mov ds,ax;源段地址
    mov di,200h
    mov si,d0s
    mov cx,d0len

    movd0:;将代码复制到0:200处
        mov al,ds:[si]
        mov es:[di],al
        inc si
        inc di
        loop movd0
    
    ;设置中断表,中断表处于内存中
    ;中断表ip: 中断号*4
    ;中断表cs: 中断号*4+2
    mov ax,0
    mov ds,ax
    mov word ptr ds:[0],200h
    mov word ptr ds:[2],0


    ;测试例程
    mov ax,1000h
    mov bh,1
    div bh
    ;测试例程

    mov ax,4c00h
    int 21h
d0:
    d0s equ $
    ;将字符串常驻内存
    jmp short d0start
    db "overflow!"
d0start:
    mov ax,cs
    mov ds,ax
    mov si,202h
    mov ax,0b800h
    mov es,ax
    mov di,12*160+36*2
    mov cx,9
s:  mov al,[si]
    mov es:[di],al
    inc si
    add di,2
    loop s

    ;iret;中断返回,这里不返回,直接调用DOS中断,返回DOS,不然会卡死
    mov ah,4ch
    int 21h
    d0len equ $-d0s
code ends
end start

运行结果

posted @ 2021-12-06 20:29  Alyjay  阅读(163)  评论(2编辑  收藏  举报