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

一、实验目的
1. 理解标志寄存器用途,理解常用标志位CF, ZF, OF, SF, TF, IF的用途和意义。
2. 理解条件转移指令je, jz, ja, jb, jg, jl等的跳转原理,掌握组合使用汇编指令cmp和条件转移指令实现分支和循环的用法
3. 了解软中断指令的用法,体验和理解中断原理4. 综合应用寻址方式和汇编指令完成简单应用编程
二、实验准备复习教材
「第10 callret指令」、「第11标志寄存器」学习教材「第12内中断」、「第13 int指令」
 
 
 
三、实验内容
1. 实验任务1
验证性实验:有些汇编指令会影响到标志寄存器中的一个或多个状态标志位。debug环境中,分别实践、观察:
 1 assume cs:code,ds:data
 2 data segment
 3     x dw 1020h,2240h,9522h,5060h,3359h,6652h,2530h,7031h
 4     y dw 3210h,5510h,6066h,5121h,8801h,6210h,7119h,3912h
 5 data ends
 6 code segment
 7 start:
 8     mov ax,data
 9     mov ds,ax
10     mov si,offset x
11     mov di,offset y
12     call add128
13     
14     mov ah,4ch
15     int 21h
16 
17 add128:
18     push ax
19     push cx
20     push si
21     push di
22 
23     sub ax,ax
24     
25     mov cx,8
26 s:    mov ax,[si]
27     adc ax,[di]
28     mov [si],ax
29 
30     inc si
31     inc si
32     inc di
33     inc di
34     loop s
35 
36     pop di
37     pop si
38     pop cx
39     pop ax
40     ret
41 code ends
42 end start
43     

 

line31~line344inc指令,能否替换成如下代码?你的结论的依据/理由是什么?
1 add si, 2
2 add di, 2

不能替换,因为add操作会对CF的值产生影响,影响进一步的sub和adc指令。

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

 

 2. 实验任务2

此部分书写内容:

程序task2.asm源码

 1 assume cs:code, ds:data
 2 data segment
 3     str db 80 dup(?)
 4 data ends
 5 code segment
 6 start:
 7     mov ax, data
 8     mov ds, ax
 9     movsi, 0
10 s1:
11     mov ah, 1
12     int 21h
13     mov [si], al
14     cmp al, '#'
15     je next
16     inc si 
17     jmp s1
18 next:
19     mov ah, 2
20     mov dl, 0ah
21     int 21h
22     mov cx, si
23     mov si, 0
24 s2:
25          mov ah, 2
26     mov dl, [si]
27     int 21h
28     inc si
29     loop s2
30     mov ah, 4ch
31     int 21h
32 code ends
33 end start

 

运行测试截图

回答问题运行程序,从键盘上输入一串字符,以#结束(比如,输入George Orwell, 1984#),观察结果。结合运行结果,理解代码并回答问题:

 

 

汇编指令代码line11-18,实现的功能是?

答:从键盘上读取输入的字符,并保存到ds:[si],每读入一个就判断是否为#,如果是则不保存,转跳至标号next处执行;如果不是则si + 1并继续读入下一个字符。

汇编指令代码line20-22,实现的功能是?

:打印一个回车(换行符)

汇编指令代码line24-30,实现的功能是?

 答:打印字符串,并且不会把#打出来

 

3. 实验任务3

此部分书写内容:

task3.asm源码

assume ds:data, cs:code, ss:stack

data segment
    x dw 91, 792, 8536, 65535, 2021, 0
    len equ $ - x
data ends

stack segment
    dw 8 dup(?)
stack ends

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

    mov ax, stack
    mov ss, ax
    mov sp, 16

    mov cx, len/2
        mov ax, word ptr ds:[di]    ; 把数据放入al
        add di, 2                   ; di指针后移2字节

        push cx             ; 把cx保存起来, 子程序中会修改cx值

        call printNumber    ; 打印数字
        call printSpace     ; 打印空格

        pop cx              ; 恢复cx
    loop print
    
    mov ah, 4ch
    int 21h

printNumber:
    mov bx, 0       ; 获取之前位数为0
    ; 逐位获取数字
    ; getEach循环: 获取每一位,然后压入栈中
    getEach:
        ; 除数放在16位寄存器bp中
        mov bp, 10      ; 除10运算
        mov dx, 0       ; 由于除数是16位寄存器,dx也是被除数一部分,需要置零      
        div bp          ; 数据除10

        push dx         ; 将数字压入栈中
        inc bx          ; 位数+1
        
        mov cx, ax      ; 除法商赋给cx
        inc cx          ; 由于loop时会-1,这里先+1,防止出现负数

    loop getEach

    ; 打印数字
    mov cx, bx 
    printEach:
        pop dx         
        add dl, 30h     
        mov ah, 2 
        int 21h
    loop printEach 

    ret

; 子程序: printSpace
; 功能: 打印空格
printSpace:
    mov ah, 2
    mov dl, 20h
    int 21h
    ret

code ends
end start

 

运行测试截图

 

 

实验任务4

题目描述

针对8086CPU,已知逻辑段定义如下:

data segment
        str db "assembly language, it's not difficult but tedious" 
        len equ $ - str
data ends

 

编写8086汇编源程序task4.asm,将data段中字符串里的小写字符转换成大写。

要求:

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

代码:

 1 assume cs:code,ds:data
 2 data segment
 3     str db "assembly language, it's not difficult but tedious"
 4     len equ $ - str
 5 data ends
 6 
 7 stack segment
 8     db 8 dup(?)
 9 stack ends
10 
11 code segment
12 start: 
13     mov ax, data
14     mov ds, ax
15     mov si, 0
16     mov cx, len     ; 参数:字符串长度存在cx中
17     call strupr     ; 调用转换子程序
18     call printStr   ; 调用打印子程序
19 
20     mov ax, 4c00h
21     int 21h
22 
23 strupr:
24     push cx
25     push si         ; 先保存两个寄存器的值
26     transform:
27         mov al, ds:[si] ; 取出一个字符
28         cmp al, 97      ; 判断ASCII码是否 >= 97
29         jl continue     ; 小于97直接进入下次循环
30         cmp al, 122     ; 判断ASCII码是否 <= 122
31         jg continue     ; 大于122直接进入下次循环
32         and al, 0dfh    ; 小写转成大写,原理详见实验2
33         mov ds:[si], al ; 把转换后的字符送回data段
34     continue:
35         inc si          ; 指针后移
36         loop transform  ; 循环
37 
38     pop si
39     pop cx          ; 恢复寄存器的值
40     ret             ; 返回
41 
42 printStr:
43     push cx         ; 保存寄存器的值
44     push si
45 
46     print:          ; 打印字符循环
47         mov ah, 2
48         mov dl, ds:[si]
49         int 21h
50         inc si
51     loop print
52 
53     pop si          ; 恢复寄存器的值
54     pop cx
55     ret             ; 返回
56 
57 code ends
58 end start

 

实验结果

可以看到,该程序成功将小写字母转成了大写。

实验任务5

源代码

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后,屏幕上右下角显示yes

 

 

 

 

输入其它字符,屏幕上倒数第2行右下角显示no

 

  

实验任务6

通过编译连接运行task6_1.asmtask6_2.asm后可以看到,屏幕底部出现了绿色的"welcome to 2049!",说明42号中断程序被成功调用。

 

 


 

 

posted @ 2021-12-10 23:59  冬咚东  阅读(176)  评论(2)    收藏  举报