脚本宝典收集整理的这篇文章主要介绍了实验3 转移指令跳转原理及其简单应用编程,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
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
结果
反汇编截图如下
1
编译器通过标号处的地址-loop指令后的第一个字节的地址计算跳转的8位位移,此例中标号s1的偏移地址为000D,loop指令后第一个字节的偏移地址为001B,两者相减结果为-14,跳转的位移量为-14。
2
标号s2的偏移地址为0029,loop指令后第一个字节的偏移地址为0039,两者相减结果为-10。loop指令在内的所有循环指令都是短转移,对应机器码中包含转移位移而非地址,跳转的位移量是-10。
2. 实验任务2
源码
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 ; ds:[0] 存储了s1的地址 mov word ptr ds:[2], offset s2 ; ds:[2] 存储了s2的地址 mov ds:[4], cs ; ds:[4] 存储了当前段的段地址 mov ax, stack mov ss, ax mov sp, 16 call word ptr ds:[0] ; word为短转移,把 s1 处的 IP 进栈, 然后跳转到 s1 的地址 s1: pop ax ; 把 s1 处的 IP 值送入 ax call dword ptr ds:[2] ; dword为远转移,把 s2 出的 CS:IP 值进栈, 然后跳转到 s2 处 s2: pop bx ; 把 s2 的 IP 值送入 bx pop cx ; 把 s2 的 CS 值送入 cx mov ah, 4ch int 21h code ends end start
给出分析、调试、验证后,寄存器(ax) = ? (bx) = ? (cx) = ? 附上调试结果界面截图。
① 根据call指令的跳转原理,先从理论上分析,程序执行到退出(line31)之前,寄存器(ax) =0021 寄存器(bx) =0026 寄存器(cx) =076C
② 对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证调试结果与理论分析结果是否一致。
一致的,执行call指令时,程序会跳转到指定的地址处执行,同时把call指令后面一条指令的ip或cs,ip入栈。如图,执行call far [2]指令后,程序将076C和0026依次入栈。
3. 实验任务3
源码
assume ds:data, cs:code, ss:stack data segment x db 99, 72, 85, 63, 89, 97, 55 len equ $ - x data ends stack segment dw 16 dup(?) stack ends code segment start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, 32 mov cx, len ; 由于数据都是byte型,所以len就是数据个数 ; print循环: 依次打印所有数字 print: mov ah, 0 ; 数据只有一个字节,先把ah置0,子函数中除法是以ax作为被除数的 mov al, byte ptr ds:[di] ; 把数据放入al inc di ; di指针后移 push cx ; 把cx保存起来, 子程序中会修改cx值 call printNumber ; 打印数字 call printSpace ; 打印空格 pop cx ; 恢复cx loop print mov ah, 4ch int 21h ; 子程序: printNumber ; 功能: 打印数字 ; 入口参数: ; 寄存器ax (待输出的数据 --> ax) ; 局部变量说明: ; bx -> 存储数字字符个数 printNumber: mov bx, 0 ; 获取之前位数为0 ; 逐位获取数字 ; getEach循环: 获取每一位,然后压入栈中 getEach: mov dl, 10 div dl ; 数据除10 push ax ; 将数字压入栈中(ah余数在ax里了) inc bx ; 位数+1 mov ah, 0 ; ah是余数,置0后ax表示除法的结果 mov cx, ax ; 除法结果赋给cx, 如果结果为0则说明所有位数都获取完了 inc cx ; 由于loop时会-1,这里先+1,防止出现负数 loop getEach ; 打印数字 mov cx, bx ; 先把bx存的数字位数赋给cx ; printEach循环: 依次从栈中取出数字,逐位打印 printEach: pop ax ; 取出一位数 add ah, 30h ; ah是刚才除法的余数,也就是需要得到的位数,+30h是转成对应字符 mov dl, ah ; 放到dl, 用于打印 mov ah, 2 ; 调用int 21h的2号子程序打印 int 21h loop printEach ret ; 子程序: printSpace ; 功能: 打印空格 printSpace: mov ah, 2 mov dl, 20h int 21h ret code ends end start
运行结果:
4. 实验任务4
源码
1 assume cs:code, ds:data 2 data segment 3 str db 'try' 4 len equ $ - str 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 12 mov si, offset str 13 mov bh, 0 14 mov bl, 2 15 call printStr 16 17 mov si, offset str 18 mov bh, 24 19 mov bl, 4 20 call printStr 21 22 mov ah, 4ch 23 int 21h 24 25 printStr:mov cx, len 26 s:mov ax, 0b800h 27 mov dx, cx 28 mov ch, 0 29 mov cl, bh 30 t:add ax, 10 31 loop t 32 mov cx, dx 33 mov es, ax 34 mov di, si 35 add di, si 36 mov al, [si] 37 mov es:[di], al 38 mov es:[di].1, bl 39 inc si 40 loop s 41 ret 42 code ends 43 end start
运行结果:
如图,打印了字符。
5. 实验任务5
源码:
assume cs:code, ds:data data segment stu_no db '201983290067' len = $ - stu_no data ends code segment start: mov ax, data mov ds, ax mov di, 0 call printStuNum ; 调用打印子程序 mov ah, 4ch int 21h ; 打印子程序: ; 参数说明: ; 学号字符串存储在 -> ds:[di] printStuNum: mov ax, 0b800h mov es, ax ; 控制显存区域段指针 mov si, 1 ; 显存区域列指针 ; 先把屏幕前24行背景打印成蓝色 mov al, 24 ; 前24行 mov dl, 80 ; 每行80个字符需要修改颜色 mul dl ; 24*80, 获得需要填充蓝色的字符数 mov cx, ax printBlue: mov al, 17h ; 蓝底+白字:0 001 0 111 -> 17h mov es:[si], al ; 把颜色填充到位 add si, 2 ; 后移2个 loop printBlue sub si, 1 ; 指针回退一个, 从最后一行起始位置开始 ; 打印最后一行 mov ax, 80 sub ax, len ; 80列 - 学号长度 mov dl, 2 div dl ; (80 - len)/2, 就是学号左右两侧需要填充'-'的长度 mov dx, ax ; 使用dx保存'-'的长度 ; 调用打印'-'的子程序, 打印学号左侧的'-' mov cx, dx call printSeparator ; 打印学号字符串 mov cx, len printNumber: mov al, ds:[di] ; 低位是字符 mov ah, 17h ; 高位是颜色 mov word ptr es:[si], ax ; 按字放入 inc di add si, 2 loop printNumber ; 再次调用打印'-'的子程序, 打印学号右侧的'-' mov cx, dx call printSeparator ret ; 子程序: 打印分隔符'-' ; 参数: 长度 -> cx ; 位置 -> es:[si] printSeparator: mov al, '-' mov ah, 17h mov word ptr es:[si], ax add si, 2 loop printSeparator ret code ends end start
以上是脚本宝典为你收集整理的实验3 转移指令跳转原理及其简单应用编程全部内容,希望文章能够帮你解决实验3 转移指令跳转原理及其简单应用编程所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。