《汇编语言》- 读书笔记 - 第7章- 更灵活的定位内存地址的方法

news2024/9/9 0:14:10

《汇编语言》- 读书笔记 - 第7章- 更灵活的定位内存地址的方法

  • 7.1 and 和 or 指令
  • 7.2 关于 ASCII 码
  • 7.3 以字符形式给出的数据
    • 程序 7.1
  • 7.4 大小写转换的问题
  • 7.5 [bx+idata] (变量 + 固定偏移量)
    • 问题 7.1
  • 7.6 用[bx+idata]的方式进行数组的处理
  • 7.7 SI 和 DI (源地址>目标地址)
    • 问题 7.2
    • 问题 7.3
  • 7.8 [bx+si]和[bx+di]
    • 问题 7.4
  • 7.9 [bx+si+idata]和[bx+di+idata]
    • 问题 7.5
  • 7.10 不同的寻址方式的灵活应用
    • 问题 7.6
    • 问题 7.7
    • 问题 7.8
  • 问题7.9
  • 实验 6 实践课程中的程序

7.1 and 和 or 指令

  1. and 指令: 逻辑与指令,按位进行与运算
mov al, 00001111b
and al, 01010101b
;结果: 00000101b  双方都为1的位为1,其他为0
  1. or 指令: 逻辑或指令,按位进行或运算
mov al, 00001111b
and al, 01010101b
;结果: 01011111b  只要有1方为1的位就为1,双方都是0的位为0

7.2 关于 ASCII 码

计算机只认01
于是人们定义了很多规则,ASCII就是一种文字的编码规则
比如小写字母aASCII中定义它的编码是97
于是在读写a的过程就是:

  • 写a
    1. 按下键盘a
    2. 程序收到aASCII规则编码,得到 97
    3. 97 转成二进制 1100001保存。(内存或硬盘)
  • 读a
    1. 程序从内存读取到1100001计算机知道这就是10进制的97
    2. 使用ASCII规则解码,97代表小写a
    3. 通知显卡将a画出来。(前面介绍过就是写显存,具体怎么画是显示的工作了)

可见数据本身是死的,只有程序按特定规则去处理它,它才有意义。
假如有另一个程序,它包含着另一套规则,那当它读到 1100001 又是完全不同的含义了。

7.3 以字符形式给出的数据

在汇编程序中,用'......'(单引号括字符)的方式声明字符数据,编译器会把它们转化为相应的ASCII码。

程序 7.1

assume cs:code, ds:data

data segment	;16字节
	db 'Jerry'	; 4A 65 72 72 97
	db 'abc'	; 61 62 63
data ends

code segment
start:	mov al, 'a'
		mov bl, 'b'
		
		mov ax, 4c00h		
		int 21h
code ends
end start

在这里插入图片描述
编译器把字符转成了ASCII码。

7.4 大小写转换的问题

在这里插入图片描述

  1. 观察ASCII码表(虽然不然能观察规律就行),大小写字母的ASCII码相关32
  2. 大小写转换时,大转小 + 32,小转大-32。(但是ASCII设计的很巧妙,我们不用去判断当前的大小写)
  3. Aa 区别就是第6位。00100000b = 20H = 32
    01000001
    01100001

利用位运算 and 1101 1111 实现转大写。(第6位置0,其他位不变)

	  A:01000001  a:01100001
and	20H:11011111	11011111
-----------------------------
	  A:01000001  A:01000001

利用位运算 or 0010 0000 实现转小写。(第6位置1,其他位不变)

	  A:01000001  a:01100001
or	20H:00100000	00100000
-----------------------------
	  a:01100001  a:01100001

在这里插入图片描述

7.5 [bx+idata] (变量 + 固定偏移量)

idata:表示常量。
mov ax, [bx+200] 表示,从内存 ((ds)*16+(bx)+200) 取出数据送入 ax
[]中的最终结果是物理地址:bx的内容 + 常量 200,得到物理地址后,再从地址取出内容。

问题 7.1

写出下面的程序执行后,ax、bx、cx 中的内容

code segment				; ax	bx		cx		ds
start:	mov ax, 2000h		; 2000
		mov ds, ax          ; 						2000
		mov bx, 1000h       ;		1000
		mov ax, [bx]        ; 00BE
		mov cx, [bx+1]      ; 				0600			
		add cx, [bx+2]      ;				0606
code ends                   
end start

在这里插入图片描述

7.6 用[bx+idata]的方式进行数组的处理

idata: 按传址理解,idata就相当于数组地址
bx: 表示遍历量,相当于遍历数组时的 i

将 data 中定义的第一个字符串转化为大写,第二个字符串转化为小写。

assume cs:code;, ds:data

data segment	;16字节
	db 'jerry'
	db 'ABCDE'
data ends

code segment			
start:	mov ax, data	
		mov ds, ax  
		
		mov bx, 0			; i = 0		
		mov cx, 5			; len = 5
	s:	mov al, [0+bx]		; 0表示第一个数组的位置 bx表示索引
		and al, 11011111b	; 转大写
		mov [0+bx], al		; 送回内存
		
		mov al, [5+bx]		; 5表示第二个数组的位置 bx表示索引
		or  al, 00100000b	; 转小写
		mov [5+bx], al		; 送回内存
		
		inc bx				; i++
		loop s				; cx--; cx != 0 继续循环,循环结束
		
		mov ax, 4c00h
		int 21h
code ends                   
end start

在这里插入图片描述

7.7 SI 和 DI (源地址>目标地址)

sidi 是 8086CPU 中和 bx 功能相近的存器。
si 和 di 不能够分成两个 8 位存器来使用。

  • 常见用法是在两块内存间复制数据时:
    ds:si 指向来源
    ds:di 指向目的地

问题 7.2

sidi 实现将字符串welcome to masm!!复制到它后面的数据区中。

assume cs:codesg,ds:datasg
datasg segment
	db 'welcome to masm!'	;16字节
	db '................'	;16字节
datasg ends

codesg segment			
start:	mov ax, datasg	
		mov ds, ax
		mov si, 0			; 指向第一行字符开头
		mov di, 16			; 指向第二行字符开头
		
		mov bx, 0			; i = 0	对应字符索引	
		mov cx, 8			; len = 8 每次复制一个字,共循环处理8次
	s:	mov ax, [si+bx]		; 取第一行的第bx个字符
		mov[di+bx], ax		; 送到第二行的第bx位
		add bx, 2			; i++ (每次偏移1个字 = 2字节)
		loop s				; cx--; cx != 0 继续循环,循环结束
		
		mov ax, 4c00h
		int 21h
codesg ends                   
end start

在这里插入图片描述

问题 7.3

优化 问题 7.2 减少代码量。
可以利用[bx+idata][si+idata][di+idata]的方式,来减化。

assume cs:codesg,ds:datasg
datasg segment
	db 'welcome to masm!'	;16字节
	db '................'	;16字节
datasg ends

codesg segment			
start:	mov ax, datasg	
		mov ds, ax
		mov si, 0			; i = 0
		mov cx, 8			; len = 8 每次复制一个字,共循环处理8次
	s:	mov ax, 0[si]		; 取第一行(偏移量0)的第bx个字符
		mov 16[si], ax		; 送到第二行(偏移量16)的第bx位
		add si, 2			; i++ (每次偏移1个字 = 2字节)
		loop s				; cx--; cx != 0 继续循环,循环结束
		
		mov ax, 4c00h
		int 21h
codesg ends                   
end start

在这里插入图片描述

7.8 [bx+si]和[bx+di]

bx+变量,更加灵活
例如数组操作:
si:表示原数组(指向数组第一个元素在内存中的地址)
di:表示目标数组(指向数组第一个元素在内存中的地址)
bx:表示索引
如此可方便的一个循环中对两个数组进行操作。

问题 7.4

写出下面的程序执行后,ax、bx、cx 中的内容

; 2000:1000 BE 00 06 00 00 00
assume cs:codesg
codesg segment			    ; ax	bx		cx		ds		si		di
start:	mov ax, 2000H	    ; 
		mov ds, ax          ; 						2000
		mov bx, 1000H		; 		1000
		mov si, 0		    ; 								0000
		mov ax, [bx+si]		; 00BE
		inc si				;								0001
		mov cx, [bx+si]		;				0600
		inc si				;								0002
		mov di, si			;										0002
		add cx, [bx+di]		;				0606
		mov ax, 4c00h		
		int 21h
codesg ends                   
end start

在这里插入图片描述

7.9 [bx+si+idata]和[bx+di+idata]

bx+变量+常量,更更加灵活
例如二维数组操作:(通过偏移量,实现行列的概念)
idata:表示二维数组(指向数组第一个元素在内存中的地址)
bx:表示行(相当于嵌套for中,第一层for的 i)
di:表示例(相当于嵌套for中,第二层for的 j)

问题 7.5

写出下面的程序执行后,ax、bx、cx 中的内容

; 2000:1000 BE 00 06 00 6A 22
assume cs:codesg
codesg segment			    ; ax	bx		cx		ds		si		di
start:	mov ax, 2000H	    ; 
   	mov ds, ax          ; 						2000
   	mov bx, 1000H		; 		1000
   	mov si, 0		    ; 								0000
   	mov ax, [bx+2+si]	; 0006
   	inc si				;								0001
   	mov cx, [bx+2+si]	;				6A00
   	inc si				;								0002
   	mov di, si			;										0002
   	add cx, [bx+2+di]	;				8C6A(6A00+226A)
   	mov ax, 4c00h		
   	int 21h
codesg ends                   
end start

在这里插入图片描述

7.10 不同的寻址方式的灵活应用

  1. [idata]用一个常量来表示地址,可用于直接定位一个内存单元;
  2. [bx]用一个变量来表示内存地址,可用于间接定位一个内存单元;
  3. [bxtidata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元;
  4. [bx+si]用两个变量表示地址;
  5. [bx+sitidata]用两个变量和一个常量表示地址。

可以看到,从[idata]一直到[bx+sitidata],都是为了使用更加灵活的方式来定位一个内存单元的地址。这使我们可以从更加结构化的角度来看待所要处理的数据。
本质就是先将[]寄存器常量表达式算出结果,作为物理地址,然后指向那块内存。

问题 7.6

编程,将 datasg 段中每个单词的头一个字母改为大写字母
在这里插入图片描述

assume cs:codesg,ds:datasg
datasg segment				;16*6=16字节
	db	'1. file         '	;16字节,末尾空格填充
	db	'2. edit         '  ;16字节,末尾空格填充
	db	'3. search       '  ;16字节,末尾空格填充
	db	'4. view         '  ;16字节,末尾空格填充
	db	'5. options      '  ;16字节,末尾空格填充
	db	'6. help         '  ;16字节,末尾空格填充
datasg ends
codesg segment
 start:	mov ax, datasg
		mov ds, ax
		
		mov bx, 0
		mov cx, 6
 	s:	mov al,[bx+3]		; 取 bx行第3列
		and al, 11011111b	; 转大写
		mov [bx+3], al		; 送回内存
		add bx, 16
		loop s
		
		mov ax, 4c00h		
		int 21h
codesg ends
end start

在这里插入图片描述

问题 7.7

编程,将 datasg 段中每个单词改为大写字母
在这里插入图片描述
这段是反面教材,两个循环共用 CX 陷入死循环。

assume cs:codesg,ds:datasg
datasg segment				;16*4=24字节
	db	'ibm             '	;16字节,末尾空格填充
	db	'dec             '  ;16字节,末尾空格填充
	db	'dos             '  ;16字节,末尾空格填充
	db	'vax             '  ;16字节,末尾空格填充

datasg ends
codesg segment
 start:	mov ax, datasg
		mov ds, ax
		
		mov bx, 0
		mov cx, 4			; 循环4次对应4行
	s0: mov si, 0			; 每行的字符索引从0开始
		mov cx, 3			; 本意是循环3次对应3个字符
							; 但是它覆盖了上面“行”的循环计数。
							; 两层循环共用同一个cx计数,就崩了。
		
 	s:	mov al,[bx+si]		; 取 bx行第3列
		and al, 11011111b	; 转大写
		mov [bx+si], al		; 送回内存
		inc si				; 内层循环j++ 指向下一个字符
		loop s				; 内层循环
		
		add bx, 16			; 外层循环i++ 指向下一歫
		loop s0				; 外层循环
		
		mov ax, 4c00h		
		int 21h
codesg ends
end start

问题 7.8

修复7.7的错误。在每次开始内层循环的时候,将外层循环的 cx 中的数值保存起来,在执行外层循环的 loop 指令前,再恢复外层循环的 cx 数值。可以用寄存器 dx 来临时保存 cx 中的数值,改进的程序如下。

assume cs:codesg,ds:datasg
datasg segment				;16*4=24字节
	db	'ibm             '	;16字节,末尾空格填充
	db	'dec             '  ;16字节,末尾空格填充
	db	'dos             '  ;16字节,末尾空格填充
	db	'vax             '  ;16字节,末尾空格填充

datasg ends
codesg segment
 start:	mov ax, datasg
		mov ds, ax
		
		mov bx, 0
		mov cx, 4			; 循环4次对应4行
	s0: mov dx, cx			; 将外层循环的 cx 值保存在 dx 中
		mov si, 0			; 每行的字符索引从0开始
		mov cx, 3			; 循环3次对应3个字符
		
 	s:	mov al,[bx+si]		; 取 bx行第3列
		and al, 11011111b	; 转大写
		mov [bx+si], al		; 送回内存
		inc si				; 内层循环j++ 指向下一个字符
		loop s				; 内层循环
		
		add bx, 16			; 外层循环i++ 指向下一行
		mov cx, dx			; 用 dx 中存放的外层循环的计数值恢复 cx
		loop s0				; 外层循环
		
		mov ax, 4c00h		
		int 21h
codesg ends
end start

在这里插入图片描述

问题7.9

编程,将 datasg 段中每个单词的前 4 个字母改为大写字母

assume cs:codesg,ss:stacksg,ds:datasg

stacksg segment				;16字节
	dw 0,0,0,0,0,0,0,0
stacksg ends

datasg segment				;64字节
	db '1. display      '	;16字节
	db '2. brows        '	;16字节
	db '3. replace      '   ;16字节
	db '4. modify       '   ;16字节
datasg ends

codesg segment	
start:
codesg ends                   
end start

在这里插入图片描述

实验 6 实践课程中的程序

《汇编语言》- 读书笔记 - 实验6 实践课程中的程序

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

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

相关文章

软件测试测试环境搭建很难?一天学会这份测试环境搭建教程

如何搭建测试环境?这既是一道高频面试题,又是困扰很多小伙伴的难题。因为你在网上找到的大多数教程,乃至在一些培训机构的课程,都不会有详细的说明。 你能找到的大多数项目,是在本机电脑环境搭建环境,或是…

Linux服务器上如何安装OpenCV的库?

Linux上安装OpenCV其实挺简单的。对于Python来说,可以直接使用pip进行安装,如: pip3 install opencv-python 当然,如果你是想在C或者Java内作为外部包使用,你可以考虑编译安装。 安装依赖 首先是依赖安装问题&#…

LED屏控制卡

LED屏控制卡(LED Screen Control Card)是一种用于控制和管理LED显示屏的关键设备。它通常是一个硬件设备,具有处理器、存储器、接口和软件功能,用于接收、解码和显示图像、视频和其他多媒体内容。 以下是LED屏控制卡的一些重要特点…

JVM (基础概念、类加载过程、垃圾回收算法)

目录 一、JVM 是什么 二、JVM 运行流程 三、Java运行时数据区 1、程序计数器(线程私有) 2、栈区(线程私有) 3、堆 4、方法区 四、OOM内存溢出和内存泄漏 1、OOM内存溢出 2、内存泄漏 五、类加载过程 1、加载 2、连接…

PMP课堂模拟题目及解析(第14期)

131. 项目经理正在制定干系人参与计划,并识别到一位权力等级较高但在项目中兴趣较低的干系人,项目经理应该如何对待该干系人? A. 重点管理 B. 随时告知 C. 监督 D. 令其满意 132. 项目经理识别到项目干系人具有明显不同的需求和期望。…

不合格机器人工程专业讲师笔记-230529-

工作八年,最大的遗憾,就是对不起学生,对不起同事,对不起领导,各项工作都没有做好。 但是由于个人水平低,能力差,唯一能做的就是在忏悔中不断总结,避免一次又一次失败。 一万句&…

别让测试岗位的坑太大,10年老鸟亲身经历告诉你如何避开陷阱

测试岗位一直是IT行业中备受争议的一个职业,有人看重其重要性,有人则认为这是个巨坑。如果你也对测试岗位存在疑虑和担忧,那么这篇文章一定能帮到你! 作者是一位在测试领域摸爬滚打了10年的老鸟,他深刻地理解了测试工…

行业报告 | 智能制造在中国—中国机器视觉产业链现状分析

文 | BFT机器人 导语 Introduction 智能制造装备是指具有感知、分析、推理、决策、控制功能的制造装备,它是先进制造技术、信息技术和智能技术的集成和深度融合,体现了制造业智能化、数字化和网络化的发展要求。智能制造装备的水平已成为当今衡量一个国家…

数据类岗位面试随想录

数据分析或者是偏向数据分析的数据开发岗,要求无非就是SQL、Python和业务相关的问题。 1 SQL问答 基本这些问题和期末考试的难度比,是简单的。和学校所教的比,基本超纲的问题只会有窗口函数。这一部分面试官一般不会问你难的问题&#xff0c…

通用支付系统设计

支付永远是一个公司的核心领域,因为这是一个有交易属性公司的命脉。那么,支付系统到底长什么样,又是怎么运行交互的呢?抛开带有支付牌照的金融公司的支付架构,下述链路和系统组成基本上符合绝大多数支付场景。其实整体可以看成是…

【人脸识别】insightface 使用记录和搭建服务注意点 从0到1

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1.开始1.1 前置1.2 再次运行,人脸检测跑通 前言 人脸识别项目,再走一遍。之前是公司老人留下的,没部署过,没交付…

【HMS Core】Health Kit关于获取历史数据问题

【问题描述1】 应用已经开通了历史数据访问权限,同时用户在授权页面已经勾选了”历史数据“项,然后我们是调用healthkit的rest接口查询健康数据,那么是否用户授权之前一年的健康数据都能被查询到呢? 【解决方案】 当用户授予应用…

5月底了,让我看看有多少准备跳槽的····

前两天跟朋友感慨,今年的铜三铁四、裁员导致好多人都没拿到offer!现在已经5月底了,具体金九银十只剩下3个月。 对于想跳槽的职场人来说,绝对要从现在开始做准备了。这时候,很多高薪技术岗、管理岗的缺口和市场需求也出来了。 所…

字节跳动测试岗,3面都过了,HR告诉我这个原因被刷了...

说在前面 面试时最好不要虚报工资。本来字节跳动是很想去的,几轮面试也通过了,最后没offer,自己只想到下面几个原因: 虚报工资,比实际高30%; 有更好的人选,这个可能性不大,我看还在…

6个月的测试,来面试居然要18K,我一问连8K都不值

2023年4月份我入职了深圳某家创业公司,刚入职还是很兴奋的,到公司一看我傻了,公司除了我一个自动化测试,公司的测试人员就只有2个开发3个前端1个测试还有2个UI,在粗略了解公司的业务后才发现是一个从零开始的项目&…

笔记本电脑正常开机但是桌面变成错误代码怎么办?

笔记本电脑正常开机但是桌面变成错误代码怎么办?有用户将自己的笔记本电脑开机之后,电脑可以正常开启,但是系统在加载的过程中,突然变成了一些错误代码,无法正常的到达桌面上。那么这个问题怎么去进行解决呢&#xff1…

操作系统学习系列(1.启航)-操作系统基本概念

文章目录 前言操作系统基本概述中断与硬件的基本交互基本地址地址概念启动流程应用程序与操作系统的关系 Hello World启动总结 前言 本系列博文主要用于第二阶段深入了解的408专业内容考研使用。也就是说在开启本系列之前,最好已经对408有基本的了解。重复的基础概…

推动网络安全的三大问题

网络攻击已成为技术主管和企业最关心的问题之一。预计到2025 年,网络犯罪将使公司每年损失 105 亿美元。2021 年网络犯罪的预估成本为 6.1 万亿美元,预计每年增长 15%。 企业正在增加网络安全预算以保护其资产。2022年,网络安全职位的发布数…

私域运营需要怎么样才能做好?

进入2023年,越来越多品牌商家意识到,“私域运营”已经成为品牌营销的必选项。作为私域运营的核心阵地,微信凭借社群、企业微信、小程序、视频号等多个生态插件,为品牌私域经营提供了很多创新思路,其中“社群微信管理”…

01.GATK肿瘤基因变异最佳实践SnakeMake流程:WorkFlow简介

<~生~信~交~流~与~合~作~请~关~注~公~众~号生信探索> 代码地址 https://jihulab.com/BioQuest/smkhsshttps://github.com/BioQuestX/smkhss GATK best practices workflow Pipeline summary SnakeMake workflow for Human Somatic short variants (SNPINDEL) Expected fa…