第九章 转移指令的原理

8086CPU的转移指令分为以下几类:
1.无条件跳转指令(如:jmp)
2.条件跳转指令
3.循环指令(如:loop)
4.过程,就像C语言中的函数
5.中断

9.1 操作符offset

​ 操作符offset(伪指令)在汇编语言中由编译器处理,它的功能是取标号的偏移地址。

assume cs :codesg
codesg segment
start : mov ax,offset start;相当于mov ax,0
s :     mov ax,offset s;相当于mov ax,3
codesg ends
end start

在上面的程序中,offset操作符取得了标号start和s的偏移地址0和3,所以指令:mov ax,offset start相当于指令mov ax,0,因为start是代码段中的标号,它所标记的指令是代码段中的第一条指令,偏移地址为0;
mov ax,offset s相当于指令mov ax,3,因为s是代码段中的标号,它所标记的指令是代码段中的第二条指令,第一条指令长度为3个字节,则s的偏移地址为3。

使该程序在运行中将s处的一条指令复制到s0处。
分析:
(1) s 和s0 处的指令所在的内存单元的地址是多少? cs:offset s和 cs:offset s0。

(2)将s 处的指令复制到s0 处,就是将cs:offset s 处的数据复制到cs:offset s0处。

(3)段地址已知在cs 中,偏移地址 offset s和 offset s0已经送入si和di中。

(4)要复制的数据有多长? mov ax,bx指令的长度为两个字节,即1个字。

assume cs : codesg
codesg segment
s : mov ax,bxmov ax,bx的机器码占两个字节mov si, offset smov di, offset s0mov ax,cs: [si]mov cs: [di] ,ax
s0 :nop ; nop的机器码占一个字节nop
codesg ends
end s
9.2 jmp指令

​ 1.无条件转移,可以只修改ip,也可以同时修改cs和ip
​ 1.【jmp 段地址:偏移地址】 可以用来同时修改CS和IP
​ 指令中的段地址修改CS
​ 偏移地址修改IP
​ 这种用法编译器不认识,只能做在debug中使用
​ 2.【jmp 某一合法的寄存器】 仅修改IP的内容
​ 比如:jmp ax 或者 jmp bx(类似于mov IP ax)
​ 2.jmp指令要给出两种信息:
​ 1.转移的目的地址
​ 2.转移的距离(段间转移、段内短转移、段内近转移)

9.3 依据位移进行转移的jmp指令

​ 1.jmp short 标号【转到标号处执行指令,段内短转移】
​ 此格式实现的是:段内短转移,它对ip的修改范围为-128~127
​ 2.也就是说,它向前转移时可以最多越过128个字节,负数使用补码表示
​ 向后转移可以最多越过127个字节

assume cs : codesg ;程序9.1
codesg segment
start : mov ax,0jmp short sadd ax,1
s:      inc ax
codesg ends
end start

上面的程序执行后,ax中的值为1,因为执行 jmp short s后,越过了add ax,1,IP指向了标号s处的inc ax。也就是说,程序只进行了一次ax加1操作。

汇编指令jmp short s对应的机器指令应该是什么样的呢?我们先看一下别的汇编指令和其相对应的机器指令。

assume cs : codesg ;程序9.2
codesg segment
start : mov ax ,0mov bx, 0jmp short sadd ax,1
s :     inc ax
codesg ends
end start

(1) (CS)-0BBDH,(IP)-0006H,CS:IP指向EB 03(jmp short s 的机器码);(2)读取指令码EB 03进入指令缓冲器;
(3) (IP)=(IP)+所读取指令的长度=(IP)+2-0008H,CS:IP指向add ax,1;(4)CPU执行指令缓冲器中的指令EB 03;
(5)指令EB03执行后,(IP)=000BH,CS:IP指向inc ax。
从上面的过程中我们看到,CPU 将指令EB 03读入后,IP指向了下一条指令,即CS:0008处的add ax,1,接着执行EB 03。如果EB03没有对P进行修改的话,那么,接下来CPU将执行add ax,1,可是,CPU执行的EB 03却是一条修改IP的转移指令,执行后(IP)=000BH,CS:IP指向inc ax,CS:0008处的add ax,1没有被执行。

​ 3.CPU不需要目的地址就可以实现对ip的修改
​ jmp指令的机器码中不包含目的地址,但是可以实现跳转
​ 实现的方式,是在原地址的基础上进行一个偏移量,即位移

f7 = 11110111 减一11110110 再取反 00001001 这里是9(-9的补码是f7),所以jmp s本来下一条指令是0009指向的nop,但是收到了修改ip的指令,EB F7,0009-9 =0 跳到了s处地址的位置。

​ 4.还有一种和指令“jmp short 标号”功能类似的指令格式:
​ jmp near ptr 标号,它实现的是段内近转移
​ 功能为:(ip)=(ip)+16位位移
​ jmp short 标号是8位的位移(范围为-128~127),而jmp near ptr 标号是16位位移(范围为-32768~32767)

9.4 转移的目的地址在指令中的jmp指令

​ 前面讲的jmp指令,其对应的机器码中并没有转移的目的地址,而是相对于当前ip的转移位移
​ 1.指令“jmp far ptr 标号”
​ 实现的是段间转移,又称为远转移,这时机器码中应该明确给出【段地址】
​ 2.指令“jmp far ptr 标号”功能如下:
​ (CS)=标号所在段的段地址
​ (IP)=标号所在段中的偏移地址
​ far ptr 指明了指令用标号的段地址和偏移地址修改cs和ip

assume cs: codesg
codesg segment
start : mov ax, 0mov bx, 0jmp far ptr sdb 256 dup (0)
s:      add ax,1inc ax
codesg ends
end start

如图中所示,源程序中的db 256 dup (0),被 Debug解释为相应的若干条汇编指令。这不是关键,关键是,我们要注意一下jmp far ptr s所对应的机器码:EA 0B 01 6A 07,其中包含转移的目的地址。“0B 01 6A 07 ”是目的地址在指令中的存储顺序,高地址的“ 6A 07”是转移的段地址: 07 6A H,低地址的“0B01”是偏移地址:010BH。

9.5 转移地址在寄存器中的jmp指令

​ 指令格式:jmp 16位寄存器
​ 功能:修改ip寄存器中的值,把16位寄存器中的值送入到ip寄存器中

9.6 转移地址在内存中的jmp指令

​ 转移地址在内存中的jmp指令有两种格式:
​ 1.jmp word ptr 内存单元地址(段内转移)
​ 功能:将内存中的那个字视为一个偏移地址,然后跳转到那个偏移地址
​ 与【jmp 寄存器】功能相似
​ 内存单元地址可用寻址方式的任意格式给出

mov ax,0123H
mov ds: [ 0] , ax
jmp word ptr ds : [ 0]
;执行后,(IP)=0123H.又比如,下面的指令:
mov ax,0123H
mov [bx ] ,ax
jmp word ptr [bx];执行后,(IP)=0123H

​ 2.jmp dword ptr 内存单元地址(段间转移)
​ (ip)=(内存单元地址) ;双字中的低位字是给ip的
​ (cs)=(内存单元地址+2) ;双字中的高位字是给cs的
​ 跟【jmp 段地址:偏移地址】功能类似
​ 内存单元地址可用寻址方式的任意格式给出

mov ax,0123H
mov ds: [0] ,ax
mov word ptr ds: [2],0
jmp dword ptr ds: [ 0]
;执行后,(CS)=0,(IP)=0123H,CS:IP指向0000:0123又比如,下面的指令:
mov ax,0123H
mov [bx ] ,ax
mov word ptr [bx+2],0
jmp dword ptr [bx]
;执行后,(CS)=0,(IP)=0123H,CS:IP指向0000:0123

补充:不能直接向内存单元中加入立即数要通过寄存器,把立即数加进去

9.7 jcxz指令

​ 1.有条件跳转指令,所有的有条件跳转指令都是短转移
​ 对应的机器码中包含转移的位移,而不是目的地址。对ip的修改范围都为:-128~127(用补码表示)
另一个有条件跳转指令【loop指令】
​ 2.指令格式:jcxz 标号
如果(cx)=0,则跳转到标号处执行
​ 3.jcxz 标号 指令的操作:
​ 1.当(cx)=0时,(ip)=(ip)+8位位移
​ 2.当(cx)!=0时,什么也不做(程序继续向下执行)

​ if ( (cx) ==0 jmp short标号;

;补全编程,利用jcxz 指令,实现在内存2000H 段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。
assume cs:code
code segment
start : mov ax,2000Hmov ds , axmov bx,0
s:mov ch,0   mov cl,[bx]jcxz ok        ;当cx=0时,CS:IP指向OKinc bx     jmp short s
ok :    mov dx,bxmov ax,4c00hint 21h
code ends
end start
9.8 loop指令

​ 1.循环指令,所有的循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对ip的修改范围都为:-128~127(用补码表示)
​ 2.指令格式:loop 标号
​ 3.指令的内部操作
​ 1.cx=cx-1
​ 2.如果cx!=0,(ip)=(ip)+8位位移,跳转
​ 3.(cx)=0,什么也不做,程序向下执行(和jcxz相反)
​ cx用来控制循环的次数

;利用loop指令,实现在内存2000H段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。
assume cs:code
code segment
start : mov ax,2000Hmov ds, axmov bx,0
s:      mov cl,[bx]mov ch, 0inc cx ;要+1避免减之前就是0了。inc bxloop s
ok:     dec bx;dec指令的功能和inc相反,dec bx进行的操作为:(bx)=(bx)-1mov dx , bxmov ax,4c00hint 21h
code ends
end start
9.9 根据位移进行转移的意义

​ 1.根据位移进行转移,这样设计,方便了程序段在内存中的浮动装配
​ 可以实现代码的复用
​ 2.如果在机器码中直接给出【段地址:偏移地址】,
​ 这段程序在内存中换一个位置,则会运行不正确
​ 3.段内近转移、段内短转移都是根据位移进行转移,一共有四种方式
​ 1.jmp short ptr 标号
​ 2.jmp near ptr 标号
​ 3.jcxz 标号
​ 4.loop 标号

这段程序装在内存中的不同位置都可正确执行,因为loop s在执行时只涉及s的位移(-4,前移4个字节,补码表示为FCH),而不是s的地址。如果 loop s的机器码中包含的是s 的地址,则就对程序段在内存中的偏移地址有了严格的限制,因为机器码中包含的是s的地址,如果s 处的指令不在目的地址处,程序的执行就会出错。而loop s的机器码中包含的是转移的位移,就不存在这个问题了,因为,无论s 处的指令的实际地址是多少,loop指令的转移位移是不变的。

9.10 编译器对转移位移超界的检测

​ 注意,根据位移进行转移的指令,他们的转移范围会受到限制
​ 如果在源程序中出现了转移范围超界的问题,在编译的时候,编译器将报错

比如,下面的程序将引起编译错误:

assume cs:code
code segment
start:  jmp short sdb 128 dup (0)
s :     mov ax,0ffffh
code ends
end start

jmp short s的转移范围是-128~127,IP最多向后移动127个字节。

jmp short s的转移范围是-128~127,IP最多向后移动127个字节。

【实验八、九】

;实验8 分析下面的程序,在运行前思考:这个程序可以正确返回吗? 答案:可以。
assume cs:codesg
codesg segmentmov ax,4c00h  ;最终跳到了这里int 21h
start:  mov ax,0
s:      nop  ;jmp short s1 F6EB H 也就是eb f6 -10的补码nopmov di, offset smov si,offset s2mov ax,cs : [si] ; F6EB Hmov cs: [di] ,ax ;jmp short s1 机器码放到了上面
s0:     jmp short s
s1:     mov ax,0  ;jmp short s1本以为会跳回来,但是是加偏移地址-10int 21hmov ax,0
s2:     jmp short s1  ;nop
codesg ends
end start

实验九 编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串 ‘welcome tomasm!’。
编程所需的知识通过阅读、分析下面的材料获得。
80×25彩色字符模式显示缓冲区(以下简称为显示缓冲区)的结构:
内存地址空间中,B8000H~BFFFFH 共32KB的空间,为80×25彩色字符模式的显示缓冲区。向这个地址空间写入数据,写入的内容将立即出现在显示器上。
在80x25彩色字符模式下,显示器可以显示25行,每行80个字符(160byte),每个字符可以有256种属性(背景色、前景色、闪烁、高亮等组合信息)。
这样,一个字符在显示缓冲区中就要占两个字节,分别存放字符的ASCII码和属性。80x25模式下,一屏的内容在显示缓冲区中共占4000个字节。
显示缓冲区分为8页,每页4KB(~4000B),显示器可以显示任意一页的内容。一般情况下,显示第О页的内容。也就是说通常情况下,B8000H~B8F9FH中的4000个字节的内容将出现在显示器上。
在一页显示缓冲区中:
偏移00009F对应显示器上的第1行(80个字符占160个字节);偏移0A013F对应显示器上的第2行;
偏移140~1DF对应显示器上的第3行;

依此类推,可知,偏移F00~F9F对应显示器上的第25行。
在一行中,一个字符占两个字节的存储空间(一个字),低位字节存储字符的 ASCII码,高位字节存储字符的属性。一行共有80个字符,占160个字节
即在一行中:
0001单元对应显示器上的第1列;0203单元对应显示器上的第2列;04~05单元对应显示器上的第3列;
依此类推,可知,9E~9F单元对应显示器上的第80列。例:在显示器的0行0列显示黑低绿色的字符串’ABCDEF’('A’的ASCII码值为41H,02H表示黑底绿色)
显示缓冲区里的内容为:

注意,闪烁的效果必须在全屏 DOS方式下才能看到。

assume cs:code , ds:data , ss : stack
data segmentdb 'welcome to masm!' ;定义要显示的字符串(共16字节加属性就是32字节)db 82h,24h,71h;定义三种颜色属性
data ends
stack segmentdw 8 dup(0)
stack ends
code segment
start:mov ax ,datamov ds , axmov ax,stackmov ss,axmov sp ,10hxor bx, bx  ;bx清零,用来索引颜色mov ax ,0b872h  ;算出屏幕第12行中间的显存的段起始位置放入ax中 也就是屏幕中第一个w的位置。;B8000H 前11行*每行160byte + 64byte(一行中间的位置80-一半的字符串字节16) = 1760+64= 1824=720H+b8000h=b8720hmov cx,3  ;s3循环控制行数,外循环为3次,因为要显示三个字符串
s3:push cx;三个进栈操作为外循环s3保存相关寄存器的值push ax;以防止它们的值在内循环中被破坏push bxmov es,ax;此时es为屏幕第12行中间的显存的段起始位置mov si ,0;si用来索引代码列的字符mov di ,0;ai用来定位目标列mov cx,10h;s1循环控制存放的字符,内循环为10h次,因为一个字符串中含10h个字节
s1:mov al,ds: [si]mov es : [di] ,alinc siadd di ,2loop s1;此循环实现偶地址中存放字符mov di,1;di的值设为1,从而为在显存奇地址中存放字符的颜色属性做准备pop bxmov al,ds : 10h [bx];取颜色属性inc bxmov cx,10h;第二个内循环也为10h次
s2:mov es:[di] , aladd di ,2loop s2;此循环实现奇地址中存放宇符的颜色属性;以下4句为下一趟外循环做准备pop axadd ax ,0ah;将显存的段起始地址设为当前行的下一行; [在段地址中加oah,相当于在偏移地址中加了0a0h (=160d) ]pop cxloop s3mov ax,4c00hint 21h
code ends
end start


用cls清屏后的效果

汇编 第九章 转移指令的原理相关推荐

  1. 第九章 转移指令的原理

    1.8086CPU转移指令分类:1.无条件转移指令(如jmp):2.条件转移指令:3.循环指令(如:loop):4.过程:5.中断. 2.offse,伪指令,功能是取得标号的偏移地址. 3.nop的机 ...

  2. 王爽 汇编语言第三版 第9章 转移指令的原理

    第九章  转移指令的原理 汇编代码: assume cs:codesgcodesg segments: mov ax,bx ; mov ax,bx 的机器码占两个字节mov si, offset sm ...

  3. 王爽汇编第九章学习笔记

    在这里0-1=ffff 有关于根据位移进行转移的意义:跳转指令与浮动装配(汇编相关),汇编语言交流,技术交流区,鱼C论坛 - Powered by Discuz! 实验八:重点关注jmp short ...

  4. 第九章 Servlet工作原理解析

    9.1 从Servlet容器说起    Servlet容器:Jetty, Tomcat等. 这里以Tomcat为例,  真正管理Servlet的容器是Context容器,一个Context对应一个WE ...

  5. 《统计学习方法》 第九章 EM算法(原理+代码)

    EM算法 EM算法是含有隐变量的概率模型极大似然估计或极大后验概率估计的迭代算法 含有隐变量的概率模型的数据表示为 θ \theta θ 这里, Y Y Y是观测变量的数据, Z Z Z是隐变量的数据 ...

  6. 开发日记-20190915 关键词 汇编语言王爽版 第九章

    第九章 转移指令的原理 可以修改IP或同事修改CS和IP和指令统称为转移指令.概括地讲,转移指令就是可以控制CPU执行内存中某处代码的指令. 8086CPU的转移行为有以下几类: 只修改IP时,称为段 ...

  7. 【机器学习实战 第九章】树回归 CART算法的原理与实现 - python3

    本文来自<机器学习实战>(Peter Harrington)第九章"树回归"部分,代码使用python3.5,并在jupyter notebook环境中测试通过,推荐c ...

  8. 《深入理解分布式事务》第九章 可靠消息最终一致性分布式事务原理

    <深入理解分布式事务>第九章 可靠消息最终一致性分布式事务原理 文章目录 <深入理解分布式事务>第九章 可靠消息最终一致性分布式事务原理 一.基本原理 二.本地消息表 1.实现 ...

  9. 《通信原理》复习笔记9----第九章数字信号的最佳接收及第九章相关例题

    系列文章链接目录 一.<通信原理>复习笔记1----第一章绪论 二.<通信原理>复习笔记1----第一章绪论相关例题 三.<通信原理>复习笔记3----第三章随机过 ...

最新文章

  1. 如何打开.npz文件
  2. SharePoint中修改密码的WEB Part之终极版:即可以修改AD,又可以修改本机用户密码的Web Part!!...
  3. aspnet网站开发实例_新手用户如何根据网站类型或应用场景选择云服务器?
  4. makefile文件编写_九图记住Makefile
  5. 7-323 逆波兰表达式 (10 分)
  6. 【多线程】并发执行指定数量的线程
  7. python中encode()函数的用法
  8. MySQL中根据A表画更新B表
  9. 数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径1...
  10. 快速排序中pivot的选取策略
  11. 校园二手交易平台设计总览
  12. w10如何共享计算机硬盘,Win10如何设置局域网磁盘共享?操作方法分享
  13. 《计算机软件著作权》申请注意事项
  14. 子组件改变父组件的两种方式
  15. WIN 10 初体验:期待越多失望越大
  16. python怎么修改字体_python怎么改字体 | 基础教程
  17. word脚注:文字与分隔符间的空格删除
  18. 细细品味B/S与C/S
  19. UltraEdit添加到右键管理
  20. Java实现五子棋对战小游戏【完整版】

热门文章

  1. uniapp 路由uni.navigateTo 传参
  2. Python3 入门100例,从入门到精通第一步
  3. 企业员工活动打卡收集照片、收集视频的小程序
  4. 连接字符串中的integrated security=true的意思是什么
  5. 易语言微信hook教程
  6. TJU【第二课堂】编程之美课程作业1
  7. reverseorder_Java集合reverseOrder()方法及示例
  8. 程序员和产品经理之间的恩怨情仇
  9. 用计算机播放vcd教案,川教版信息技术七下第11课《CD与VCD播放》教案.doc
  10. ubuntu文件夹侧边栏消失不见