实验3 转移指令跳转原理及其简单应用编程
1. 实验任务1
1)task1.asm源码:
1 assume cs:code, ds:data 2 3 data segment 4 x db 1, 9, 3 5 len1 equ $ - x 6 7 y dw 1, 9, 3 8 len2 equ $ - y 9 data ends 10 11 code segment 12 start: 13 mov ax, data 14 mov ds, ax 15 16 mov si, offset x 17 mov cx, len1 18 mov ah, 2 19 s1:mov dl, [si] 20 or dl, 30h 21 int 21h 22 23 mov dl, ' ' 24 int 21h 25 26 inc si 27 loop s1 28 29 mov ah, 2 30 mov dl, 0ah 31 int 21h 32 33 mov si, offset y 34 mov cx, len2/2 35 mov ah, 2 36 s2:mov dx, [si] 37 or dl, 30h 38 int 21h 39 40 mov dl, ' ' 41 int 21h 42 43 add si, 2 44 loop s2 45 46 mov ah, 4ch 47 int 21h 48 code ends 49 end start
编译、连接、运行截图:

① line27, 汇编指令 loop s1 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明是如何计算得到跳转后标号s1其后指令的偏移地址的。
debug反汇编:

(1)loop指令的机器码为E2F2,跳转的8位位移=标号处的地址-loop指令后的第一个字节的地址。
这里标号处的地址是s1的地址为076B:000D,loop指令后的第一个字节的地址是loop后下一条指令的地址为076B:001B。
所以8位位移=000D-001B=-0E(十六进制)=-14(十进制),十六进制补码为F2。
(2)CPU计算跳转后的偏移地址(IP)是通过loop指令的机器码和当前IP得出的。
机器码E2F2,其中E2表明此命令为loop指令,F2为位移量的十六进制补码形式。
当CPU读取并执行E2F2时,当前IP=001B(0019+0003),跳转后IP=当前IP+位移量=001B-0E=000D。
② line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机 器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明 是如何计算得到跳转后标号s2其后指令的偏移地址的。
debug反汇编:

(1)loop指令的机器码为E2F0,跳转的8位位移=标号处的地址-loop指令后的第一个字节的地址。
这里标号处的地址是s2的地址为076B:0029,loop指令后的第一个字节的地址是loop后下一条指令的地址为076B:0039。
所以8位位移=0029-0039=-10(十六进制)=-16(十进制),十六进制补码为F0。
(2)CPU计算跳转后的偏移地址(IP)是通过loop指令的机器码和当前IP得出的。
机器码E2F0,其中E2表明此命令为loop指令,F0为位移量的十六进制补码形式。
当CPU读取并执行E2F0时,当前IP=0039(0037+0002),跳转后IP=当前IP+位移量=0039-10=0029。
2. 实验任务2
1)task2.asm源码:
1 assume cs:code, ds:data
2
3 data segment
4 dw 200h, 0h, 230h, 0h
5 data ends
6
7 stack segment
8 db 16 dup(0)
9 stack ends
10
11 code segment
12 start:
13 mov ax, data
14 mov ds, ax
15
16 mov word ptr ds:[0], offset s1
17 mov word ptr ds:[2], offset s2
18 mov ds:[4], cs
19
20 mov ax, stack
21 mov ss, ax
22 mov sp, 16
23
24 call word ptr ds:[0]
25 s1: pop ax
27 call dword ptr ds:[2]
28 s2: pop bx
29 pop cx
30
31 mov ah, 4ch
32 int 21h
33 code ends
34 end start
① 根据call指令的跳转原理,先从理论上分析,程序执行到退出(line31)之前,寄存器(ax) = ? 寄存器(bx) = ? 寄存器(cx) = ?
(1)call word ptr 内存单元相当于
push IP
jmp word ptr 内存单元地址
(2)call dword ptr 内存单元相当于
push CS
push IP
jmp dword ptr 内存单元地址
(3)ds:[0]中存放的是s1的IP,ds:[2]中存放的是s2的IP。第一个call指令先将s1的IP压入栈,再跳转到ds:[0]即s1处执行pop ax,即将s1的IP=0021出栈并存放到ax。
(4)第二个call指令先将s2处的CS压入栈,再将s2处的IP压入栈,再跳转到ds:[2]即s2处执行pop bx,即将s2的IP:0026出栈并存放到bx,再执行pop cx,即将s2的CS:076C出栈并存放到cx中。
综上可得程序执行到line31之前,ax=0021,bx=0026,cx=076C
② 对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证调试结果与理论分析结果是否一致。
编译、连接截图:

使用debug调试,观察、验证调试结果

运行到31行前 -g 076C:0028

可以看到ax=0021,bx=0026,cx=076C,与理论值一致。
3. 实验任务3
编写8086汇编源程序task3.asm,在屏幕上以十进制形式输出data段中这一组连续的数据,数据和数据之间以空格间隔。
1)task3.asm源码:
1 assume cs:code, ds:data 2 3 data segment 4 x db 99, 72, 85, 63, 89, 97, 55 5 len equ $ - x 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov si, offset x 13 mov cx, len 14 mov byte ptr ds:[8],10 ;用一个内存单元存储除数10,注意不要用到已经用过的内存空间 15 16 s: mov ah, 0 17 mov al, [si] 18 div byte ptr ds:[8] ;被除数x除10的余数和商保存在ax中 19 call printNumber 20 call printSpace 21 22 inc si 23 loop s 24 25 mov ax, 4c00h 26 int 21h 27 28 printNumber: 29 mov bx, ax ;这里用bx暂存,因为输出字符要用到ax 30 or bh, 30h ;转换为数字的ASCII码值 31 or bl,30h 32 mov ah,2 ;准备输出字符 33 mov dl,bl ;先输出商 34 int 21h; 35 mov dl,bh ;再输出余数 36 int 21h; 37 ret 38 39 printSpace: 40 mov ah, 2 41 mov dl, ' ' 42 int 21h 43 ret 44 45 code ends 46 end start
2)运行测试截图

4. 实验任务4
在屏幕上以指定颜色、指定行,在屏幕上输出字符串。
1)task4.asm源码:
1 assume cs:code, ds:data 2 3 data segment 4 str db 'try' 5 len equ $ - str 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov ax, 0b800h ;显示缓冲区开头 13 mov es, ax 14 15 mov si, offset str 16 mov cx, len 17 mov bl, 2h ;颜色为绿色 18 mov bh, 0 ;行数为第0行 19 call printStr 20 21 mov si, offset str 22 mov cx, len 23 mov bl, 4h ;颜色为红色 24 mov bh, 24 ;行数为第24行 25 call printStr 26 27 mov ax, 4c00h 28 int 21h 29 30 printStr: 31 mov al, 160 ;每一行字符占用空间: 80×2=160Bytes 32 mul bh 33 mov di, ax ;ax为第bh行的偏移量 34 s: mov ah, ds:[si] 35 mov es:[di], ah ;字符 36 mov es:[di+1], bl ;颜色 37 38 add di, 2 39 inc si 40 loop s 41 ret 42 43 code ends 44 end start
2)运行测试截图

5.实验任务5
在80×25彩色字符模式下,在屏幕最后一行正中间显示学号。要求输出窗口蓝底,学号和两侧折线,以白色前景色显示。

蓝底白字:0,001,0,111=17h
1)task5.asm源码:
1 assume ds:data, cs:code 2 3 data segment 4 stu_no db '201983290278' 5 len = $ - stu_no 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov ax, 0b800h 13 mov es, ax 14 mov cx, 4000 ;每一屏的内容在显示缓冲区所占字节数:80×25×2 = 4000Bytes 15 mov di, 0 16 mov ah,17h ;蓝底白字 17 18 s1: mov al, 0 19 mov es:[di], al 20 mov es:[di+1], ah 21 add di, 2 22 loop s1 23 24 ;最后一行开始的- 25 mov di, 3840 ;第24行开始 26 mov cx, 34 ;=(160-12*2)/2/2 27 mov ah, 17h 28 s2: call printSign 29 add di, 2 30 loop s2 31 32 ;打印学号 33 mov di, 3908 ;3840+(160-12*2)/2=3840+68 34 mov si, offset stu_no 35 mov cx, len 36 mov ah, 17h 37 s3: call printStu_no 38 inc si 39 add di, 2 40 loop s3 41 42 ;最后一行最后的- 43 mov di, 3932 ;=3840-68 44 mov cx, 34 45 mov ah, 17h 46 s4: call printSign 47 add di, 2 48 loop s4 49 50 mov ax, 4c00h 51 int 21h 52 53 printStu_no: 54 mov al, [si] 55 mov es:[di], al 56 mov es:[di+1], ah 57 ret 58 59 printSign: 60 mov al, 2Dh ;- 61 mov es:[di], al 62 mov es:[di + 1], ah 63 ret 64 65 code ends 66 end start
2)运行测试截图


浙公网安备 33010602011771号