汇编简单入门教程(六)si、di,双重循环


 

参考: 《汇编语言》 王爽 第7章

 

1. and和or指令,与[bx+idata]

 

and和or,就不多说了。

[bx+idata] 这样写是可以的,某些情况下,比较方便。

[bx+idata] 也可以写成 idata[bx]


直接见例子: 把’ABcde‘ 跟 ‘fGHig’ 都改成大写(ASCII中大写字母与小写字母二进制中,只有第五位不同,大写字母是0,小写字母是1)

 

 

assume cs:code,ds:data 

data segment
	db 'ABcde'
	db 'fGHIg'
data ends 

code segment

start:	mov ax,data
	mov ds,ax
		
	mov bx,0
	mov cx,4
	mov al,00100000b
s:	or [bx],al
	or [5+bx],al ;[5+bx]也可以写成5[bx]
	inc bx
	loop s
		
		
	mov ax,4c00H
	int 21H

code ends

end start

 

 

2. si,di,与[bx+si],[bx+di],[bx+si+idata],[bx+di+idata]

 

 

si与di,除了不能像bx一样分成bh,bl,其他与bx一样。如 mov ax,[si] 等等

[bx+si],[bx+di],[bx+si+idata],[bx+idata]

这些都是可以的,某些情况下,比较方便。


其中[bx+si]与[bx+di] 可以写成 [bx][si],[bx][di]

[bx+si+idata],[bx+di+idata] 可以写成idata[bx][si],idata[bx][di]


例子:复制Welcome!

 

assume cs:code,ds:data

data segment
	db 'Welcome!        '
data ends

code segment
	start:	mov ax,data
		mov ds,ax
	
		mov si,0
		mov cx,4
	s:	mov ax,[si]
		mov 8[si],ax
		add si,2
		loop s
			
		mov ax,4c00H
		int 21H
code ends

end start

 

 

例子:将data中的单词的首字母改成大写

 

assume cs:code,ds:data

data segment
	db '1.file  '
	db '2.edit  '
	db '3.search'
	db '4.view  '
data ends

code segment
	start:	mov ax,data
		mov ds,ax
			
		mov bx,0
		mov cx,4
		mov al,11011111b
	s:	and [bx+2],al
		add bx,8
		loop s
			
		mov ax,4c00H
		int 21H
			
			
code ends

end start

 

 


3. 双重循环


例子:data中单词改成大写的

 

assume cs:code,ds:data

data segment
	db 'ibm     '
	db 'dec     '
	db 'dos     '
	db 'vax     '
data ends

code segment
	start:	mov ax,data
		mov ds,ax
			
		mov bx,0
		mov al,11011111b
		mov cx,4
	s:	mov cx,3
		mov si,0
	s0:	and [bx+si],al
		inc si
		loop s0
		
		add bx,8
		loop s
			
		mov ax,4c00H
		int 21H
			
code ends

end start

 

 

上面 的代码,是错误的会出现是死循环。因为cx不断的被赋予3,导致外层循环死循环。

 

改进,在进行内层循环时把cx保存起来,内存循环结束时,恢复cx。例子:


 

assume cs:code,ds:data

data segment
	db 'ibm     '
	db 'dec     '
	db 'dos     '
	db 'vax     '
data ends

code segment
	start:	mov ax,data
		mov ds,ax
			
		mov bx,0
		mov al,11011111b
		mov cx,4
	s:	mov dx,cx  ;dx用来临时存放外层的cx的值
		mov cx,3
		mov si,0
	s0:	and [bx+si],al
		inc si
		loop s0
		mov cx,dx	;用来回复外层循环的cx
		add bx,8
		loop s
			
		mov ax,4c00H
		int 21H
			
code ends

end start

 

 

上面的代码,虽然能解决上面问题,能正常运行。但是寄存器的数量有限,有时,可能没有其他的寄存器可以用。

解决方法,保存在内存中。例子:

 

assume cs:code,ds:data

data segment
	db 'ibm     '
	db 'dec     '
	db 'dos     '
	db 'vax     '
	dw 0    ;定义一个字,用来保存cx
data ends

code segment
	start:	mov ax,data
		mov ds,ax
			
		mov bx,0
		mov al,11011111b
		mov cx,4
	s:	mov ds:[20H],cx  
		mov cx,3
		mov si,0
	s0:	and [bx+si],al
		inc si
		loop s0
		mov cx,ds:[20H]	
		add bx,8
		loop s
			
		mov ax,4c00H
		int 21H
			
code ends

end start

 

 

上面的代码,解决了寄存器不够的情况。但是,还是比较复杂,如果有很多循环,就会弄不清楚。

解决方法,使用栈来保存恢复cx。例子1:

 

assume cs:code,ds:data,ss:stack

data segment
	db 'ibm     '
	db 'dec     '
	db 'dos     '
	db 'vax     '
data ends

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

code segment
	start:	mov ax,data
		mov ds,ax
		mov ax,stack
		mov ss,ax
		mov sp,16
			
		mov bx,0
		mov al,11011111b
		mov cx,4
	s:	push cx
		mov cx,3
		mov si,0
	s0:	and [bx+si],al
		inc si
		loop s0
			
		pop cx
		add bx,8
		loop s
			
		mov ax,4c00H
		int 21H
			
code ends

end start

 

 

例子2:把data中的单词,前3个字母改成大写

 

assume cs:code,ds:data,ss:stack

data segment
	db '1.display.......'
	db '2.brows.........'
	db '3.replace.......'
	db '4.modify........'
data ends

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

code segment
	start:	mov ax,data
		mov ds,ax
		mov ax,stack
		mov ss,ax
		mov sp,16
				
		mov bx,0
		mov al,11011111b
		mov cx,4
	s:	push cx
		mov si,0
		mov cx,3
	s0:	and [bx+si+2],al
		inc si
		loop s0
		
		pop cx
		add bx,10H
		loop s
			
		mov ax,4c00H
		int 21H
		
code ends

end start

 

 

 

 

  • codergeek

    评论: 发现从这章开始有点看不懂了,我日,你的汇编代码是跑在masm中的吗???群主

    2016-05-06 11:40:32          回复