实验三 转移指令跳转原理及其简单应用编程
实验任务1
task1.asm :
assume cs:code, ds:data data segment x db 1, 9, 3;定义一个x[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 star
实验结果:
问题回答:
①:line27, 汇编指令 loop s1 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明是如何计算得到跳转后标号s1其后指令的偏移地址的。
loop指令可以实现指令段内短转移,在指令对应的机器码中应包含转移的偏移量,cpu计算当前地址到目标地址的位移量。通过反汇编,loop指令执行后IP变为001B,跳转到000D,偏移量为-14(向前跳转偏移量为负值)
②:line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明是如何计算得到跳转后标号s2其后指令的偏移地址的。
loop指令后IP变为0039,需要跳转到0029,所以位移量为-10
③:
实验任务2
task2.asm :
assume cs:code, ds:data data segment dw 200h, 0h, 230h, 0h data ends stack segment db 16 dup(0) stack ends code segment start: mov ax, data mov ds, ax mov word ptr ds:[0], offset s1 mov word ptr ds:[2], offset s2 mov ds:[4], cs mov ax, stack mov ss, ax mov sp, 16 call word ptr ds:[0] s1: pop ax call dword ptr ds:[2] s2: pop bx pop cx mov ah, 4ch int 21h code ends end start
实验结果:
问题回答:
① 根据call指令的跳转原理,先从理论上分析,程序执行到退出(line31)之前,寄存器(ax) = ? 寄存器(bx) = ? 寄存器(cx) = ?
ax = 0021h, bx = 0026h,cx = 076ch
② 对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证调试结果与理论分析结果是否一致。
offset将s1,s2的地址分别传入内存单元ds:[0]和ds:[2]。在执行第一次call指令时,将下一跳指令,即s1的地址入栈,然后跳转至ds:[0]中的地址,即同为s1处,执行s1中的命令,将栈中的内容放入ax,即s1的地址。同理,入栈下一跳指令的段地址和偏移地址,ax中存放了s1的地址,bx中存放了s2的地址中偏移地址部分,cx中存放了s2的地址中短地址部分。
实验任务3
assume cs:code, ds:data data segment x db 99,72,85,63,89,97,55 len equ $ - x ;len = 7 data ends code segment start: mov ax, data mov ds, ax mov si, 0 mov bl, 0ah mov cx, len s: mov al, [si] mov ah, 0 call printNumber call printSpace inc si loop s jmp exit printNumber: div bl mov dl, ah mov dh, al add dl, 30h mov ah, 2 int 21h mov dl, dh add dl, 30h int 21h ret printSpace: mov dl, ' ' int 21h ret exit: mov ah, 4ch int 21h code ends end start
实验结果:
实验任务4
assume cs:code, ds:data data segment str db 'try' len equ $ - str data ends code segment start: mov ax, data mov ds, ax mov si, 0 ;数据段指针,指向try mov cx, len ;几个字符循环几次 mov bl, 02h ;颜色 mov bh, 0 ;行位置 mov ax, 0b800h mov es, ax ;显示缓冲区段地址 mov di, 0 ;显示缓冲区指针 mov al, 0a0h ;每行80个字符,每个字符2字节,每行160字节,用来确定行首 call printStr ;调用子程序 mov si, 0 mov di, 0 mov bl, 04h mov bh, 18h mov ax, 0b800h mov es, ax mov cx, len mov al, 0a0h call printStr jmp exit printStr: mul bh ;确定行首在显示缓冲区的位置 add di, ax s: mov al, [si] mov es:[di], al ;移入字符ASCII码 mov al, bl mov es:[di+1], al ;移入属性(颜色) inc si ;try指针+1,指向下个字符 add di, 2 ;每个显示的字符占2字节,显示缓冲区指针+2 loop s ret exit: mov ah, 4ch int 21h code ends end start
实验结果:
实验任务5
assume cs:code, ds:data data segment stu_no db '201983290152' len = $ - stu_no data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800h mov es, ax mov bl, 017h mov si, 0 mov di, 0 mov al, 050h mov bh, 18h mul bh mov cx, ax s: mov es:[di+1], bl add di, 2 loop s mov cx, 022h s1: mov byte ptr es:[di], '-' mov es:[di+1], bl add di, 2 loop s1 mov cx, len s2: mov al, [si] mov es:[di], al mov es:[di+1], bl inc si add di, 2 loop s2 mov cx, 023h ;学号后面的-- s3: mov byte ptr es:[di], '-' mov es:[di+1], bl add di, 2 loop s3 code ends end start
实验结果: