1、汇编语言课件,王爽 著清华大学出版社,制作工具:Microsoft PowerPoint2003,本课件由汇编网()制作提供,第7章 更灵活的定位内存地址的方法,7.1 and和or指令 7.2 关于ASCII码 7.3 以字符形式给出的数据 7.4 大小写转换的问题 7.5 bx+idata 7.6 用bx+idata的方式进行数组的处理,7.7 SI和DI 7.8 bx+si和bx+di 7.9 bx+si+idata和bx+di+idata 7.10 不同的寻址方式的灵活应用,引言,前面,我们用0、bx的方法,在访问内存的指令中,定位内存单元的地址。在这一章中,我们主要讲解一些更灵活的定
2、位内存地址的方法和相关的编程方法。 我们的讲解将通过具体的问题来进行。,7.1 and和or指令,首先我们介绍两条指令and和or,因为我们下面的例程中要用到它们。 (1)and 指令:逻辑与指令,按位进行与运算。如 mov al, 01100011Band al, 00111011B执行后:al = 00100011B通过该指令可将操作对象的相应位设为0,其他位不变。示例,7.2 关于ASCII码,世界上有很多编码方案,有种方案叫做ASCII编码,是在计算机系统中通常被采用的。 简单地说,所谓编码方案,就是一套规则,它约定了用什么样的信息来表示现实对象。 比如说,在ASCII编码方案中,用
3、61H 表示“a”,62H表示“b”。,7.2 关于ASCII码,一种规则需要人们遵守才有意义。 一个文本编辑过程中,就包含着按照ASCII编码规则进行的编码和解码。在文本编辑过程中,我们按一下键盘的a键,就会在屏幕上看到“a”。这是怎样一个过程呢?,7.3 以字符形式给出的数据,我们可以在汇编程序中,用 “”的方式指明数据是以字符的形式给出的,编译器将把它们转化为相对应的ASCII码。例如程序7.1,7.3 以字符形式给出的数据,assume ds:data data segmentdb unIX db foRK data ends code segmentstart:mov al,amov
4、 bl,bmov ax,4c00hint 21h code ends end start,程序7.1,7.3 以字符形式给出的数据,上面的源程序中: “db unIX ” 相当于“db 75H,6EH,49H,58H”, “u”、 “n”、 “I”、 “X”的ASCII码分别为75H、6EH、49H、58H; “db foRK ” 相当于“db 66H,6FH,52H,4BH”, “u”、 “n”、 “I”、 “X”的ASCII码分别为66H、6FH、52H、4BH; “mov al,a”相当于“mov al,61H”,”a”的ASCII码为61H; “mov al,b”相当于“mov al,
5、62H”,”b”的ASCII码为62H。,7.4 大小写转换的问题,首先分析一下,我们知道同一个字母的大写字符和小写字符对应的 ASCII 码是不同的,比如 “A” 的 ASCII 码是41H,“a”的ASCII码是61H。要改变一个字母的大小写,实际上就是要改变它所对应的ASCII 码。,7.4 大小写转换的问题,我们可以将所有的字母的大写字符和小写字符所对应的ASCII码列出来,进行对比,从中找到规律。 大写 二进制 小写 二进制A 01000001 a 01100001B 01000010 b 01100010C 01000011 c 01100011D 01000100 d 01100
6、100,7.4 大小写转换的问题,通过对比,我们可以看出来,小写字母的ASCII码值比大写字母的ASCII码值大20H 。这样,我们可以想到,如果将 “a” 的ASCII码值减去20H,就可以得到“A”;如果将“A”的ASCII码值加上20H 就可以得到“a”。,7.4 大小写转换的问题,按照这样的方法,我们可以将 datasg段中:第一个字符串“BaSiC”中的小写字母变成大写;第二个字符串,“iNfOrMaTiOn”中的大写字母变成小写。,7.4 大小写转换的问题,要注意的是:对于字符串“BaSic”,我们应只对其中的小写字母所对应的ASCII码进行减20H 的处理,将其转为大写,而对其中
7、的大写字母不进行改变;,7.4 大小写转换的问题,要注意的是: (续)对于字符串 “ iNforMaTIOn ” ,我们应只对其中的大写字母所对应的ASCII码进行加20H 的处理,将其转为小写;而对于其中的小写字母不进行改变,这里面就存在着一个前提,程序必须要能够判断一个字母是大写还是小写。,7.4 大小写转换的问题,以“BaSiC”讨论,程序的流程将是这样的:,assume cs:codesg,ds:datasg datasg segment db BaSiC db iNfOrMaTiOn datasg ends codesg segmentstart: mov ax,datasgmov
8、ds,axmov bx,0mov cx,5s: mov al,bx如果(al)61H,则为小写字母ASCII码,则:sub al,21Hmov bx,alinc bxloop s : codesg ends end start,7.4 大小写转换的问题,判断将用到一些我们目前还没有学习到的指令。现在面临的问题是,用己学的指令来解决这个问题,则我们不能对字母的大小写进行任何判断。 但是,现实的问题却要求程序必须要能区别对待大写字母和小写字母。,7.4 大小写转换的问题,可以看出,就ASCII码的二进制形式来看,除第5位(位数从0开始计算)外,大写字母和小写字母的其他各位都一样。大写字母ASCII
9、码的第5位(位数从0开始计算)为0,小写字母的第5位为1。,7.4 大小写转换的问题,这样,我们就有了新的方法:一个字母,我们不管它原来是大写还是小写: 我们将它的第5位置0,它就必将变为大写字母; 将它的第5 位置1,它就必将变为小写字母。,7.4 大小写转换的问题,我们用什么方法将一个数据中的某一位置0还是置1?当然是用我们刚刚学过的or和and指令。完整的程序代码,7.5 bx+idata,在前面,我们可以用bx的方式来指明一个内存单元, 我们还可以用一种更为灵活的方式来指明内存单元:bx+idata表示一个内存单元,它的偏移地址为(bx)+idata(bx中的数值加上idata)。,7
10、.5 bx+idata,我们看一下指令mov ax,bx+200的含义: 将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为bx中的数值加上200,段地址在ds中。 数学化的描述为: (ax)=(ds)*16+(bx)+200),7.5 bx+idata,指令mov ax,bx+200也可以写成如下格式(常用):mov ax,200+bxmov ax,200bxmov ax,bx.200问题,7.5 bx+idata,问题7.1用Debug查看内存,结果如下:2000:1000 BE 00 06 00 00 00 写出下面的程序执行后,ax、bx、cx中
11、的内容。思考后看分析。,mov ax,2000Hmov ds,axmov bx,1000Hmov ax,bxmov cx,bx+1add cx,bx+2,7.5 bx+idata,问题7.1分析mov ax,bx访问的字单元的段地址在ds中,(ds)=2000H;偏移地址在bx 中,(bx)=1000H;指令执行后(ax)=00BEH。,7.5 bx+idata,问题7.1分析 mov cx,bx+1 访问的字单元的段地址在ds中,(ds)=2000H;偏移地址=(bx)+1=1001H;指令执行后(cx)=0600H。,7.5 bx+idata,问题7.1分析 add cx,bx+2 访问的
12、字单元的段地址在ds中,(ds)=2000H;偏移地址=(bx)+2=1002H;指令执行后(cx)=0606H。,7.6 用bx+idata的方式进行数组的处理,有了bx+idata这种表示内存单元的方式,我们就可以用更高级的结构来看待所要处理的数据。 我们通过下面的问题来理解这一点。,7.6 用bx+idata的方式进行数组的处理,在codesg中填写代码,将datasg中定义的第一个字符串,转化为大写,第二个字符串转化为小写。,assume cs:codesg,ds:datasg datasg segment db BaSiC db MinIX datasg endscodesg seg
13、mentstart: codesg ends end start,7.6 用bx+idata的方式进行数组的处理,按照我们原来的方法,用bx的方式定位字符串中的字符。代码段中的程序代码:,mov ax,datasgmov ds,ax mov bx,0 mov cx,5 s: mov al,bx and al,11011111b mov bx,al inc bx loop smov bx,5mov cx,5 s0: mov al,bxor al,00100000b mov bx,alinc bxloop s0,7.6 用bx+idata的方式进行数组的处理,现在,我们有了 bx+idata的方式
14、,就可以用更简化的方法来完成上面的程序。我们观察datasg段中的两个字符串,一个的起始地址为0,另一个的起始地址为5。我们可以将这两个字符串看作两个数组,一个从0地址开始存放,另一个从5开始存放。,7.6 用bx+idata的方式进行数组的处理,那么我们可以用0+bx和5+bx的方式在同一个循环中定位这两个字符串中的字符。在这里,0和5给定了两个字符串的起始偏移地址,bx中给出了从起始偏移地址开始的相对地址。这两个字符串在内存中的起始地址是不一样的,但是,它们中的每一个字符,从起始地址开始的相对地址的变化是相同的。,7.6 用bx+idata的方式进行数组的处理,改进的程序:,mov ax,
15、datasgmov ds,axmov bx,0mov cx,5 s: mov al,bx ;定位第一个字符串的字符and al,11011111bmov bx,almov al,5+bx ;定位第二个字符串的字符or al,00100000bmov 5+bx,alinc bxloop s,7.6 用bx+idata的方式进行数组的处理,程序还可以写成这样:,mov ax,datasgmov ds,axmov bx,0mov cx,5 s: mov al,0bx and al,11011111bmov 0bx,almov al,5bx or al,00100000bmov 5bx,alinc b
16、xloop s,7.6 用bx+idata的方式进行数组的处理,如果我们用高级语言,比如C语言来描述上面的程序,大致是这样的:,char a5=“BaSiC”;char b5=“MinIX”;main()int i;i=0;doai=ai,7.6 用bx+idata的方式进行数组的处理,如果读者熟悉C语言的话,可以比较一下这个C程序和上面的汇编程序的相似之处。尤其注意它们定位字符串中字符的方式: C语言定位方式:ai,bi 汇编语言定位方式:0bx,5bx,7.6 用bx+idata的方式进行数组的处理,通过比较,我们可以发现:bx+idata的方式为高级语言实现数组提供了便利机制。,7.7
17、SI和DI,SI和DI是8086CPU中和bx功能相近的寄存器,SI和DI不能够分成两个8 位寄存器来使用。下面的三组指令实现了相同的功能:,(1) mov bx,0mov ax,bx (2) mov si,0mov ax,si (3) mov di,0mov ax,di,7.7 SI和DI,下面的三组指令也实现了相同的功能:问题7.2,(1) mov bx,0mov ax,bx+123 (2) mov si,0mov ax,si+123 (3) mov di,0mov ax,di+123,7.7 SI和DI,问题7.2用寄存器SI和DI实现将字符串welcome to masm!复制到它后面
18、的数据区中。assume cs:codesg,ds:datasgdatasg segment db welcome to masm!db datasg ends思考后看分析。,7.7 SI和DI,问题7.2分析我们编写的程序大都是进行数据的处理,而数据在内存中存放,所以我们在处理数据之前首先要搞清楚数据存储在什么地方,也就是说数据的内存地址。现在我们要对datasg 段中的数据进行复制,我们先来看一下要复制的数据在什么地方,datasg:0,这是要进行复制的数据的地址。,7.7 SI和DI,问题7.2分析(续)那么复制到哪里去呢?它后面的数据区。“welcome to masm!”从偏移地址0
19、开始存放,长度为 16 个字节,所以,它后面的数据区的偏移地址为 16 ,就是字符串所要存放的空间。,7.7 SI和DI,问题7.2分析(续) 清楚了地址之后,我们就可以进行处理了。我们用ds:si 指向要复制的源始字符串,用 ds:di 指向复制的目的空间,然后用一个循环来完成复制。,7.7 SI和DI,代码段:注意,在程序中,我们用16位寄存器进行内存单元之间的数据传送,一次复制 2 个字节,一共循环8次。,codesg segment start: mov ax,datasgmov ds,axmov si,0mov di,16mov cx,8s: mov ax,simov di,axad
20、d si,2add di,2loop smov ax,4c00hint 21h codesg ends end start,7.7 SI和DI,问题7.3用更少的代码,实现问题7. 2中的程序。 思考后看分析。,7.7 SI和DI,问题7.3分析:我们可以利用bx(si或di)+idata的方式,来使程序变得简洁。 程序如下:,codesg segment start: mov ax,datasgmov ds,axmov si,0mov cx,8s: mov ax,0simov 16si,axadd si,2loop smov ax,4c00hint 21h codesg ends end s
21、tart,7.8 bx+si和bx+di,在前面,我们用bx(si或di)和bx(si或di)+idata 的方式来指明一个内存单元,我们还可以用更灵活的方式: bx+si bx+di bx+si和bx+di的含义相似,我们以bx+si为例进行讲解。,7.8 bx+si和bx+di,bx+si表示一个内存单元,它的偏移地址为(bx)+(si)(即bx中的数值加上si中的数值)。 我们看下指令mov ax,bx+si的含义:将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为bx中的数值加上si中的数值,段地址在ds中。,7.8 bx+si和bx+di,指令
22、mov ax,bx+si的数学化的描述为:(ax)=( (ds)*16+(bx)+(si) )该指令也可以写成如下格式(常用):mov ax,bxsi,7.8 bx+si和bx+di,问题7.4用Debug查看内存,结果如下:2000:1000 BE 00 06 00 00 00 写出下面的程序执行后,ax、bx、cx中的内容。,7.8 bx+si和bx+di,用Debug查看内存,结果如下:2000:1000 BE 00 06 00 00 00 ,mov ax,2000Hmov ds,axmov bx,1000Hmov si,0mov ax,bx+siinc simov cx,bx+siin
23、c simov di,simov ax,bx+di 思考后看分析。,7.8 bx+si和bx+di,问题7.4分析 mov ax,bx+si 访问的字单元的段地址在ds中,(ds)=2000H;偏移地址=(bx)+(si)=1000H;指令执行后(ax)=00BEH。,7.8 bx+si和bx+di,问题7.4分析 mov cx,bx+si 访问的字单元的段地址在ds中,(ds)=2000H;偏移地址=(bx)+(si)=1001H;指令执行后(cx)=0600H。,7.8 bx+si和bx+di,问题7.4分析 add cx,bx+di 访问的字单元的段地址在ds中,(ds)=2000H;偏
24、移地址=(bx)+(di)=1002H;指令执行后(cx)=0606H。,7.9 bx+si+idata和bx+di+idata,bx+si+idata和bx+di+idata的含义相似,我们以bx+si+idata为例进行讲解。 bx+si+idata表示一个内存单元它的偏移地址为(bx)+(si)+idata。(即bx中的数值加上si中的数值再加上idata),7.9 bx+si+idata和bx+di+idata,指令mov ax,bx+si+idata的含义:将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为bx中的数值加上si中的数值再加上id
25、ata,段地址在ds中。数学化的描述为: (ax)=( (ds)*16+(bx)+(si)+idata ),7.9 bx+si+idata和bx+di+idata,指令mov ax,bx+si+idata:该指令也可以写成如下格式(常用):mov ax,bx+200+si mov ax,200+bx+si mov ax,200bxsi mov ax,bx.200si mov ax,bxsi.200,7.9 bx+si+idata和bx+di+idata,问题7.5用Debug查看内存,结果如下:2000:1000 BE 00 06 00 6A 22 写出下面的程序执行后,ax、bx、cx中的内
26、容。,7.9 bx+si+idata和bx+di+idata,用Debug查看内存,结果如下:2000:1000 BE 00 06 00 6A 22 ,mov ax,2000Hmov ds,axmov bx,1000Hmov si,0mov ax,bx+2+siinc simov cx,bx+2+siinc simov di,simov ax,bx+2+di 思考后看分析。,7.9 bx+si+idata和bx+di+idata,问题7.5分析 mov ax,bx+2+si访问的字单元的段地址在ds中,(ds)=2000H;偏移地址=(bx)+(si)+2=1002H;指令执行后(ax)=00
27、06H。,7.9 bx+si+idata和bx+di+idata,问题7.5分析 mov ax,bx+2+si访问的字单元的段地址在ds中,(ds)=2000H;偏移地址=(bx)+(si)+2=1003H;指令执行后(cx)=006AH。,7.9 bx+si+idata和bx+di+idata,问题7.5分析 mov ax,bx+2+si访问的字单元的段地址在ds中,(ds)=2000H;偏移地址=(bx)+(si)+2=1004H;指令执行后(cx)=226AH。,7.10 不同的寻址方式的灵活应用,如果我们比较一下前而用到的几种定位内存地址的方法(可称为寻址方式),就可以发现有以下几种方
28、式: (1)iata 用一个常量来表示地址,可用于直接定位一个内存单元; (2)bx用一个变量来表示内存地址,可用于间接定位一个内存单元; (3)bx+idata 用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元; (4)bx+si用两个变量表示地址; (5)bx+si+idata 用两个变量和一个常量表示地址。,7.10 不同的寻址方式的灵活应用,可以看到:从idata一直到bx+si+idata,我们可以用更加灵活的方式来定位一个内存单元的地址。这使我们可以从更加结构化的角度来看待所要处理的数据。,7.10 不同的寻址方式的灵活应用,下面我们通过一个问题的系列来
29、体会CPU提供多种寻址方式的用意,并学习一些相关的编程技巧。,7.10 不同的寻址方式的灵活应用,问题7.6编程,将datasg段中每个单词的头一个字母改为大写字母。,assume cs:codesg,ds:datasg datasg segmentdb 1. file db 2. edit db 3. search db 4. view db 5. options db 6. help datasg endscodesg segmentstart: codesg ends end start,7.10 不同的寻址方式的灵活应用,问题7.6分析datasg中的数据的存储结构,如图:,7.10
30、不同的寻址方式的灵活应用,我们可以看到:在datasg中定义了6个字符串,每个长度为16字节。(注意,为了直观,每个字符串的后面都加上了空格符,以使它们的长度刚好为16字节),7.10 不同的寻址方式的灵活应用,因为它们是连续存放的,我们可以将这6个字符串看成一个6行16列的二维数组。按照要求,我们需要修改每一个单词的第一个字母,即二维数组的每一行的第4列(相对于行首的偏移地址为3 )。,7.10 不同的寻址方式的灵活应用,我们需要进行6次循环,用一个变量R定位行,用常量3 定位列。处理的过程如下:R=第一行的地址mov cx,6s: 改变R行,3列的字母为大写R=下一行的地址loop,7.1
31、0 不同的寻址方式的灵活应用,我们用bx作变量,定位每行的起始地址,用3定位要修改的列,用bx+idata的方式来对目标单元进行寻址, 程序如下:,mov ax,datasgmov ds,axmov bx,0mov cx,6s: mov al,bx+3and al,11011111bmov bx+3,aladd bx,16loop s,7.10 不同的寻址方式的灵活应用,问题7.7 编程:将datasg段中每个单词改为大写字母。,assume cs:codesg,ds:datasg datasg segmentdb ibm db dec db dos db vax datasg endscod
32、esg segmentstart: codesg ends end start,7.10 不同的寻址方式的灵活应用,问题7.7分析datasg中数据的存储结构,如图:,7.10 不同的寻址方式的灵活应用,在datasg中定义了4个字符串,每个长度为16字节。(注意,为了使我们在Debug 中可以直观地查看,每个字符串的后面都加上了空格符,以使它们的长度刚好为16byte),7.10 不同的寻址方式的灵活应用,因为它们是连续存放的,我们可以将这 4 个字符串看成一个 4行16列的二维数组。按照要求,我们需要修改每一个单词,即二维数组的每一行的前3列。,7.10 不同的寻址方式的灵活应用,我们需要
33、进行4x3次的二重循环,用变量R 定位行,变量C定位列。 外层循环按行来进行; 内层按列来进行。,7.10 不同的寻址方式的灵活应用,我们首先用R 定位第1行,然后循环修改R行的前3列;然后再用R定位到下一行,再次循环修改R行的前3列,如此重复直到所有的数据修改完毕。,7.10 不同的寻址方式的灵活应用,处理的过程大致如下:R=第一行的地址;mov cx,4s0: C=第一列的地址mov cx,3s: 改变R 行,C列的字母为大写C=下一列的地址;loop sR=下一行的地址loop s0,7.10 不同的寻址方式的灵活应用,我们用bx来作变量,定位每行的起始地址,用si 定位要修改的列,用
34、bx+si 的方式来对目标单元进行寻址,程序代码: 问题7.8,mov ax,datasgmov ds,axmov bx,0mov cx,4s0: mov si,0mov cx,3s: mov al,bx+siand al,11011111bmov bx+si,alinc siloop sadd bx,16loop s0 源程序,7.10 不同的寻址方式的灵活应用,问题7.8仔细阅读上面的程序,看看有什么问题?思考后看分析。,7.10 不同的寻址方式的灵活应用,问题7.8分析问题在于cx的使用,我们进行二重循环,却只用了一个循环计数器,造成在进行内层的时候覆盖了外层循环的循环计数值。多用一个计
35、数器又不可能,因为loop指令默认cx为循环计数器。怎么办呢?,7.10 不同的寻址方式的灵活应用,我们应该在每次开始内层循环的时候,将外层循环的cx中的数值保存起来,在执行外层循环的loop指令前,再恢复外层循环的cx数值。我们可以用寄存器dx来临时保存cx中的数值。 改进的程序,7.10 不同的寻址方式的灵活应用,mov ax,datasgmov ds,axmov bx,0mov cx,4s0: mov dx,cx ;将外层循环的cx值保存在dx中mov si,0mov cx,3 ;cx设置为内存循环的次数s: mov al,bx+siand al,11011111bmov bx+si,a
36、linc siloop sadd bx,16mov cx,dx ;用dx中存放的外层循环的计数值恢复cxloop s0 ;外层循环的loop指令将cx中的计数值减 1,7.10 不同的寻址方式的灵活应用,上面的程序用dx来暂时存放cx中的值;如果在内层循环中,dx寄存器也被使用,该怎么办? 我们似乎可以使用别的寄存器,但是CPU中的寄存器数量毕竟是有限的,如8086CPU只有14个寄存器。,7.10 不同的寻址方式的灵活应用,在上面的程序中:si、cx、ax、bx,显然不能用来暂存cx中的值,因为这些寄存器在循环中也要使用;cs、ip、ds也不能用,因为cs:ip时刻指向当前指令,ds指向da
37、tasg段;可用的就只有:dx、di、es、ss、sp、bp等6个寄存器了。,7.10 不同的寻址方式的灵活应用,可是如果循环中的程序比较复杂,这些寄存器也都被使用的话,那么该如何? 我们在这里讨论的问题是,程序中经常需要进行数据的暂存,我们怎样做将更为合理。,7.10 不同的寻址方式的灵活应用,这些数据可能是寄存器中的,也可能是内存中的。 我们可以用寄存器暂存它们,但是这不是一个一般化的解决方案,因为寄存器的数量有限,每个程序中可使用的寄存器都不一样。 我们希望寻找一个通用的方案,来解决这种在编程中经常会出现的问题。,7.10 不同的寻址方式的灵活应用,显然,我们不能选择寄存器,那么可以使用
38、的就是内存了。我们可以考虑将需要暂存的数据放到内存单元中,需要使用的时候,再从内存单元中恢复。这样我们就需要开辟一段内存空间。 再次改进的程序,7.10 不同的寻址方式的灵活应用,上面的程序中,用内存单元来保存数据; 可是上面的作法却有些麻烦,因为如果需要保存多个数据的时候,读者必须要记住数据放到了哪个单元中,这样程序容易混乱。,7.10 不同的寻址方式的灵活应用,我们使用内存来暂存数据,这一点是确定了的,但是值得推敲的是,我们用怎样的结构来保存这些数据,而使得我们的程序更加清晰。,7.10 不同的寻址方式的灵活应用,一般来说,在需要暂存数据的时候,我们都应该使用栈,回忆一下,栈空间在内存中,
39、采用相关的指令,如:push、pop等,可对其进行特殊的操作。 我们再次改进我们的程序,7.10 不同的寻址方式的灵活应用,问题7.9编程,将datasg段中每个单词的前四个字母改为大写字母:,assume cs:codesg,ds:datasg,ss:stacksg stacksg segmentdw 0,0,0,0,0,0,0,0 stacksg ends datasg segmentdb 1. displaydb 2. browsdb 3. replacedb 4. modify. datasg ends codesg segment start: codesg ends end sta
40、rt,7.10 不同的寻址方式的灵活应用,问题7.9分析datasg中的数据的存储结构,如图:,7.10 不同的寻址方式的灵活应用,在datasg中定义了4个字符串,每个长度为16字节(注意,为了使我们在Debug中可以直观地查看,每个字符串的后面都加上了空格符,以使它们的长度刚好为16字节)。 因为它们是连续存放的,我们可以将这4个字符串看成一个4行16列的二维数组,按照要求,我们需要修改每个单词的前四个字母,即二维数组的每一行的36列。,7.10 不同的寻址方式的灵活应用,我们需要进行4x4次的二重循环,用变量R定位行,常量3定位每行要修改的起始列,变量C定位相对于起始列的要修改的列。 外
41、层循环按行来进行,内层按列来进行。,7.10 不同的寻址方式的灵活应用,我们首先用R定位第1行,循环修改R行的3+C( 0C3 )列;然后再用R 定位到下一行,再次循环修改R行的3+C(0C3)列,如此重复直到所有的数据修改完毕。,7.10 不同的寻址方式的灵活应用,处理的过程大致如下:R=第一行的地址;mov cx,4s0: C=第一个要修改的列相对于起始列的地址mov cx,4s: 改变R行,3+C列的字母为大写C=下一个要修改的列相对于起始列的地址loop sR=下一行的地址loop s0,7.10 不同的寻址方式的灵活应用,我们用bx来作变量,定位每行的起始地址,用 si定位要修改的列
42、,用 bx+3+si 的方式来对目标单元进行寻址。 请在实验中白己完成这个程序。,7.10 不同的寻址方式的灵活应用,这一章中,我们主要讲解了更灵活的寻址方式的应用和一些编程方法,主要内容有: 寻址方式bx(或si、di)+idata、 bx+si(或di)、bx+si(或di)+idata的意义和应用; 二重循环问题的处理; 栈的应用; 大小写转化的方法; and 、or 指令。,7.10 不同的寻址方式的灵活应用,下一章中,我们将对寻址方式的问题进行更深入地探讨。 之所以如此重视这个问题,是因为寻址方式的适当应用,使我们可以以更合理的结构来看待所要处理的数据。 而为所耍处理的看似杂乱的数据设计一种清晰的数据结构是程序设计的一个关键的问题。,小结,