汇编语言随笔(5)-and、or指令,串传送指令movsb、访问内存单元的方式及实验4,5(向内存传送数据)

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
 		

おすすめ

転載: blog.csdn.net/Little_ant_/article/details/108186037