ShuangChenYue ShuangChenYue
首页
  • Cpp之旅
  • Cpp专栏
  • Effective_CPP
  • muduo网络库
  • Unix环境高级编程
  • Cpp提高编程
  • 计算机网络
  • 操作系统
  • 数据结构
  • Linux
  • 算法
  • 基础篇
  • MySql
  • Redis
  • 电子嵌入式通信协议
  • 深入浅出SSD
  • 文件系统
  • 汇编语言
  • STM32
  • 随笔(持续更新)
  • Git知识总结
  • Git备忘清单
  • Git 创建删除远程分支
  • nvm使用小结
  • 虚拟机固定 IP 地址
  • Shell 脚本学习笔记
  • VScode 插件 CodeGeeX 使用教程
  • KylinV10 将项目上传至 Github教程
  • KylinV10 安装 MySQL 教程(可防踩雷)
  • kylinV10-SP1 安装 QT
  • 高并发内存池
  • USBGUARD 项目编译环境配置
  • Power_Destory 项目
  • U 盘清除工具编译教程
  • 个人博客代码推送教程
  • SVN Trunk Branches的Merge操作
  • 如何高效阅读嵌入式项目代码
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • MFC编程随记
  • MFC实现ini配置文件的读取
  • MFC实现点击列表头排序
  • 贴图法美化Button按钮
  • MFC使用细节
  • 如何高效阅读嵌入式项目代码
  • NAND Flash
  • ARM 处理器
  • 嵌入式基础知识-存储器
  • 闪存存储和制造技术概述
  • 芯片IO驱动力
  • 主流先进封装技术介绍
  • NAND Flash基础
  • 基于PA算法的FTL引导
  • SD逻辑擦除和物理擦除
  • NAND Flash的SDR、ONFI、DDR接口
  • 【详解】Nand Flash必看知识
  • 【两万字详解】Nand Flash必看知识
  • 虎牙C++技术面经
  • 金山一面复习
  • 完美世界秋招 C++ 游戏开发面经(Cpp部分)
  • 博客搭建
  • 网站收藏箱
首页
  • Cpp之旅
  • Cpp专栏
  • Effective_CPP
  • muduo网络库
  • Unix环境高级编程
  • Cpp提高编程
  • 计算机网络
  • 操作系统
  • 数据结构
  • Linux
  • 算法
  • 基础篇
  • MySql
  • Redis
  • 电子嵌入式通信协议
  • 深入浅出SSD
  • 文件系统
  • 汇编语言
  • STM32
  • 随笔(持续更新)
  • Git知识总结
  • Git备忘清单
  • Git 创建删除远程分支
  • nvm使用小结
  • 虚拟机固定 IP 地址
  • Shell 脚本学习笔记
  • VScode 插件 CodeGeeX 使用教程
  • KylinV10 将项目上传至 Github教程
  • KylinV10 安装 MySQL 教程(可防踩雷)
  • kylinV10-SP1 安装 QT
  • 高并发内存池
  • USBGUARD 项目编译环境配置
  • Power_Destory 项目
  • U 盘清除工具编译教程
  • 个人博客代码推送教程
  • SVN Trunk Branches的Merge操作
  • 如何高效阅读嵌入式项目代码
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • MFC编程随记
  • MFC实现ini配置文件的读取
  • MFC实现点击列表头排序
  • 贴图法美化Button按钮
  • MFC使用细节
  • 如何高效阅读嵌入式项目代码
  • NAND Flash
  • ARM 处理器
  • 嵌入式基础知识-存储器
  • 闪存存储和制造技术概述
  • 芯片IO驱动力
  • 主流先进封装技术介绍
  • NAND Flash基础
  • 基于PA算法的FTL引导
  • SD逻辑擦除和物理擦除
  • NAND Flash的SDR、ONFI、DDR接口
  • 【详解】Nand Flash必看知识
  • 【两万字详解】Nand Flash必看知识
  • 虎牙C++技术面经
  • 金山一面复习
  • 完美世界秋招 C++ 游戏开发面经(Cpp部分)
  • 博客搭建
  • 网站收藏箱
  • 电子嵌入式通信协议

  • 深入浅出SSD

  • 文件系统

  • 汇编语言

    • 第1章 基础知识
    • 第2章 寄存器
    • 第3章 寄存器(内存访问)
    • 第4章 第一个程序
    • 第5章 [BX]和loop指令
    • 第6章 包含多个段的程序
    • 第7章 更灵活的定位内存地址的方法
    • 第8章 数据处理的两个基本问题
    • 第9章 转义指令
      • 9.1 操作符 offset
      • 9.2 根据位移进行转移的 jmp 指令
      • 9.3 转移的 目的地址 在指令中的 jmp 指令
      • 9.4 转移指令在寄存器中的 jmp 指令
      • 9.5 转移指令在内存中 jmp 指令
      • 9.6 jcxz 指令
      • 9.7 loop 指令
    • 第10章 CALL和RET指令
  • STM32

  • 嵌入式软件开发
  • 汇编语言
霜晨月
2025-07-09
目录

第9章 转义指令

# 第9章 转移指令

==转移指令:可以修改 IP,或同时修改 CS 和 IP 的指令统称为转移指令。==

概括而言,转移指令就是可以控制 CPU 执行内存中某处代码的指令。

8086CPU 的转移行为有以下几类:

  • 只修改 IP 时,称为段内转移,比如:jmp ax。
  • 同时修改 CS 和 IP 时,称为段间转移,比如:jmp 1000 : 0。

根据转移指令对 IP 的修改范围可分为短转移和近转移:

  • 短转移 IP 的修改范围:-128~127
  • 近转移 IP 的修改范围:-32768~32767

8086CPU 的转移指令分为以下几类:

  • 无条件转移指令(如:jmp)
  • 条件转移指令
  • 循环指令(如:loop)
  • 过程
  • 中断

# 9.1 操作符 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
1
2
3
4
5
6

上图的案例:取得标号 start 和 s 的偏移地址为 0 和 3

# 9.2 根据位移进行转移的 jmp 指令

jmp 为五条件转移指令,可以只修改 IP,也可以同时修改 CS 和 IP 。

jmp 指令要给出两种信息:

  • 转移的目的地址
  • 转移的距离(段间转移、段内短转移,段内近转移)

段内短转移格式:jmp short 标号(转到标号处执行指令)

jmp short 标号指令不包含转移的目的地址,而包含转移的位移。这个位移时根据 ”标号“ 计算出来的。

实际上,jmp short 标号的功能为:(IP)=(IP)+8位位移

  1. 8位位移 = 标号处的地址 - jmp 指令后的第一个字节的地址;
  2. short 指明此处的位移为 8 位位移;
  3. 8位位移的范围为 -128~127,用补码表示
  4. 8位位移由编译程序在编译时算出
assume cs:codesg
codesg segment
start:mov ax,0
	jmp short s
	add ax,1
      s:inc ax
codesg ends
end start
1
2
3
4
5
6
7
8

程序执行后,ax 中的值为1,因为执行 jmp short s 后,越过了 add ax,1,IP 指向了标号 s 处的 inc ax。

jmp near ptr 标号 与 jmp short 标号 功能相近,它实现的是段内近转移。

jmp near ptr 标号的功能为:(IP)=(IP)+16位位移

  1. 16位位移 = 标号处的地址 - jmp 指令后的第一个字节的地址;
  2. near ptr 指明此处的位移为 16 位位移,进行的是段内近转移;
  3. 16位位移的范围为 -32768~32767,用补码表示
  4. 16位位移由编译程序在编译时算出

# 9.3 转移的 目的地址 在指令中的 jmp 指令

jmp 指令对应的机器指令没有转移的 目的地址,而是相对于当前 IP 的转移位移。

"jmp far ptr 标号"实现的是段间转移,又称为远转移。功能如下:

  • (CS)= 标号所在段的段地址;
  • (IP) = 标号在段中的偏移地址。
assume cs:codesg
codesg segment
	start:mov ax,0
	jmp far ptr s
	db 256 dup(0)
s:	 add ax,1
	inc ax
codesg ends
end start
1
2
3
4
5
6
7
8
9

将跳转到 CS:IP 所在的地址

# 9.4 转移指令在寄存器中的 jmp 指令

指令格式:jmp 16 位 reg

功能:(IP)=(16位 reg)

# 9.5 转移指令在内存中 jmp 指令

(1)jmp word ptr 内存单元地址(段内转移)

功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址。

内存单元地址可用寻址方式的任一格式给出

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
1
2
3
4
5
6
7
8
9

(2)jmp dword ptr 内存单元地址(段间转移)

功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。

  • (CS)=(内存单元地址+2)
  • (IP)=(内存单元地址)

内存单元地址可用寻址方式的任一格式给出

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
1
2
3
4
5
6
7
8
9
10
11
12

# 9.6 jcxz 指令

jcxz 指令为有条件转移指令,所有的有条件转移指令都是短转移,对应的机器码中包含转移的位移而不是目的地址。对 IP 的修改范围都为:-128 ~ 127

  • 指令格式:jcxz 标号(如果(cx)= 0,转移到标号处执行)
  • 操作:当(cx) = 0 时,(IP)= (IP)+8位位移;
  • 8位位移 = 标号处的地址 - jcxz指令后的第一个字节的地址;
  • 8位位移由编译程序在编译时算出。
  • 当(cx)不等于0时,什么也不做,程序向下执行
  • jcxz 标号相当于 if((cx) == 0),jmp short 标号;
# 补全编程,利用 jcxz 指令,实现在内存 2000H 段中查找第一个值为0的字节,找到后,将它的偏移地址存贮在 dx 中。
assume cs:code
code segment
start: 
	mov ax,2000h
	mov ds,ax
 	 mov bx,0
s:
	mov cl, [bx]  # 注意需要保存字节
	mov ch,0
	jcxz ok
	inc bx
 	 jmp short s
ok:
	mov dx,bx
	mov ax,4c00h
 	 int 21h
code ends
end star
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 9.7 loop 指令

loop指令为循环指令,所有的循环指令都是短转移,对应的机器码中包含转移的位移,而不是目的地址。对 IP 的修改范围都为:-128 ~ 127。

指令格式:loop 标号 ((cx) = (cx) - 1),如果 (cx) ≠ 0,转移到标号处执行。

操作:

  1. (cx)=(cx)-1;
  2. 如果(cx)≠ 0,(IP)=(IP)+ 8位位移。
  • 8位位移 = 标号处的地址 - loop 指令后的第一个字节的地址;
  • 8位位移的范围为 -128~127,用补码表示;
  • 8位位移由编译程序在编译时算出。

如果(cx)= 0,什么也不做(程序向下执行)。

loop 标号相当于 (cx)--; if((cx) ≠ 0 jmp short 标号);

;************************************************************************
;利用 loop 指令,实现在内存 2000H 段中查找第一个值为零的 byte,找到后 
;将它的偏移地址存储到dx中 
;************************************************************************
assume cs:code 
code segment 
start: 
   mov ax,2000H
   mov ds,ax
   mov bx,0
s: 
   mov cl,[bx]
   mov ch,0
   inc cx      # 当cx为0,然后加一
   inc bx
   loop s     # 这边会减一,然后当cx等于0 就会直接跳到下一步ok
ok: 
   dec bx
   mov dx,bx
   mov ax,4c00h
   int 21h
code ends 
end start
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
第8章 数据处理的两个基本问题
第10章 CALL和RET指令

← 第8章 数据处理的两个基本问题 第10章 CALL和RET指令→

Theme by Vdoing | Copyright © 2023-2025 霜晨月
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式