实验3 转移指令跳转原理及其简单应用编程
1. 实验任务1
task1.asm
assume cs:code, ds:data data segment x db 1, 9, 3 len1 equ $ - x ;符号常量, $指下一个数据项的偏移地址 y dw 1, 9, 3 len2 equ $ - y data ends code segment start: mov ax, data mov ds, ax mov si, offset x mov cx, len1 mov ah, 2 s1:mov dl, [si] or dl, 30h int 21h mov dl, ' ' int 21h inc si loop s1 mov ah, 2 mov dl, 0ah int 21h mov si, offset y mov cx, len2/2 mov ah, 2 s2:mov dx, [si] or dl, 30h int 21h mov dl, ' ' int 21h add si, 2 loop s2 mov ah, 4ch int 21h code ends end start
回答问题:
① line27, 汇编指令 loop s1 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码, 分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明是如何计算得到跳转后标号s1其后指令的偏移地址的。
loop s1 机器码为 E2F2,E2为loop的机器码,F2为位移量,由于F2是补码形式,将其转为十进制数应为 -14 ,即跳转的位移量 = -14。
从CPU的角度,程序执行完 loop s1后,IP保存的是下一条指令的地址,也就是001B,001Bh+(-14d)= 001Bh+(-Eh)=000Dh
② line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码, 分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明是如何计算得 到跳转后标号s2其后指令的偏移地址的。
loop s2 机器码为 E2F0,E2为loop的机器码,F0为位移量,由于F0是补码形式,将其转为十进制数应为 -16 ,即跳转的位移量 = -16。
从CPU的角度,程序执行完 loop s2后,IP保存的是下一条指令的地址,也就是0039,0039h+(-16d)= 0039h+(-10h)=0029h
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
① 根据call指令的跳转原理,先从理论上分析,程序执行到退出(line31)之前,寄存器(ax) = offset s1 , 寄存器 (bx) = offset s2, 寄存器(cx) = cs.
原因:cpu执行call word ptr ds:[0]时,将当前IP压入栈中(当前IP指向call指令的下一条语句,也就是offset s1),然后跳转到s1处执行pop ax,将栈顶出栈并赋给ax。cpu执行call dword ptr ds:[2]时,将CS(当前段地址)、IP(当前IP指向call指令的下一条语句,也就是offset s2)压入栈中,然后跳转到s2处执行pop bx,将栈顶IP出栈并赋给bx,再执行pop cx,将栈顶CS出栈赋给cx。
② 对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证,得调试结果与理论分析结果一致。
3. 实验任务3
task3.asm
assume cs:code, ds:data data segment x db 99, 72, 85, 63, 89, 97, 55 len equ $- x data ends code segment start: mov ax, data mov ds, ax mov cx, len mov si, offset x mov byte ptr ds:[len], 10 s: mov al, [si] mov ah, 0 div byte ptr ds:[len] call printNumber call printSpace inc si loop s mov ah, 4ch int 21h printNumber: mov bx, ax ;输出要用到ah or bh, 30h or bl, 30h mov ah, 2 mov dl, bl int 21h mov dl, bh int 21h ret printSpace: mov ah, 2 mov dl, ' ' int 21h ret code ends end start
4. 实验任务4
task4.asm
5. 实验任务5
task5.asm
assume cs:code, ds:data data segment stu_no db '201983300334' len = $ - stu_no data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800h ;显存段地址 mov es, ax mov si, offset stu_no mov cx, 4000/2 mov ah, 17h ;窗口蓝底,前景色白色,0,001,0,111=17h mov di, 0 call setcolor ;整个窗口80*2*25=4000字节,25行开始处的偏移地址为3840 mov di, 3840 mov cx, 34 ;(160-12*2)/2/2(每个字符占2字节) call print_ ;打印学号左侧---- mov di, 3908 ;3840+68 mov cx, len call print_stuno mov di, 3932 ;3908+12*2 mov cx, 34 call print_ ;打印学号右侧---- mov ah, 4ch int 21h setcolor: mov al, 0 s: mov es:[di], al mov es:[di+1], ah add di, 2 loop s ret print_: s1: mov byte ptr es:[di], '-' add di, 2 loop s1 ret print_stuno: s2: mov al, ds:[si] mov es:[di], al inc si add di, 2 loop s2 ret code ends end start