汇编语言-王爽 第7章 更灵活的定位内存地址的方法-笔记

  • Post author:
  • Post category:其他




将datasg中的第一个字符串转化为大写,第二个字符串转化为小写。

第一种方法:

assume cs:codesg,ds:datasg

datasg segment

	db 'BaSic'
	db 'iNfOrMaTiOn'
	
datasg ends

codesg 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, 11011111h		;将al中的ASCII码的第5位置为0,变为大写字母
			mov [bx], al			;将转变后的ASCII码写回原单元
			inc bx					;(bx)1,ds:bx指向下一个字母
			loop s		
			
			mov bx, 5				;设置(bx)=5,ds:bx指向'iNfOrMaTiOn'的第一个字母
			
			mov cx, 11
		s0:	mov al, [bx]
			or al, 00100000h
			mov [bx], al
			inc bx
			loop s0
			
			mov ax, 4c00h
			int 21h
			
codesg ends

end start

第二种方法:用[bx + idata]的方式进行数组的处理

将两个字符串看作两个数组,一个从0地址开始存放,另一个从5开始存放。那么可以用[0+bx]和[5+bx]的方式在同一个循环种定位这两个字符串中的字符。0和5给定了两个字符串的起始偏移地址,bx中给出了从起始偏移地址开始的相对地址。这两个字符串在内存中的起始地址是不一样的,但是,它们中的每一个字符,从起始地址开始的相对地址的变化是相同的。

assume cs:codesg,ds:datasg

datasg segment

	db 'BaSic'
	db 'iNfOr'
	
datasg ends

codesg segment 

	start:	mov ax, datasg
			mov ds, ax				
			
			mov bx, 0				
			
			mov cx, 5				
		s:	mov al, [bx]		;定位第一个字符串种的字符	
			and al, 11011111h		
			mov [bx], al
			
			mov al, [5+bx]		;定位第二个字符串种的字符
			or al, 00100000h
			mov [bx], al			
			inc bx					
			loop s		
			
			mov ax, 4c00h
			int 21h
			
codesg ends

end start



用di和si实现将字符串’welcome to masm!’复制到它后面的数据区中

用di和si实现将字符串’welcome to masm!’复制到它后面的数据区中

用ds:si指向要复制的源始字符串,用ds:di指向复制的目的空间,然后用一个循环来完成复制。

assume cs:codesg,ds:datasg

datasg segment

	db 'welcome to masm!'
	db '                '
	
datasg ends

codesg segment 

	start:	mov ax, datasg
			mov ds, ax				
			mov si, 0
			mov di, 16
			
			mov cx, 8				
		s:	mov ax, [si]				
			mov [di], ax		
			add si, 2
			add di, 2
			loop s		
			
			mov ax, 4c00h
			int 21h
			
codesg ends

end start

利用[bx(si或di)+idata]的方式,来使程序变得简洁

assume cs:codesg,ds:datasg

datasg segment

	db 'welcome to masm!'
	db '                '
	
datasg ends

codesg segment 

	start:	mov ax, datasg
			mov ds, ax	
			mov si, 0
			mov cx, 8				
		s:	mov ax, 0[si]		
			mov 16[si], ax		
			add si, 2
			loop s		
			
			mov ax, 4c00h
			int 21h
			
codesg ends

end start



编程将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 

		mov ax, datasg
		mov ds, ax
		mov bx, 0
		
	s:	mov al, [bx+3]
		and al, 11011111b
		mov [bx+3], al
		add bx, 16
		loop s

		mov ax, 4c00h
		int 21h
			
codesg ends

end start



编程将datasg段中每个单词改为大写字母

在这里插入图片描述

我们用bx用作变量,定位每行的起始地址,用si定位要修改的列,用[bx+si]的方式来对目标单位进行寻址。

assume cs:codesg,ds:datasg

datasg segment

	db 'ibm             '
	db 'dec             '
	db 'dos             '
	db 'vax             '
	
datasg ends

codesg segment 

		mov ax, datasg
		mov ds, ax
		mov bx, 0
		
		mov cx, 4
		
	s0:	mov dx, cx   ;**将外层循环的cx的值保存在dx中**
		mov si, 0
		mov cx, 3    ;cx设置为内存循环的次数
	
	s:	mov al, [bx+si]
		and al, 11011111b
		mov [bx+si], al
		inc si
		loop s
		
		add bx, 16
		mov cx, dx		;**用dx中存放的外层循环的计数值恢复cx**
		loop s0			;外层循环的loop指令将cx中的计数值减1

		mov ax, 4c00h
		int 21h	
			
codesg ends

end start

将需要暂存的数据放到内存单元中

assume cs:codesg,ds:datasg

datasg segment

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

codesg segment 

start:	mov ax, datasg
		mov ds, ax
		mov bx, 0
		
		mov cx, 4
		
	s0:	mov ds:[40H], cx   ;将外层循环的cx的值保存在datasg:40H单元中
		mov si, 0
		mov cx, 3    ;cx设置为内存循环的次数
	
	s:	mov al, [bx+si]
		and al, 11011111b
		mov [bx+si], al
		inc si
		loop s
		
		add bx, 16
		mov cx, ds:[40H]	;用datasg:40H单元中的值恢复cx
		loop s0			;外层循环的loop指令将cx中的计数值减1

		mov ax, 4c00h
		int 21h
			
codesg ends

end start

一般来说,在需要暂存数据的时候,我们都应该使用栈。

assume cs:codesg ds:datasg

datasg segment

	db 'ibm             '
	db 'dec             '
	db 'dos             '
	db 'vax             '
	
datasg ends

stacksg segment				;定义一个段,用来做栈段,容量为16个字节

	dw 0, 0, 0, 0, 0, 0, 0, 0

stack ends

codesg segment 

start:	mov ax, stacksg
		mov ss, ax
		mov sp, 16 	

		mov ax, datasg
		mov ds, ax
		mov bx, 0
		
		mov cx, 4
		
	s0:	push cx				;将外层循环的cx值压栈
		mov si, 0
		mov cx, 3			;cx设置为内层循环的次数
		
	s:	mov al, [bx+si]
		and al, 11011111b
		mov [bx+si], al
		inc si
		loop s
		
		add bx, 16
		pop cx				;从栈顶弹出原cx的值,恢复cx
		loop s0				;外层循环的loop指令将cx中的计数值减1
		
		mov ax, 4c00h
		int 21h

codesg ends

end start



编程将datasg段中每个单词的前4个字母改为大写字母

在这里插入图片描述

我们用bx来做变量,定位每行的起始地址,用si定位要修改的列,用[bx+3+si]的方式来对目标单元进行寻址。

assume cs:codesg,ss:stacksg,ds:datasg

datasg segment

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

stacksg segment				

	dw 0, 0, 0, 0, 0, 0, 0, 0

stack ends

codesg segment 

start:	mov ax, stacksg
		mov ss, ax
		mov sp, 16 	

		mov ax, datasg
		mov ds, ax
		mov bx, 0
		
		mov cx, 4
		
	s0:	push cx				;将外层循环的cx值压栈
		mov si, 0
		mov cx, 4			;cx设置为内层循环的次数
		
	s:	mov al, [bx+si+3]
		and al, 11011111b
		mov [bx+si+3], al
		inc si
		loop s
		
		add bx, 16
		pop cx				;从栈顶弹出原cx的值,恢复cx
		loop s0				;外层循环的loop指令将cx中的计数值减1
		
		mov ax, 4c00h
		int 21h

codesg ends

end start



版权声明:本文为weixin_46708000原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。