一、实验目的
1. 理解标志寄存器用途,理解常用标志位CF, ZF, OF, SF, TF, IF的用途和意义。
2. 理解条件转移指令je, jz, ja, jb, jg, jl等的跳转原理,掌握组合使用汇编指令cmp和条件转移指令实现 分支和循环的用法
3. 了解软中断指令的用法,体验和理解中断原理
4. 综合应用寻址方式和汇编指令完成简单应用编程
二、实验准备
复习教材「第10章 call和ret指令」、「第11章 标志寄存器」
学习教材「第12章 内中断 」、「第13章 int指令」
三、实验内容
1. 实验任务1
验证性实验:
有些汇编指令会影响到标志寄存器中的一个或多个状态标志位。 在debug环境中,分别实践、观察:
① add指令对标志寄存器中的零标志位ZF(Zero Flag)、进位标志位CF(Carry Flag)是否有影响?
如图所示,在执行add指令ff+1之后,产生进位,进位标志为由NC变为CY,零标志位由NZ变为ZR。
② inc指令对标志寄存器中的零标志位ZF(Zero Flag)、进位标志位CF(Carry Flag)是否有影响?
如图所示,INC指令会影响零标志位,但不会影响进位标志位
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
其中: add128是子程序子程序。
功能:实现计算两位128位数的加法
入口参数: ds:si指向存储第一个128位数的存储空间(因为一个数128位,需要8个字节的连续空间) ds:di指向存储第二个128位数的存储空间
出口参数: 加运算后的结果,保存在第一个数的存储空间中,即:ds:si开始的连续8个字节空间 在代码段种,调用add128实现对标号x和y处存储的两个128位数据相加,结果保存在x处的连续128个字 节中。
对程序进行汇编、链接,得到可执行程序task1.exe。在debug中调试程序,并回答问题。
① line31~line34的4条inc指令,能否替换成如下代码?你的结论的依据/理由是什么?
能换成如下代码
试:将代码改成add指令
验证可以,因为这里不涉及到进位操作
② 在debug中调试,观察数据段中做128位加之前,和,加之后,数据段的值的变化。
加之前:
加之后:
2. 实验任务2
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
对源程序task2.asm进行汇编、链接,得到可执行文件task2.exe。
运行程序,从键盘上输入一串字符,以#结束(比如,输入George Orwell, 1984#),观察结果。
结合运 行结果,理解代码并回答问题:
① 汇编指令代码line11-18,实现的功能是?
读入输入的字符串,如果读到#,表示读结束,跳到next
② 汇编指令代码line20-22,实现的功能是?
打印换行符
③ 汇编指令代码line24-30,实现的功能是?
依次打印刚刚存入的输入字符,除了#,因为#并未存入到内存单元中。
3. 实验任务3
assume cs:code, ds:data,ss:stack data segment x dw 91,792,8536,65521,2021 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,5;获取数字的个数 mov bx,10;16位的除数 mov si,0 s: push cx mov ax,word ptr [si];dx和ax存放32位被除数,dx存放高16位,ax存放低16位 call printNumber call printSpace add si,2 pop cx;因为jmp指令里会改变cx的值 loop s mov ah,4ch int 21h printNumber: mov di,0 s1: mov dx,0 div bx push dx;把余数push进去 inc di;数组的位数+1 cmp ax,0 je s2;商为0则打印 jmp s1 s2: mov cx,di s3: ;打印,并将其转换成数字字符 pop ax mov dl,al mov ah,2 add dl,30h int 21h loop s3 ret printSpace: mov ah, 2 mov dl, " ";打印ASCII码值为10的换行符 int 21h ret code ends end start
调试运行:
4. 实验任务4
assume cs:code,ds:data data segment str db "assembly language, it's not difficult but tedious" len equ $ - str data ends code segment s: mov ax,data mov ds,ax mov cx,len mov si,0 call strupr mov ah,4ch int 21h strupr: mov al,[si] cmp al,' ' je ok and byte ptr [si],11011111b ok: inc si loop strupr ret code ends end s
调用子程序之前
调用子程序之后
5. 实验任务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 ;(1) int 21h mov ah, 2 ;(2) mov bh, 0 mov dh, 24 mov dl, 70 int 10h cmp al, '7' ;(3) 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,则在屏幕24行70列显示yes,输入其他字符,则在屏幕24行70列显示no。
程序分析
(1) 从键盘上输入一个字符
(2) 设置光标位置:0页24行70列
(3)若输入字符等于'7',则跳转到标号s1处,调用int 21h的9号子功能,显示str1处的字符串"yes";
若不等于'7',则调用int 21h的9号子功能,显示str2处的字符串"no"。
6. 实验任务6
task6_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) 将程序装到0:200的位置上 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 ;42*4-->ip 42*4+2-->CS mov ah, 4ch int 21h code ends end start
理解
1、中断、中断信息和中断处理程序:
中断的意思是,CPU不再接着向下执行,而是转去处理这个特殊信息。是指由于接收到外围硬件(相对于CPU与内存而言)的异步信号或者来自软件的同步信号而进行相应的硬件/软件处理。
CPU接受到中断信息后,可以立即对中断信息进行处理,用来处理中断信息的程序被称为中断处理程序。
2、中断向量表:
CPU用8为的中断类型码通过中断向量表找到相应的中断处理程序的入口地址。中断向量就是中断处理程序的入口地址。
3、软中断:
由软件本身发给操作系统内核的中断信号。
4、中断过程:
(1)从中断信息中取得中断类型码;
(2)标志寄存器的值入栈(因为在中断过程中要改变标志寄存器的值,所以先将其保存在栈中);
(3)设置标志寄存器的第8位TF和第9位IF的值为0;
(4)CS的内容入栈;
(5)IP的内容入栈;
(6)从内存地址为中断类型码*4和中断类型码*4+2的两个子单元中读取中断处理程序的入口地址设置IP和CS。