《汇编语言》——第七章:更灵活的定位内存地址的方法
1.and和or指令
- and指令:将操作对象的相应位设为0,其他位不变
- or指令:将操作对象的相应位设为1,其他位不变
2.以字符形式给出的数据
- 在汇编程序中,用’ '的方式指明数据是以字符的形式给出的,编译器将把它们转化为相对应的ASCII码
- 如
db 'unIX'
相当于db 75H,6EH,49H,58H
- 小写字母的ASCII码值比大写字母的ASCII码值大20H,故,“a"的ASCII码值减去20H,就可以得到"A”
- 一个字母,不管它原来是大写还是小写,将它的位置的第6位置0,它就必将变为大写字母,将它的第6位置1,它就必将变为小写字母
- 代码实现大小写改变
assume cs:cscode,ds:datasg datasg segment db 'BaSiC' db 'iNfOrMaTiOn' datasg ends cscode segment start: mov ax,datasg mov ds,ax ;设置ds指向datasg段 mov bx,0 ;设置(bx)=0,ds:bx指向"BaSiC"的第一个字母 mov cx,5 ;设置循环次数5,因为"BaSiC"的有5个字母 s: mov al,[bx] ;将ASCII码从ds:bx所指向的单元中取出 and al,11011111b ;将al中的ASCII码的第6位置为0,变为大写字母 mov [bx],al ;将转变后的ASCII码写回原单元 inc bx ;(bx)加1,ds:bx指向下一个字母 loop s mov ax,4c00h int 21h cscode ends end start ;指明程序的入口在start处
3.不同的寻址方法的灵活应用
- SI和DI是8086CPU中和bx功能相近的寄存器,但是SI和DI不能够分成两个8位寄存器来使用
- [idata]用一个常量来表示地址,可用于直接定位一个内存单元
- [bx]用一个变量来表示内存地址,可用于间接定位一个内存单元
- [bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元
- [bx+si]用两个变量表示地址
- [bx+si+idata]用两个变量和一个常量表示地址
- 例,将datasg段中每个单词的头一个字母改为大写字母
assume cs:codesg,ds:datasg datasg segment db '1. file ' db '2. edit ' db '3. search ' db '4. view ' db '5. options ' db '6. help ' datasg ends codesg segment start: codesg ends end start
- 思考后,要亲手打一遍
assume cs:codesg,ds:datasg datasg segment db '1. file ' db '2. edit ' db '3. search ' db '4. view ' db '5. options ' db '6. help ' datasg ends codesg segment start: mov ax,datasg mov ds,ax mov bx,0 mov cx,6 s: mov al,[bx+3] and al,11011111b mov [bx+3],al add bx,10h loop s mov ax,4c00h int 21h codesg ends end start
4.多重循环
- 进行二重循环时,使用一个循环计数器,造成在进行内层的时候覆盖了外层循环的循环计数值
- 多用一个计数器又不可能,因为loop指令默认cx为循环计数器
- 解决方法:在每次开始内层循环的时候,将外层循环的cx中的数值保存起来,在执行外层循环的loop指令前,再恢复外层循环的cx数值
- 但是8086的寄存器是有限的,其他寄存器被占用导致没有寄存器可以保存外层循环的数值怎么办?=>即,程序中经常需要进行数据的暂存,我们该如何做将更为合理?
暂存数据,可以使用栈的操作(栈是真的顶!!!)
- 例,将datasg段中每个单词改为大写字母
assume cs:codesg,ds:datasg datasg segment datasg ends codesg segment start: codesg ends end start
- 思考后,要亲手打一遍
要实践,把书上的代码自己打一遍、debug一遍assume cs:codesg,ds:datasg,ss:stacksg datasg segment db 'ibm ' db 'dec ' db 'dos ' db 'vax ' datasg ends stacksg segment ;定义一个栈段,容量为16个字节 dw 0,0,0,0,0,0,0,0 stacksg ends codesg segment start: mov ax,datasg mov ds,ax mov ax,stacksg mov ss,ax mov sp,16 mov bx,0h mov cx,4 s: push cx ;将外层循环的cx值压栈 mov cx,3 mov si,0 ;cx设置为内层循环的次数 s0: mov al,[bx+si] and al,11011111b mov [bx+si],al inc si loop s0 add bx,10h pop cx ;从栈顶弹出原cx的值,恢复cx loop s ;外层循环的loop指令将cx中的计数值减一 mov ax,4c00h int 21h codesg ends end start
来源:CSDN
作者:夏至未至c
链接:https://blog.csdn.net/qq_43364352/article/details/104441414