《汇编语言》- 读书笔记 - 第9章 - 转移指令的原理

news2024/11/30 10:31:59

《汇编语言》- 读书笔记 - 第9章 - 转移指令的原理

  • 总结
  • 9.1 操作符 offset
    • 问题 9.1
  • 9.2 jmp 指令
  • 9.3 依据位移进行转移的 jmp 指令
    • jmp short 标号
      • 程序 9.1
      • 程序 9.2
        • 图 9.2 程序 9.2 的机器码
    • jmp near ptr 标号
  • 9.4 转移的目的地址在指令中的 jmp 指令
    • 如何选择 jmp short、jmp near、jmp far
  • 9.5 转移地址在寄存器中的 jmp 指令
  • 9.6 转移地址在内存中的jmp 指令
    • jmp word ptr 内存单元地址(段内转移)
    • jmp dword ptr 内存单元地址(段间转移)
    • 检测点 9.1
  • 9.7 jcxz 指令
    • 1. 循环控制
    • 2. 条件分支
    • 检测点 9.2
  • 9.8 loop 指令
    • 检测点 9.3
  • 9.9 根据位移进行转移的意义
  • 9.10 编译器对转移位移超界的检测
  • 实验 8 分析一个奇怪的程序
  • 实验 9 根据材料编程

总结

本章主要介绍了转移指令的原理,这些指令允许程序在执行过程中改变控制流程,实现程序的分支循环跳转。掌握这些概念有助于深入理解计算机程序的执行机制和内存管理。

9.1 操作符 offset

问题 9.1

在这里插入图片描述
分析:

  1. ss0 都在 CS 段,偏移量也拿到分别放在了 sidi 中。
  2. ax 通用寄存器大小1个字(2字节)够存放这条语句 mov ax, bx
  3. 先把 s 标号处的第一句复制到 ax,再从 ax 复制到 s0
assume cs:codesg 

codesg segment
	s:	mov ax, bx			; mov ax,bx 的机器码占两个字节
		mov si, offset s
		mov di, offset s0
		mov ax, cs:[si]		
		mov cs:[di], ax
	s0: nop					; nop 的机器码占一个字节
		nop
codesg ends
end s

在这里插入图片描述

9.2 jmp 指令

jmp无条件转移指令,可以只修改 IP,也可以同时修改 CS 和 IP
jmp 有两种跳转思路:

  1. 偏移量跳。向前或向后N个字节。(相对跳转)
  2. 目录地址跳。跳到指定位置。(绝对跳转)

通过只修改 偏移地址 IP 还是同时修改 段地址和偏移地址 CS:IP 可以区分段内段间转移。

中文命令说明修改的
寄存器
例子(假设有标号叫 label
段内短转移jmp short 标号根据相对偏移量在当前段内进行跳转。
IP修改范围 -128 到 +127 (8位)。
IPjmp short label
段内近转移jmp near ptr 标号根据相对偏移量在当前段内进行跳转。
IP修改范围 -32768 到 +32767(16位)。
IPjmp near ptr label
段间转移
(远转移)
jmp far ptr 标号同时修改CSIP标号段地址偏移地址
以实现跨段跳转。
CS:IPjmp far ptr label
寄存器
间接转移
jmp 寄存器指定寄存器的值加载到IP。实现修改偏移地址
(段地址CS不变)
IPjmp dx
段内
间接转移
jmp word ptr [内存]将指定内存中的数据l读取到IP
读取长度一个 word(字,16位)
IPjmp word ptr [bx+si]
段间
间接转移
jmp dword ptr [内存]将指定内存中的数据l读取到CS:IP
读取长度一个 dword(双字,32位)
IP=低16位, CS=高16位
CS:IPjmp dword ptr ds:[0]
———————————————————————————————

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

使用jmp short 还是 jmp near 取决于想要跳转到的目标相对于当前指令执行位置的距离(字节)
如果该距离在 -128 ~ 127(字节)范围内,使用 jmp short
如果该距离在 -32768 ~ 32767(字节)范围内,使用 jmp near

jmp short 标号

程序 9.1

此例中因为偏移量为 03-128 ~ 127 范围内,所以使用短转移

assume cs:codesg
codesg segment
 start:	mov ax,0		; 1. 设置 ax 为 0
		jmp short s		; 2. 跳到标号 s 处
		add ax,1		; 3. 被跳过
 s:	inc ax				; 4. ax 自增 1
codesg ends				; 5. 最终执行结果 ax  为 1
end start

在这里插入图片描述
如上图查看 jmp short s 反编译的机器码对应 EB03
这里 EBJMP 指令的操作码,对应 jmp short
03就是要跳过的字节数,也就是add ax,1的机器码83C001的长度。
执行后 IP + 3 字节,跳过了 add ax,1 指向 inc ax
在这里插入图片描述
单步执行,看结果 AX=0001

程序 9.2

我们把程序 9.1 改写一下,变成下面这样:

assume cs:codesg
codesg segment
 start: mov ax,0
		mov bx,0
		jmp short s
		add ax,1
	s:	inc ax
codesg ends
end start
图 9.2 程序 9.2 的机器码

在这里插入图片描述
分析 jmp short 标号 前先回忆一下 CPU 执行指令的过程:(详见:2.10 CS和IP)

读取指令
重复
CS:IP 所指内存
指令缓冲器
IP指向下一条指令
执行当前指令

按照这个步骤,我们参照 【图 9.2】 看一下,程序 9.2 中 jmp short s 指令的读取和执行过程:

  1. (CS)=0BBDH,(IP)=0006HCS:IP 指向 EB 03( jmp short s的机器码,长度2字节);
  2. 读取指令码 EB 03 进入指令缓冲器;
  3. (IP) = (IP)+所读取指令的长度 = (IP)+2 = 0008HCS:IP 指向 add ax,1;
  4. CPU 执行指令缓冲器中的指令 EB 03;
  5. 指令 EB 03 执行后(IP+=3),(IP)=000BH,CS:IP 指向 inc ax

jmp near ptr 标号

jmp near 的偏移范围比 jmp short 更大,
如跳转的目标地址在当前代码段内,且偏移量可以使用2字节表示,则应该使用 jmp near

assume cs:codesg
codesg segment
 start:	mov ax,0		; 1. 设置 ax 为 0
		jmp near ptr s	; 2. 跳到标号 s 处
		add ax,1		; 3. 被跳过
 s:	inc ax				; 4. ax 自增 1
codesg ends				; 5. 最终执行结果 ax  为 1
end start

这段代码只是修改了 jmp near ptr s 一句。我们看下面截图:
虽然偏移量(操作数)还是 3 但此时占用了2字节
在这里插入图片描述

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

jmp far 它直接 修改CSIP实现跨段跳转

ssume cs:codesg
codesg segment
 start:	mov ax,0
		mov bx,0
		jmp far ptr s
		db 256 dup (0) 		; 被跳过
	 s:	add ax,1			; ax 中的值 +1
		inc ax				; ax 自增 1
codesg ends
end start

查看反汇编效果 jmp far
操作码:EA
操作数:偏移地址=010B 段地址=076C (在内存中存储,低位在前,高位在后)
在这里插入图片描述

在这里插入图片描述
单步执行,看结果 AX=0002

如何选择 jmp short、jmp near、jmp far

从设计的角度考虑,区分 jmp shortjmp nearjmp far 的主要原因是为了节省字节码空间。
根据上面的例子我们看到了:

指令机器码长度
jmp short2字节
jmp near3字节
jmp far5字节

在早期8086处理器的设计中,内存和存储器资源相对有限,因此指令大小对于程序大小和效率至关重要。
在现代处理器中,尽管内存不再是主要瓶颈,但这样的设计传统仍然保留下来,并且在某些嵌入式系统或对空间极度敏感的应用场景中仍然具有重要意义。

在实际编程中,现代汇编器会根据目标地址与当前指令之间的距离自动选择合适的跳转指令类型。程序员只需要指定目标地址,而无需关心具体的跳转指令类型。

jmp my_label
my_label:
    ; 业务代码略

当汇编器处理这段代码时,它会计算 jmp 指令与目标标签 my_label 之间的距离。

  1. 如果距离在 jmp short 指令的偏移量范围内(1 个字节),汇编器会生成 jmp short 指令。
  2. 如果距离超过 jmp short 指令的范围,但仍在 jmp near 指令的偏移量范围内(2 个字节),汇编器会生成 jmp near 指令。
  3. 如果距离超过 jmp near 指令的范围,汇编器会生成 jmp far 指令。

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

jmp 指令将程序的控制流跳转到 BX 寄存器中存储的地址。

assume cs:codesg
codesg segment
 start:	mov bx,s	; 把标号 s 的地址存到 bx
		mov ax,0
		jmp bx		; 跳转到 bx 寄存器中存储的地址
		add ax,1	; 这句被跳过
	s:	inc ax		; ax 自增 1
codesg ends
end start

在这里插入图片描述
在这里插入图片描述
单步执行,看结果 AX=0001

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

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

修改 IP 段内转移

assume cs:code, ds:data
data segment
    t dw offset s 		; 定义一个内存变量 t 保存标号 s 的偏移地址。
data ends

code segment
 start: mov ax, data		; 数据段偏移量存入 ax
        mov ds, ax			; 设置数据段 ds 地址
        jmp word ptr [t]	; 段内跳转,到内存变量 t 保存的址
		mov ax, 0			; 这句被跳过
     s: mov ax, 1			; 最终结果 ax 为 1
code ends
end start

在这里插入图片描述

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

同时修改 CS:IP 段间转移

assume cs:code, ds:data
data segment
    t dd 12345678h
data ends

code segment
 start: mov ax, data		; 数据段偏移量存入 ax
        mov ds, ax			; 设置数据段 ds 地址
        jmp dword ptr [t]	; 段内跳转,到内存变量 t 保存的址
code ends
end start

在这里插入图片描述
这里就确认一下 jmp 后 CSIP都正确的修改了。

检测点 9.1

《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 9.1

9.7 jcxz 指令

指令格式:jcxz 标号
jcxz(Jump if CX is Zero)指令在x86汇编语言中主要用于条件跳转,当CX寄存器的值为0时执行跳转。否则啥也不做,继续执行下一句。(所有的有条件转移指令都是短转移,对 IP 的修改范围都为: -128 ~ 127
它的常见用途包括:循环控制、条件分支

1. 循环控制

在编写循环结构时,jcxz可以用来检测循环计数器是否已经减至0,从而决定是否结束循环。
如下示例代码,循环累加 AX

assume cs:code
code segment
	start:	
		mov ax,0		; 初始化 ax 为 0
		mov cx,3		; 初始化循环次数 3 到 CX寄存器
	loop_start:
		; 循环体开始
		inc ax			; ax 自增
		; 循环体结束
		dec cx          ; 每次循环后递减CX
		jcxz loop_end   ; 如果 CX为0,则跳转到 loop_end
		jmp loop_start	; 否则跳转到 loop_start 处继续下一次循环
	loop_end:
		mov ax,4c00H
		int 21H
code ends
end start

等价于JS的 do{...}while(ax != 0)

var ax = 0, cx = 3;
do { 
    console.log(++ax);
} while (--cx);
#include <stdio.h>

int main() {
	int ax = 0, cx = 3;
    do {
        printf("Current value: %d\n", ++ax);
    } while (--cx); // cx 不等于 0 就继续
    return 0;
}

2. 条件分支

在某些算法或数据处理中,CX可能被当作条件判断的标志位。当CX代表某种条件成立与否时,可以用jcxz来进入相应的处理分支。

assume cs:code
code segment
	start:
		mov cx,0			; 将标志变量加载到 CX 寄存器中
		jcxz branch_B   	; 如果 CX 为 0,则跳转到 分支B
	branch_A:
		mov ax,6666H
		jmp branch_end		; 跳转到结束
	branch_B:
		mov ax,3333H
	branch_end:
		mov ax,4c00H
		int 21H
code ends
end start

分别演示 cx01 的效果。
在这里插入图片描述 在这里插入图片描述
总之,jcxz是一个用于简化基于CX寄存器值进行条件跳转的指令,它在需要根据CX是否为0来进行决策的场景中非常有用。不过,现代编程中往往使用高级循环结构和条件判断语句,但在底层编程和特定优化场合,jcxz仍有其独特的应用价值

检测点 9.2

《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 9.2

9.8 loop 指令

loop指令是一种条件循环指令,主要用于实现计数型循环。它依赖于CX寄存器作为循环计数器。

  1. 在执行loop指令之前,需要先将循环次数(通常是递减的次数)加载到CX寄存器中。
  2. 每次执行loop 标号时,CPU会自动将CX寄存器中的值减1
  3. 然后检查CX寄存器是否为0
    3.1. 如果CX != 0,则跳转到标号指定的地址处继续执行循环体内的代码;
    3.2. 否则CX == 0,程序流程将继续向下执行,即跳出循环。

所有的循环指令都是短转移,对 IP 的修改范围都为:-128 ~ 127
偏移量的计算方式为:标号地址 - loop 下一句的地址
以补码形式保存,在编译时获得。

loop 标号 的功能相当于:

(cx)--;
if((cx) != 0){
	jmp short 标号;
}

检测点 9.3

《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 9.3

9.9 根据位移进行转移的意义

jmp short 标号jmp near ptr 标号jcxz 标号loop 标号 这几种汇编指令,都是相对跳转。
在对应的机器码中不包含转移的目的地址,而是包含到目的地址的偏移量(字节)。
这种设计,方便了程序段在内存中的浮动装配,如:
在这里插入图片描述
这段代码中,loop s 用的相对跳转,记录的是 -4(字节) 而不是 s 的地址,这样无论这段程序加载到内存中任何位置,都能正常跳到 s
但如果使用 s 的目标地址来跳转,比如 s 的地址是2000:0000那这个地址就被限制死了。
这段程序只能加载到内存这个位置才能正常跑。如果这段内存被其它程序占用,就没法玩了。

FC说明
11111100补码
11111011反码 = 补码 - 1
10000100原码 = 反码按位取反(最左侧的符号位不动)
-4结果为 -4

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

根据位移进行相对跳转的指令,转移范围都是有限制的,
编译器会在编译时检测越界问题,如果触发会报·编译错误
所以我们只要知道偏移量是如何计算即可。实际操作中编译器在编译时会自动算好。

实验 8 分析一个奇怪的程序

《汇编语言》- 读书笔记 - 实验8 分析一个奇怪的程序

实验 9 根据材料编程

《汇编语言》- 读书笔记 - 实验9 根据材料编程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1449805.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Github用人工智能(AI)帮你的代码修正安全漏洞

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Java:继承——继承概念+父子类成员、构造访问顺序+super、this关键字(代码+画图超详解!)

一、什么是继承 1、继承的概念 举例理解&#xff1a; 根据打印机的原理&#xff0c;我们可以知道不管是彩色打印机还是黑白打印机&#xff0c;实现的都是一个功能&#xff1a;打印&#xff0c;这是二者的共性。彩色打印机和黑白打印机都继承了打印机的打印功能&#xff0c;且二…

基于T1w/T2w 比值揭示髓磷脂相关变化

前言&#xff1a; 最近在阅读文献的时候发现2篇文章&#xff0c;是采用T1w/T2w 比值表征髓磷脂&#xff0c;有点感兴趣&#xff0c;因此尝试了一下文献所提出的方法。&#xff08;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC9247578/ https://www.ncbi.nlm.nih.gov/pmc/ar…

vue的网络请求以及封装

①先备好springboot的接口 ②安装依赖 在vue中安装网络请求工具的依赖&#xff1a; npm i axios③简单的demo 直接通过axios请求尝试一下&#xff1a; <script> import axios from "axios";export default {name: HomeView,data() {return {users:[]}}, …

言语残疾和言语残疾分级

言语残疾和言语残疾分级 言语残疾&#xff0c;指各种原因导致的不同程度的言语障碍&#xff0c;经治疗一年以上不愈或病程超过两年&#xff0c;而不能或难以进行正常的言语交流活动&#xff0c;以致影响其日常生活和社会参与。包括&#xff1a;失语、运动性构音障碍、器质性构音…

app移动应用开发

1.案例7.安安的通讯助手 目标 组件设计 素材准备 所有组件的说明及属性设置&#xff08;1&#xff09; 所有组件的说明及属性设置&#xff08;2&#xff09; 所有组件的说明及属性设置&#xff08;3&#xff09;布局小技巧 行为逻辑设计 自动回复短信 短信收发器 组件 记录已收…

MongoDB部署策略

内 容 简 介 本文介绍了MongoDB数据库的优点的数据存储模式的安装部署过程。 利用MongoDB在存储海量数据上的优势&#xff0c;部署存储空间大数据。 欢迎批评指正补充 由于编者水平有限&#xff0c;所搜集资料也很有限&#xff0c;制定的规范肯定有考虑不周全、甚至完全错误…

利用路由懒加载和CDN分发策略对极客园项目进行性能优化

文章目录 前言1.配置路由懒加载2.项目资源打包3.包体积可视化分析4.cdn配置 总结 前言 极客园项目的完成之后&#xff0c;我们需要对项目进行打包以及性能优化&#xff0c;优化用户体验以及加快响应时间&#xff0c;本文只列举了路由懒加载和cdn分发的策略 1.配置路由懒加载 …

Spring Security学习(四)——登陆认证(包括自定义登录页)

前言 和前面的文章隔了很长时间才更新Spring Security系列&#xff0c;主要原因一个是之前太忙了&#xff0c;把项目都忙完了&#xff0c;赶上春节假期&#xff0c;就慢慢研究。Spring Security的体系非常复杂&#xff0c;一口吃不了热豆腐&#xff0c;没办法速成&#xff0c;…

​StableSwarmUI#超越文本的prompt

今天看到一个新的webui方案&#xff0c;是Stability-AI开源的&#xff1a; StableSwarmUI 是一个模块化的稳定扩散web用户界面&#xff0c;着重于使强大的工具易于访问、高性能和可扩展性。 由于项目还在开发中&#xff0c;我们可以先了解下&#xff0c;翻看了它的特点&#xf…

年假作业11

一、选择题 ADDAADADC&#xff0c;BD,D,B,BD,D,C,CD 二、填空题 6 2&#xff0c;3,5,7,9 rgb *s, - a 2,5 *s 三、编程题 1、 #include <iostream> using namespace std; int main() {int arr[10]{10,20,30,40,50,60,70,80,90,100};int m;//从标准输入读取一个…

[职场] 应聘销售的简历怎么写 #职场发展#笔记

应聘销售的简历怎么写 应聘销售的简历怎么写1 基本信息 姓名&#xff1a;吴x 性别&#xff1a;女 毕业院校&#xff1a;徐州师范大学计算机科学院 学历&#xff1a;大专 联系电话&#xff1a;电子邮件&#xff1a; 工作经验&#xff1a;4年 求职意向 期望从事职业&#xff1a;销…

【Spring MVC篇】返回响应

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、返回静态页面…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第三天-ARM Linux ADC和触摸屏开发 (物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd1688 提取码&#xff1a;1688 教学内容&#xff1a; 1、ADC S3C2440的A/D转换器包含一个8通道的模拟输入转换器&#xff0c;可以将模拟输入信号转换成10位数字编码。 在A/D转换时钟频率为2.5MHz时&…

ClickHouse--10--临时表、视图

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.临时表1.1 特征1.2 创建一个临时表 2.视图2.1 普通视图2.2 物化视图 1.临时表 1.1 特征 ClickHouse 支持临时表&#xff0c;临时表具备以下特征&#xff1a; 当…

7 大 Android 数据恢复软件,可轻松找回丢失的数据

每年&#xff0c;由于各种原因&#xff0c;数百万人从他们的 Android 设备中丢失数据。它可能像意外删除文件一样简单&#xff0c;也可能像系统崩溃一样复杂。在这种情况下&#xff0c;拥有高效的数据恢复工具可以证明是救命稻草。Mac 用户尤其需要找到与其系统兼容的软件。好消…

D. Divisible Pairs

思路&#xff1a;我们预处理出每个数分别摸上xy的值&#xff0c;用map存一下&#xff0c;然后遍历每个数&#xff0c;如果a b是x的倍数的话&#xff0c;那么他们模x的值相加为x&#xff0c;如果a - b是y的倍数的话&#xff0c;那么他们的模y的值相等。 代码&#xff1a; voi…

Python dict函数

Python中的字典&#xff08;dict&#xff09;是一种非常重要且灵活的数据结构&#xff0c;它提供了键值对的存储和访问机制。字典函数&#xff08;dict()&#xff09;作为创建字典的工具之一&#xff0c;可以从多种数据结构中创建字典对象。在本文中&#xff0c;将深入探讨dict…

[OPEN SQL] 删除数据

DELETE语句用于删除数据库表中的数据 本次操作使用的数据库表为SCUSTOM&#xff0c;其字段内容如下所示 航班用户(SCUSTOM) 需要删除以下数据 1.删除单条数据 语法格式 DELETE <dbtab> FROM <wa>. DELETE <dbtab> FROM TABLE <itab>. DELETE FROM &…