实验3 转移指令跳转原理及其简单应用编程
四、实验结论
1. 实验任务1
给出程序task1.asm源码,及,运行截图
1 assume cs:code, ds:data 2 3 data segment 4 x db 1, 9, 3 ;x初始值是0(偏移地址) 5 len1 equ $ - x ; 符号常量, $指下一个数据项的偏移地址,这个示例中,是3 6 7 y dw 1, 9, 3 ;y是3 8 len2 equ $ - y ; 符号常量, $指下一个数据项的偏移地址,这个示例中,是9 9 data ends 10 11 code segment 12 start: 13 mov ax, data 14 mov ds, ax 15 16 mov si, offset x ; 取符号x对应的偏移地址0 -> si 17 mov cx, len1 ; 从符号x开始的连续字节数据项个数 -> cx 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其后指令的偏移地址的。
机器码:F2(h) --> 11110010(b) --> 00001110(b) --> -12(d十进制) (补码-->原码)
位移量的计算: d(h) - 19(h) -->13-25= -12(d十进制)
CPU根据目标偏移地址减去当前偏移地址得到位移量,计算得到跳转后标号s1其后指令的偏移地址的。
回答问题②
② line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机 器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明 是如何计算得到跳转后标号s2其后指令的偏移地址的。
位移量:F0(h)
问题③
③ 附上上述分析时,在debug中进行调试观察的反汇编截图
2. 实验任务2
给出程序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 26 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
给出分析、调试、验证后,寄存器(ax) = ? (bx) = ? (cx) = ? 附上调试结果界面截图。
① 根据call指令的跳转原理,先从理论上分析,程序执行到退出(line31)之前,寄存器(ax) = ? 寄存器(bx) = ? 寄存器(cx) = ?
寄存器(ax) = S1的偏移地址 寄存器 (bx) = S2的偏移地址 寄存器(cx) = S2的段地址
② 对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证调试 结果与理论分析结果是否一致。
一致。
3. 实验任务3
给出程序源码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 main: 10 mov ax, data 11 mov ds, ax 12 13 mov cx, len 14 mov si, offset x 15 print: 16 mov al, [si] 17 mov ah, 0 18 call printNumber 19 call printSpace 20 inc si 21 loop print 22 23 mov ah, 4ch 24 int 21h 25 26 ;功能:以十进制形式输出一个两位数 27 ;入口参数:寄存器ax(待输出的数据 --> ax) 28 ;出口参数:无 29 printNumber: 30 mov bl, 10 31 div bl 32 mov bx, ax 33 34 mov ah, 2 35 36 mov dl, bl ; 打印商(10位) 37 or dl, 30h 38 int 21h 39 40 mov dl, bh ; 打印余数(个位) 41 or dl, 30h 42 int 21h 43 ret 44 45 printSpace: 46 mov ah, 2 47 mov dl, ' ' 48 int 21h 49 ret 50 51 code ends 52 end main
运行测试截图
4. 实验任务4
给出程序源码task4.asm
1 assume cs:code 2 data segment 3 str db 'try' 4 len equ $ - str 5 data ends 6 code segment 7 main: 8 mov ax, 0b800h 9 mov es, ax 10 11 first_print: 12 mov ax, data 13 mov ds, ax 14 mov si, offset str 15 mov cx, len 16 mov bl, 00000010b ; 黑底绿字 17 mov bh, 0 ; 第0行 18 call printStr 19 20 second_print: 21 mov si, offset str 22 mov cx, len 23 mov bl, 00000100b ; 黑底红字 24 mov bh, 24 ; 第24行 25 call printStr 26 27 mov ah, 4ch 28 int 21h 29 30 ; 入口参数: 31 ; 字符串首字符地址 --> ds:si(其中,字符串所在段的段地址—> ds, 字符串起始地址的偏移地址—> si) 32 ; 字符串长度 --> cx 33 ; 字符串颜色 --> bl 34 ; 指定行 --> bh (取值:0 ~24) 35 printStr: 36 push bp 37 push di 38 39 mov ah, 0 40 mov al, 160 41 mul bh 42 mov bp, ax 43 mov di, si 44 printChar: 45 mov al, ds:[si] 46 mov es:[bp+di], al ; 字符 47 mov es:[bp+di+1], bl ; 颜色 48 inc si 49 inc di 50 inc di 51 loop printChar 52 53 pop bp 54 pop di 55 ret 56 code ends 57 end main
运行测试截图
5. 实验任务5
给出程序源码task5.asm
1 assume cs:code, ds:data 2 data segment 3 stu_no db '201983290357' 4 len = $ - stu_no 5 data ends 6 7 code segment 8 main: 9 call print_blue_screen 10 call print_stu_no 11 12 mov ah, 4ch 13 int 21h 14 print_blue_screen: 15 push ax 16 push es 17 push si 18 19 mov ax, 0b800h 20 mov es, ax 21 mov cx, 2000 22 mov si, 1 23 single_blue: 24 mov byte ptr es:[si], 00010000b 25 inc si 26 inc si 27 loop single_blue 28 29 pop si 30 pop es 31 pop ax 32 ret 33 34 print_stu_no: 35 push ax 36 push es 37 push si 38 push ds 39 push di 40 prefix: 41 mov ax, 0b800h 42 mov es, ax 43 mov cx, 34 44 mov si, 3840 ; si存放每次显存输出的偏移地址 45 call print_dash 46 content: 47 mov ax, data 48 mov ds, ax 49 mov cx, len 50 mov di, 0 ; di存放data中每个字符的偏移地址 51 single_no: 52 mov al, ds:[di] 53 inc di 54 mov byte ptr es:[si], al 55 inc si 56 mov byte ptr es:[si], 00010111b 57 inc si 58 loop single_no 59 postfix: 60 mov cx, 34 61 call print_dash 62 63 pop di 64 pop ds 65 pop si 66 pop es 67 pop ax 68 ret 69 70 ; 输入参数: 71 ; 显示的基地址si 72 ; 输出长度cx 73 ; 输出: 74 ; 迭代后的基地址si 75 print_dash: 76 single_dash: 77 mov byte ptr es:[si], '-' 78 inc si 79 mov byte ptr es:[si], 00010111b 80 inc si 81 loop single_dash 82 ret 83 84 code ends 85 end main
运行测试截图
五、实验总结
1.符号常量, $指下一个数据项的偏移地址。
2.EQU是等值命令:
COUNT EQU 100;令COUNT的值为100,存储器中为变量分配 0个字节;
COUNT DB 100 ;应该是令count的值为100的偏移地址。
3.OFFSET 运算符返回数据标号的偏移量。这个偏移量按字节计算,表示的是该数据标号距离数据段起始地址的距离。