[汇编语言]更灵活的定位内存地址的方法
目录
- 一、and和or指令
- 二、以字符的形式给出数据
- 三、大小写转化问题
- 四、[bx+idata]
- 五、SI和DI
- 六、[bx+si]和[bx+di] 与 [bx+si+idata]和[bx+di+idata]
- 七、不同寻址方式的灵活引用
一、and和or指令
and指令逻辑与指令,按位进行与运算
例如指令:
mov al,01100011B
and al,00111011B
执行后:al = 00100011B
通过该指令可以将操作对象的相应位设置为0,其他位不变
例如:
将al的第6位设置为0的指令是:and al,10111111B
or指令逻辑或指令,可以进行或运算
例如指令:
mov al,01100011B
or al,00111011B
执行后:al = 01111011B
可以通过该指令将操作对象的相应位设置为1,其他位保持不变
二、以字符的形式给出数据
在汇编语言中,我们用’…'的方式来指明数据是以字符的形式给出的,编译器将他们转化为相对应的ASCII码,如下面的程序:
assume cs:code,ds:datadata segment
db 'unIX'
db 'foRK'
data endscode segment
start:mov al,'a'mov bl,'b'mov ax,4c00hint 21h
code endsend start
上面的源程序中db 'unIX'
相对应是db 75H,6EH,49H,58H
分别对应unIX的ASCII码
mov al,'a'
相对应是mov al,61H
,对应a的ASCII码
可以用d命令查看data段,debug下是以16进制数码和ASCII码字符的形式显示出其中的内容
三、大小写转化问题
A 十六进制41H
a 十六进制61H
下面考虑这样一个问题,在codesg下填写代码,将datasg中的第一个字符串转化为大写,第二个字符串转化为小写
assume cs:codesg,ds:datasgdatasg segmentdb 'BaSiC'db 'iNfOrMaTiOn'
datasg endscodesg segment
start:codesg endsend start
大写字符’A’的ASCII码值+20H就可以得到’a’
小写字符’a’的ASCII码值-20H就可以得到’A’
因此我们先判断大小写,看是否需要进行转化,以BaSiC讨论,程序的流程是这样的:
assume cs:codesg,ds:datasgdatasg segmentdb 'BaSiC'db 'iNfOrMaTiOn'
datasg endscodesg segment
start:mov ax,datasgmov ds,axmov bx,0mov cx,5s: mov al,[bx] ;每个字符送入al;如果(al)> 61H,则为小写字母的ASCII码,则sub al,20Hmov [bx],al ;转化完的字符再送回去inc bxloop s;...codesg endsend start
目前问题是我们还没有学习判断的指令,所以我们如何用已学的指令来解决这个问题?
从ASCII的二进制形式来看,除了第5位外(从0开始计算位数),大小写字母的其他各位都是一样的,大写字母ASCII的第五位为0,小写字母的第5位为1,这样子我们不管他们原先是大写还是小写,将它的第五位置为0,就变为大写字母,置为1,就变为小写字母。
assume cs:codesg,ds:datasgdatasg segmentdb 'BaSiC'db 'iNfOrMaTiOn'
datasg endscodesg segment
start:mov ax,datasgmov ds,ax ;设置ds指向datasgmov bx,0mov cx,5s: mov al,[bx] ;ds:bx送入aland al,11011111B ;第五位设置为大写mov [bx],al ;转变后的送入原单元inc bxloop smov bx,5mov cx,11s0: mov al,[bx]or al,00100000Bmov [bx],alinc bxloop s0mov ax,4c00hint 21hcodesg endsend start
四、[bx+idata]
前面,我们用[bx]的方式来指明一个内存单元,还可以用一种更灵活的方式来指明内存单元:[bx+idata]表示一个内存单元,它的偏移地址为:(bx) = idata 也就是bx中的数值再加上idata
mov ax,[bx+200]
的含义:将一个内存单元的内容送入ax,这个内存单元的长度为2个字节,存放一个字,偏移地址为bx中的数值加上200,段地址在ds中,数字化描述为:(ax) = ((ds)*16 + (bx) + 200)
也可以写为:mov ax,[200+bx]
、mov ax,200[bx]
、mov ax,bx.200
这样子我们就可以用更高级的结构来看待要处理的数据:
在codesg中填写代码,将datasg中定义的第一个字符串转化为大写,第二个字符串转化为小写
现在我们可以使用[bx+idata]的方式来简化上面的程序,datasg中有两个字符串,一个起始地址为0,另外一个起始地址为5,我们可以将这两个字符串看作是两个数组,一个从地址0开始存放,一个是从5开始存放,我们就可以使用[0+bx],[5+bx]的方式在同一循环中定位这两个字符串中的字符。
assume cs:codesg,ds:datasgdatasg segmentdb 'BaSiC'db 'iNfOrMaTiOn'
datasg endscodesg segment
start:mov ax,datasgmov ds,axmov bx,0mov cx,5s: mov al,[bx] ;定位第一个字符串中的字符and al,11011111bmov [bx],almov al,[5+bx]or al,001000000bmov [b+bx],alinc bxloop scodesg endsend start
五、SI和DI
SI和DI是8086中和bx功能相近的寄存器,SI和DI不能分为两个8位寄存器来使用,下面三组指令实现了相同的功能:
(1)
mov bx,0
mov ax,[bx]
(2)
mov si,0
mov ax,[si]
(3)
mov di,0
mov ax,[di+123]
用SI和DI实现将字符串’welcome to masm!'复制到他后面的数据区中
assume cs:codesg,ds:datasgdatasg segmentdb 'welcome to masm!'db '................'
datasg endscodesg segment
start:;...是从16字节开始存放的mov ax,datasgmov ds,axmov si,0mov di,16 ;ds:di指向复制的空间mov cx,8s: mov ax,[si] ; ds:si指向的内容送入axmov [di],ax ; ax送入ds:diadd si,2add di,2loop smov ax,4c00hint 21hcodesg endsend start
用一个16位寄存器进行传送,一次复制2个字节,一共循环8次
我们还可以进行一些优化,使得程序更加简单:
assume cs:codesg,ds:datasgdatasg segmentdb 'welcome to masm!'db '................'
datasg endscodesg segment
start:;...是从16字节开始存放的mov ax,datasgmov ds,axmov si,0mov cx,8s: mov ax,[si+0] ; ds:si指向的内容送入axmov [si+16],ax ; ax送入ds:diadd si,2loop smov ax,4c00hint 21hcodesg endsend start
六、[bx+si]和[bx+di] 与 [bx+si+idata]和[bx+di+idata]
现在我们还可以用更灵活的方式来指明一个内存单元:[bx+si]
和[bx+di]
[bx+si]
表示一个内存单元,它的偏移地址为(bx)+(si),bx中的数值加上si中的数值
该指令也可以写为如下形式:mov ax,[bx][si]
[bx+si+idata]
表示一个内存单元,它的偏移地址为(bx)+(si)+ idata,bx中的数值加上si中的数值再加上idata
该指令也可以写为如下形式:
mov ax,[bx+200+si]
mov ax,200[bx][si]
mov ax,[bx][si].200
mov ax,[bx].200[si]
七、不同寻址方式的灵活引用
前面用到了几种定位内存地址的方式,可以称为寻址方式
- [idata]用一个常量来表示地址,可以用于直接定位一个内存单元
- [bx]用一个变量来表示内存地址,用于间接定位一个内存单元
- [bx+idata]用一个变量和常量来表示地址,可在一个起始地址的基础上用变量间接定位内存单元
- [bx+si]用两个变量来表示地址
- [bx+si+idata]用两个变量和一个常量来表示地址
编程,将datasg段中的每个单词的头一个字母改为大写字母
assume cs:codesg,ds:datasgdatasg segmentdb '1.file 'db '2.edit 'db '3.search'db '4.view 'db '5.options'db '6.help '
datasg endscodesg segmentstart:mov ax,4c00hint 21hcodesg endsend start
我们可以看到,在datasg中定义了6个字符串,每个长度为16个字节(有空格)他们是连续存放的,可以把他们看为是6行16列的二维数组,按照要求,需要修改每一个单词的第一个字母,即二维数组的每一行的第3列,相当于首行偏移地址为2
我们只需要进行6次循环,用一个R变量定义行,用常量2定位列
R = 第一行地址mov cx,6
s: 改变R行,3列的字母为大写R = 下一行的地址loop s
assume cs:codesg,ds:datasgdatasg segmentdb '1.file 'db '2.edit 'db '3.search'db '4.view 'db '5.options'db '6.help '
datasg endscodesg segmentstart:mov ax,datasgmov ds,axmov bx,0mov cx,6s: mov al,[bx+3]and al,11011111bmov [bx+3],aladd bx,16loop smov ax,4c00hint 21hcodesg endsend start
编程,将datasg段中每个单词改为大写字母
assume cs:codesg,ds:datasgdatasg segmentdb 'fie 'db 'edt 'db 'sch 'db 'vie 'datasg endscodesg segmentstart:mov ax,4c00hint 21hcodesg endsend start
data中定义了4个字符串,每个长度为16个字节(为了使在Debug中方便查看,所以我们每个字符串后面加了空格符)可以把这4个字符串看成一个4行16列的二维数组
assume cs:codesg,ds:datasgdatasg segmentdb 'fie 'db 'edt 'db 'sch 'db 'vie 'datasg endscodesg segmentstart:mov ax,4c00hint 21hcodesg endsend start
assume cs:codesg,ds:datasgdatasg segmentdb '1.file 'db '2.edit 'db '3.search'db '4.view 'db '5.options'db '6.help '
datasg endscodesg segmentstart:mov ax,datasgmov ds,axmov bx,0 ;ds:axmov cx,4 s0: mov dx,cx ;将外层循环cx保存在dx中mov si,0 ;第一列的地址mov cx,3 ;这里是内层循环次数s: mov al,[bx+si] ; 内层循环按列进行,and al,11011111bmov [bx+si],alinc siloop sadd bx,16mov cx,dxloop s0mov ax,4c00hint 21hcodesg endsend start
上面的程序我们用dx来暂时存放cx的值,但是如果在内层循环中,dx寄存器也被使用,怎么办?因为CPU寄存器数量是有限的,那怎么办?
这样子我们就不能考虑使用寄存器来存放,我们就使用内存来存放,这样子我们就需要去开辟一段内存空间
assume cs:codesg,ds:datasgdatasg segmentdb '1.file 'db '2.edit 'db '3.search'db '4.view 'db '5.options'db '6.help '
datasg endscodesg segmentstart:mov ax,datasgmov ds,axmov bx,0 ;ds:axmov cx,4 s0: mov ds:[40H],cx ;将外层循环的cx值保存在datasg:40单元中mov si,0 ;第一列的地址mov cx,3 ;这里是内层循环次数s: mov al,[bx+si] ; 内层循环按列进行,and al,11011111bmov [bx+si],alinc siloop sadd bx,16mov cx,ds:[40H] ;用datasg:40H单元中的值来恢复cxloop s0mov ax,4c00hint 21hcodesg endsend start
上面的程序中,我们使用了内存单元来保存数据,但是上面的作法有些麻烦,因为如果需要保存多份数据的时候,我们需要记住数据存放在哪一个单元中,这样子程序容易混乱。一般来说,我们需要暂存数据的时候,我们都应该使用栈,所以可以再改进我们的程序
assume cs:codesg,ds:datasg,ss:stacksgdatasg segmentdb 'fie 'db 'edt 'db 'sch 'db 'vie '
datasg endsstacksg segmentdw 0,0,0,0,0,0,0,0
stacksg endscodesg segmentstart:mov ax,stacksgmov ss,axmov sp,16mov ax,datasgmov ds,axmov bx,0mov cx,4s0: push cx ;将外层循环cx压入栈mov si,0mov cx,3 ;cx为内层循环s: mov al,[bx+si]and al,11011111bmov [bx+si],alinc siloop sand bx,16pop cxloop s0mov ax,4c00hint 21hcodesg endsend start
[汇编语言]更灵活的定位内存地址的方法相关推荐
- (七)汇编语言——更灵活的定位内存地址的方法
目录 and和or ASCII码 [bx+idata] SI和DI寄存器 [bx+si]和[bx+di] [bx+si+idata]和[bx+di+idata] 总结 例子(双重循环的解决方案) 我们 ...
- 汇编语言-更灵活的定位内存地址的方法
目录 一.and和or指令 1.补充知识: 2.and指令 3.or指令 二.以字符的形式给出的数据 三.大小写转换 ACSII码值对照表: 一.and和or指令 1.补充知识: 与运算(&) ...
- 更灵活的定位内存地址的方法02 - 零基础入门学习汇编语言33
第七章:更灵活的定位内存地址的方法02 让编程改变世界 Change the world by program [bx+idata] 在前面,我们可以用[bx]的方式来指明一个内存单元, 我们还可以用 ...
- 更灵活的定位内存地址的方法05 - 零基础入门学习汇编语言36
第七章:更灵活的定位内存地址的方法05 让编程改变世界 Change the world by program 问题7.8 [codesyntax lang="asm"] assu ...
- 更灵活的定位内存地址的方法---汇编学习笔记
更灵活的定位内存地址的方法 前面,我们用[0].[bx]的方法,在访问内存的指令中,定位内存单元的地址.本章将用更灵活的方式来定位内存地址. 7.1 and和or指令 (1)and指令:逻辑与指令,按 ...
- 汇编: 更灵活的定位内存地址的方法
bx是偏移地址寄存器.同样的, si,di也是偏移地址寄存器. 这样使用了si,di可以更灵活的定位内存地址. assume cs:codecode segmentstart: mov bx,0mov ...
- 王爽 汇编语言第三版 第7章 --- 更灵活的定位内存地址的方法(可以理解为 数组形式的内存定位)
汇编语言(第三版)王爽著 的十二个实验:https://blog.csdn.net/OrangeHap/article/details/89791064 大小端 字节对齐 对于 arm,intel 这 ...
- 《汇编语言》总结04 —— 更灵活的定位内存地址的方法
(一)and和or指令 and指令:逻辑与指令,按位进行与运算 mov al,01100011B and al,00111011B 执行后,al=00100011B 作用:通过该指令可将操作对象的相应 ...
- 汇编语言-王爽 第7章 更灵活的定位内存地址的方法-笔记
将datasg中的第一个字符串转化为大写,第二个字符串转化为小写. 第一种方法: assume cs:codesg,ds:datasgdatasg segmentdb 'BaSic'db 'iNfOr ...
最新文章
- 谁说GPT只擅长生成?清华研究力证:GPT语言理解能力不输BERT
- 网络请求的基本知识《极客学院 --AFNetworking 2.x 网络解析详解--1》学习笔记...
- 以太坊智能合约编程之带菜鸟入门教程
- 关于大龄程序员的谣言 新手必读
- pl/sql下DBMS_OUTPUT.PUT_LINE的输出位置
- python安装轮子_如何安装这个轮子?
- 【Nginx那些事】nginx配置实例(二)负载均衡
- 数据可视化美学形式与功能需要齐头并进
- 朴素贝叶斯常见面试题
- [转]关于computer vision的会议及vision guys
- 如何安装thinkphp
- 计算机上显示找不到无线网络连接失败,笔记本找不到无线网络,教您笔记本电脑搜索不到无线网络怎么办...
- 华尔街英语核心价值观综合视频发布
- 特征值分解:特征值,特征向量,特征向量矩阵
- Git如何保留两地并行开发的提交
- 文件和磁盘存储器管理
- react-native 调用第三方 SDK
- leetcode Rotate Array 旋转数组
- 二进制中正负数表示和判断
- windows虚拟机_windows系统安装和使用虚拟机
热门文章
- 我的世界java路径错误_我的世界JAVE路径错误怎么办?路径设置方法
- 免费报名 | 爱奇艺ZoomAI视频增强技术的应用
- win7分辨率不能调怎么办 win7系统分辨率不能调的解决方案
- 猎云早报:羽泉代言的借贷宝陷”受害者维权”风波,国盛金控3.75亿元收购趣店集团5%股权
- Android 9.0 APP中显示导航栏的menu键
- 如何成为一名漫画家——漫画家入门
- Qt安卓开发经验021-030
- 使用 OpenCV 进行实时对象颜色检测
- android 图片闪电效果图,Android超简单实现炫酷的图片展示效果
- AirPods Pro 链接windows不稳定