首页 > 代码库 > 汇编入门学习笔记 (六)—— si、di,双重循环

汇编入门学习笔记 (六)—— si、di,双重循环

疯狂的暑假学习之  汇编入门学习笔记 (六)—— 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