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

四、实验结论

1.实验任务1

task61.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

(1)line31~line34的4条inc指令,能否替换成如下代码?你的结论的依据/理由是什么?

add si, 2 
add di, 2

inc指令不影响进位标志位,但是add会对进位标志位产生影响。本次实验可以替换。下面的截图是替换后的运行结果,

可以看出运行结果正确。因为本次实验的di和si的数值在16位范围内,不会对进位产生影响。因此可以替换。

(2)在debug中调试,观察数据段中做128位加之前和加之后,数据段的值的变化。给出调试观察截图。

数据段未进行128位之前和加之前,数据如下

数据段未进行128位之前和加之后,数据如下 

 

2.实验任务2

task62.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
运行程序,从键盘上输入一串字符,以#结束(比如,输入well good morning 1999#),观察结
果。结合运行结果,理解代码并回答问题:

① 汇编指令代码line11-18,实现的功能是?
  从键盘输入单个字符,将该字符与#比较大小。
  若不相等,继续输入字符。
  若相等,则执行next后,输出#之前输入的字符到屏幕上。
② 汇编指令代码line20-22,实现的功能是?
  输出换行符到屏幕上。
③ 汇编指令代码line24-30,实现的功能是?
     输出#之前输入的字符到屏幕上。

 

3.实验任务3

编写8086汇编源程序task63.asm,在屏幕上以十进制形式输出data段中这一组连续的数据,数据和数据
之间以空格间隔。
要求:
  编写子程序printNumber
    功能:以十进制形式输出一个任意位数的整数(整数范围0 ~ 65535)
    入口参数:寄存器ax(待输出的数据 --> ax)
    出口参数:无
  编写子程序printSpace
    功能:打印一个空格
    入口参数:无
    出口参数:无
在主体代码中,综合应用寻址方式和循环,调用printNumber和printSpace, 实现题目要求。

task63.asm程序代码如下

assume cs:code,ds:data,ss:stack
data segment
    x dw 91,792,8356,65521,2021
    len equ $ - x
data ends
stack segment
    db 20 dup(0)
stack ends
;把内存中的十进制数以十进制数输出
code segment
start:
    mov ax,data
    mov ds,ax

    mov ax,stack
    mov ss,ax
    mov sp,20
    
    mov cx,5 
    mov si,offset x
;si存放十进制数的地址

s:  
    mov ax,ds:[si]
    call printNumber
    call printSpace
    inc si
    inc si
    loop s

    mov ah,4ch
    int 21h
    
printNumber:
    mov bx,10
    mov dx,0
    mov di,0
    push cx ;保存cx寄存器的值

s1:
    div bx;十进制除以10,商数存放在al,余数存放在ah
    push dx;将分离出的余数先保存到栈
    inc di
    mov dx,0
    cmp ax,0
    je ok
    jmp s1

ok:
    mov ah,2
    mov cx,di
s2:
    pop dx
    or dl,30h;数字转字符
    int 21h
    loop s2

    pop cx
    ret
printSpace:
    mov ah,2
    mov dl,32
;ASCII中32代表空格
    int 21h
    ret

code ends
end start

 

 4.实验任务4

编写8086汇编源程序task4.asm,将data段中字符串里的小写字符转换成大写。
要求:
  编写子程序strupr
    功能:将包含任意字符的字符串中的小写字母变成大写
    入口参数
    (ds:si ) 字符串首地址的段地址和偏移地址分别送至ds和si
    (cx) 字符串的长度
    出口参数:无
  在主体代码中,设置入口参数,调用strupr, 实现题目要求。

程序task64.asm代码如下

assume cs:code,ds:data
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,offset str
    mov cx,len
    call strupr

    mov ah,4ch
    int 21h

strupr:
s:
    mov al,byte ptr ds:[si]
    cmp al,'a'
    jb ok
    cmp al,'z'
    ja ok
;小写字母
    and al,11011111b
    mov ds:[si],al
ok:
    inc si
    loop s
    ret

code ends
end start

 

 5.实验任务5

task65.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
    mov dl, 70
    int 10h

    cmp al, '7'
    je s1
    mov ah, 9
    mov dx, offset str2
    int 21h

    jmp over

s1: mov ah, 9
    mov dx, offset str1
    int 21h
over:  
    mov ah, 4ch
    int 21h
code ends
end start

 

 程序的功能是验证输入的数据是否是7。如果是7,在屏幕指定位置输入yes,反之输出no。

cmp相当于减法指令,但是不保存结果,执行过后,会对标志寄存器产生影响。

 

6.实验任务6

对汇编源程序task66_1.asm进行汇编、链接,得到可执行程序task6_1.exe。运行task6_1.exe,实现将
42号中断处理程序安装到0:200开始的连续内存空间,并设置中断向量表,使得将来通过 int 42 ,系统
可以跳转到中断处理程序。
对汇编源程序task66_2.asm进行汇编、链接,得到可执行程序task6_2.exe。运行task6_2.exe。 
task66_1.asm程序代码如下
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

task66_2.asm程序代码如下:

assume cs:code

code segment
start:
    int 42

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

执行结果如图所示

 

 (1)8086cpu用称为中断类型码的数据来标识中断信息的来源。比如:在执行int n指令时,

         指令中的n为字节型立即数,是提供给CPU的中断类型码

(2)cpu用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址。

        对于8086pc机,中断向量表指定放在内存0地址处。

(3)iret指令可以让cpu返回执行中断处理程序的执行点继续执行程序。

五、实验总结

  以十进制输出ax的值,可以通过堆栈来实现。

  入栈:ax每次除以10,将余数压栈,商就保存在ax里,并用cx计入入栈个数。当商不为0时,继续循环,否则开始出栈。

  出栈:将刚刚保存的余数分别出栈,变为对应的ASCII值后输出。

posted @ 2021-12-10 22:04  Restart1012  阅读(47)  评论(4)    收藏  举报