目录

  • 一、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]


七、不同寻址方式的灵活引用

前面用到了几种定位内存地址的方式,可以称为寻址方式

  1. [idata]用一个常量来表示地址,可以用于直接定位一个内存单元
  2. [bx]用一个变量来表示内存地址,用于间接定位一个内存单元
  3. [bx+idata]用一个变量和常量来表示地址,可在一个起始地址的基础上用变量间接定位内存单元
  4. [bx+si]用两个变量来表示地址
  5. [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

[汇编语言]更灵活的定位内存地址的方法相关推荐

  1. (七)汇编语言——更灵活的定位内存地址的方法

    目录 and和or ASCII码 [bx+idata] SI和DI寄存器 [bx+si]和[bx+di] [bx+si+idata]和[bx+di+idata] 总结 例子(双重循环的解决方案) 我们 ...

  2. 汇编语言-更灵活的定位内存地址的方法

    目录 一.and和or指令 1.补充知识: 2.and指令 3.or指令 二.以字符的形式给出的数据 三.大小写转换 ACSII码值对照表: 一.and和or指令 1.补充知识: 与运算(&) ...

  3. 更灵活的定位内存地址的方法02 - 零基础入门学习汇编语言33

    第七章:更灵活的定位内存地址的方法02 让编程改变世界 Change the world by program [bx+idata] 在前面,我们可以用[bx]的方式来指明一个内存单元, 我们还可以用 ...

  4. 更灵活的定位内存地址的方法05 - 零基础入门学习汇编语言36

    第七章:更灵活的定位内存地址的方法05 让编程改变世界 Change the world by program 问题7.8 [codesyntax lang="asm"] assu ...

  5. 更灵活的定位内存地址的方法---汇编学习笔记

    更灵活的定位内存地址的方法 前面,我们用[0].[bx]的方法,在访问内存的指令中,定位内存单元的地址.本章将用更灵活的方式来定位内存地址. 7.1 and和or指令 (1)and指令:逻辑与指令,按 ...

  6. 汇编: 更灵活的定位内存地址的方法

    bx是偏移地址寄存器.同样的, si,di也是偏移地址寄存器. 这样使用了si,di可以更灵活的定位内存地址. assume cs:codecode segmentstart: mov bx,0mov ...

  7. 王爽 汇编语言第三版 第7章 --- 更灵活的定位内存地址的方法(可以理解为 数组形式的内存定位)

    汇编语言(第三版)王爽著 的十二个实验:https://blog.csdn.net/OrangeHap/article/details/89791064 大小端 字节对齐 对于 arm,intel 这 ...

  8. 《汇编语言》总结04 —— 更灵活的定位内存地址的方法

    (一)and和or指令 and指令:逻辑与指令,按位进行与运算 mov al,01100011B and al,00111011B 执行后,al=00100011B 作用:通过该指令可将操作对象的相应 ...

  9. 汇编语言-王爽 第7章 更灵活的定位内存地址的方法-笔记

    将datasg中的第一个字符串转化为大写,第二个字符串转化为小写. 第一种方法: assume cs:codesg,ds:datasgdatasg segmentdb 'BaSic'db 'iNfOr ...

最新文章

  1. 谁说GPT只擅长生成?清华研究力证:GPT语言理解能力不输BERT
  2. 网络请求的基本知识《极客学院 --AFNetworking 2.x 网络解析详解--1》学习笔记...
  3. 以太坊智能合约编程之带菜鸟入门教程
  4. 关于大龄程序员的谣言 新手必读
  5. pl/sql下DBMS_OUTPUT.PUT_LINE的输出位置
  6. python安装轮子_如何安装这个轮子?
  7. 【Nginx那些事】nginx配置实例(二)负载均衡
  8. 数据可视化美学形式与功能需要齐头并进
  9. 朴素贝叶斯常见面试题
  10. [转]关于computer vision的会议及vision guys
  11. 如何安装thinkphp
  12. 计算机上显示找不到无线网络连接失败,笔记本找不到无线网络,教您笔记本电脑搜索不到无线网络怎么办...
  13. 华尔街英语核心价值观综合视频发布
  14. 特征值分解:特征值,特征向量,特征向量矩阵
  15. Git如何保留两地并行开发的提交
  16. 文件和磁盘存储器管理
  17. react-native 调用第三方 SDK
  18. leetcode Rotate Array 旋转数组
  19. 二进制中正负数表示和判断
  20. windows虚拟机_windows系统安装和使用虚拟机

热门文章

  1. 我的世界java路径错误_我的世界JAVE路径错误怎么办?路径设置方法
  2. 免费报名 | 爱奇艺ZoomAI视频增强技术的应用
  3. win7分辨率不能调怎么办 win7系统分辨率不能调的解决方案
  4. 猎云早报:羽泉代言的借贷宝陷”受害者维权”风波,国盛金控3.75亿元收购趣店集团5%股权
  5. Android 9.0 APP中显示导航栏的menu键
  6. 如何成为一名漫画家——漫画家入门
  7. Qt安卓开发经验021-030
  8. 使用 OpenCV 进行实时对象颜色检测
  9. android 图片闪电效果图,Android超简单实现炫酷的图片展示效果
  10. AirPods Pro 链接windows不稳定