概述
and、or指令
and指令,逻辑与指令,按位进行与运算;or指令,逻辑或指令,按位进行或运算。
如:mov al,01100011B
and al,00111011B
执行后:(al)=00100011B。用法:将操作数的某一位设置为0,其他位不变,如将al的第6位设置为0,and al 10111111B,或and al 0bfh。
如:mov al,01100011B
or al,00111011B
执行后:(al)=01111011B。用法:将操作数的某一位设置为1,其他位不变,如将al的第6位设置为1,or al 01000000B,或or al 40h。
访问内存
1,之前提到过采用中括号‘[ ]‘来访问内存,在此对其做一补充:在汇编源程序中,如果采用常量作为内存的偏移地址时,应在前面显示加上相应的段寄存器。如:mov ax,ds:[0],来指明内存数据的段地址在ds段寄存器中,偏移地址为0;
如果采用寄存器值作为内存的偏移地址时,则不需要这样做,如:mov bx,0 mov ax,[bx] ,这两种写法是等价的。
其中用于显示指明内存单元的段地址的段寄存器如’ds:’、‘es:’、‘cs:’、'ss:'称为段前缀。
2,定义数据段空间:
db,定义字节数据(8位);dw,定义字型数据(16位);dd,定义双字型数据(32位)。
db ‘…’,单引号中为字符串,定义字符串数据。如 db ’unIX‘ 它定义了4个字节大小的空间分别来存储’u’的ASCII值75h,’n’的ASCII值6eh,’I’的ASCII值49h,’X’的ASCII值58h。等价于 db 75h,6eh,49h,58h
dup,常与db、dw、dd配合使用,用来进行数据的重复。例:db 3 dup(0),定义了3个字节,它们的值都是0,相当于db 0,0,0;db 3 dup(0,1,2),定义了9个字节,它们是0,1,2,0,1,2,0,1,2,相当于db 0,1,2,0,1,2,0,1,2。也可以配合 dw和dd来使用,用法都是一样的。
3,定位内存单元的更多方法:
[bx+idata],段地址默认在ds中,也可显式给出段地址。如:mov ax,[bx+200],将段地址在ds中,偏移地址为(bx)+200处的字型数据传送到ax中。其他等价的格式为:mov ax,[200+bx],mov ax,200[bx],mov ax,[bx].200.。同样的方式还有[si+idata]、[di+idata]、[bp+idata](含有bp的默认段地址在ss中)。
[bx+si],段地址默认在ds中,也可显式给出段地址。如:mov ax,[bx+si],将段地址在ds中,偏移地址为(bx)+(si)处的字型数据传送到ax中。其他等价的格式为:mov ax,[bx] [si]。同样的方式还有[bx+di]、[bp+si]、[bp+di](含有bp的默认段地址在ss中)。
[bx+si+idata],段地址默认在ds中,也可显式给出段地址。如:mov ax,[bx+si+200],将段地址在ds中,偏移地址为(bx)+(si)+200处的字型数据传送到ax中。其他等价的格式为:mov ax,[bx+200+si],mov ax,[200+bx+si],mov ax,200[bx] [si],mov ax,[bx].200[si],mov ax,[bx] [si].200。同样的方式还有[bx+di+idata]、[bp+si+idata]、[bp+di+idata](含有bp的默认段地址在ss中)。
例题
传送数据:将内存ffff:0-ffff:b单元内的数据复制到0:200-0:20b单元中。
方法一:采用loop指令,具体如下:
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax ds保存源数据的段地址
mov ax,0020 为使得偏移地址保持一致进行转化
mov es,ax es保存目的数据的段地址
mov bx,0 bx中存储偏移地址
mov cx,0ch
s:mov al,[bx]
mov es:[bx],al
inc bx
loop s
mov ax,4c00h 程序返回指令
int 21h
code ends
end
方法二:采用DF标志和串传送指令
其中df标志为flag的第10位,方向标志位。在串传送指令中,它用来控制每次操作后si、di的增减。其中当df=0时,每次操作后si、di递增;当df=1时,每次操作后si、di递减。cld指令将标志寄存器的df位设置位0;std指令将df设置为1。
串传送指令movsb,它的功能是将ds:si指向的内存单元中的字节送入es:di中,然后根据标志寄存器中df位的值,将si和di递增或递减。而movsw传送的是字单元,用法与movsb类似,si、di每次加2或减2。
用法:rep movsb,根据cx中的值,重复执行串传送指令,即传送cx个字节。
故:
传送的原始位置:ffff:0放入ds:si中
传送的目的位置:0:200放入es:di中
传送的长度:0ch放入cx中
传送的方向:正方向,从而设置df为0
编码如下:
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax
mov si,0
mov ax,0
mov es,ax
mov di,200h
mov cx,0ch
cld
rep movsb
mov ax,4c00h
int 21h
code ends
end
实验4
编程实现向内存0:200-0:23F依次传送数据0-63(3FH),只能用9条指令。
mov ax,0020
更改内存地址的表示方式为0020:0-0020:3f
mov ds,ax
mov bx,0
mov cx,64
s:mov [bx],bx
inc bx
loop s
mov ax,4c00h
int 21h
实验5
有一条重要的结论:如果我们在定义一段栈段空间或数据段空间时,无论具体定义了多大的空间,最终被分配的空间大小都是16字节的整数倍。
如
assume cs:code,ds:data,ss:stack
data segment
dw 0123H,0456H
data ends
stack segment
dw 0,0
stack ends
code segment
...
code ends
...
上述代码虽然定义的数据段只有两个字,4个字节大小,但是在程序加载时分配的空间为16字节,后12个字节单元中的值均为0。栈段也是如此。
如果段中的数据占有N个字节,则程序加载后,该段实际占有的空间为(N/16+1)*16字节大小。
(5),编写code中代码,将a段和b段中的数据依次相加,将结果存到c段中。
assum cs:code
a segment
db 1,2,3,4,5,6,7,8
a ends
b segment
db 1,2,3,4,5,6,7,8
b ends
c segment
db 0,0,0,0,0,0,0,0
c ends
code segment
start: mov ax,a 先将a段和b段中数据相加的结果保存到a段中
mov ds,ax
mov ax,b
mov es,ax
mov bx,0
mov cx,8
s: add byte ptr [bx],es:[bx]
每个字节相加
inc bx
loop s
mov ax,c 将a段中的结果保存到c段中。
mov es,ax
mov bx,0
mov cx,8
s: mov byte ptr es:[bx],[bx]
inc bx
loop s
mov ax,4x00h
int 21h
code ends
end start
(6),编写code中代码,用push指令将a段中的前8个字型数据,逆序存储到b段中。
assum cs:code
a segment
dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
a ends
b segment
dw 0,0,0,0,0,0,0,0
b ends
code segment
start: mov ax,b
mov ss,ax
mov sp,10h
将b段作为栈段
mov ax,a
mov ds,ax
mov bx,0
mov cx,8
s: push [bx]
只需要依次入栈即可。(栈操作中的数据都为字型)
add bx,2
注意:此处为加2.
loop s
mov ax,4x00h
int 21h
code ends
end start
最后
以上就是呆萌身影为你收集整理的汇编语言随笔(5)-and、or指令,串传送指令movsb、访问内存单元的方式及实验4,5(向内存传送数据)的全部内容,希望文章能够帮你解决汇编语言随笔(5)-and、or指令,串传送指令movsb、访问内存单元的方式及实验4,5(向内存传送数据)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复