ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

灵活定位内存地址

2020-12-08 23:04:41  阅读:276  来源: 互联网

标签:定位 code 灵活 data mov al ax 内存地址 bx


灵活定位内存地址,灵活应用

1.0 and和or指令

  • and指令,逻辑运算 &按位与运算 都真为真

  • mov al, 0110 0011B
    and al, 0011 1011B
    
    执行后al=0010 0011B 
    
  • 通过该指令可以将操作对象的相对位设置为0

  • mov al, 1111 1111B
    and al, 1011 1111B
    
    执行后al=1011 1111B
    
    将操作对象的第6位设置为0 
    
  • or指令,逻辑运算 | 按位或运算 都假为假

  • mov al, 0110 0011B
    or  al, 0011 1011B
    
    执行后al=0111 1011B 
    
  • 通过该指令可以将操作对象的相对位设置为1

  • mov al, 0000 0000B
    or  al, 0100 0000B
    
    执行后al=0100 0000B
    
    将操作对象的第6位设置为1 
    

1.1 ASCII

1.2 以字符的形式给出数据集

  • 我们可以在编程时用‘ ...... ‘的方式指定数据是以字符的形式给出的,编译器将他们转换为ASCII码

  • db 'linux'
    db 'unix'
    

1.3 大小写转换的问题

  • 通过对比,我们可以看出小写字母的ASCII码的值比大写字母的大20H,十进制也就是32

  • 可以看出除第五位外,大小写字母的其他各位都是一样的

  • 一个字母,我们不管它之前是不是大写或者小写,我们将他的第5位置改变成0那它就变成大写字母,改为1就是小写

  • assume cs:code,ds:data
    
    data segment
    	db 'LINUX'
    	db 'UNIX'
    data ends
    
    code segment
    start:  mov ax, data
    		mov ds, ax
    	
    		mov bx, 0
    		mov cx, 5
    	
    	  s:mov al, [bx]
    		or al, 00100000B
    		mov [bx], al
    		inc bx
    		loop s
    	
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    

1.4 [bx+idata] [bx+SI+idata] [bx+DI+idata]

  • 为了更好更方便多的访问内存可以用 [bx+idata] 用bx加上一个常量来进行寻址

  • [bx+idata]的方式进行数组的处理

  • 数组是在内存中一连串的区域,这个区域都是同一类型的变量

  • 将上面程序用[bx+idata]修改,将’basic‘大写

  • assume cs:code,ds:data
    
    data segment
    	db 'LINUX'
    	db 'basic'
    data ends
    
    code segment
    start:  mov ax, data
    		mov ds, ax
    	
    		mov bx, 0
    		mov cx, 5
    	
    	  s:mov al, [bx]
    		or al, 00100000B
    		mov [bx], al
    		mov al, [bx+5]
    		and al, 11011111B
    		mov [bx+5], al
    	
    		inc bx
    		loop s
    	
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    
  • [bx+idata]的方式为高级语言实现数组提供了变利的条件

1.5 SI和DI

  • SI和DI和bx寄存器的功能是相近的,但是他们不能拆成两个8位的寄存器

  • 以下s三组代码实现了相同的功能

  • mov bx, 0
    mov ax, [bx]
    
    mov si,0
    mov ax, [si]
    
    mov di,0
    mov ax, [di]
    
  • 由SI和DI 实现将字符串”helloworld“复制到它后面的数据区中 看代码

  • SI指向原始字符串,DI指向复制的空间,然后循环完成复制

  • assume cs:code,ds:data
    
    data segment
    	db 'helloworld'
    	db '..........'
    data ends
    
    code segment
    
    start:	mov ax, data
    		mov ds, ax
    		
    		mov si, 0
    		mov di, 10
    		
    		mov cx, 5
    		
    	f:  mov ax, [si]
    		mov [di], ax
    		
    		add si, 2
    		add di, 2
    		
    		loop f
    		
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    
  • 用[bx+idata] 简化程序

  • assume cs:code,ds:data
    
    data segment
    	db 'helloworld'
    	db '..........'
    data ends
    
    code segment
    start:	mov ax, data
    		mov ds, ax
    		mov si, 0		
    		mov cx, 5	
    		
    	f:  mov ax, [si]
    		mov [si+10], ax
    		add si, 2
    		loop f
    		
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    

1.6 编程题

  • 1.实现定义字符的大写首字母

  • assume cs:code,ds:data
    
    data segment
    	db '1. edit   '
    	db '2. file   '
    	db '3. view   '
    	db '4. help   '
    data ends
    
    code segment
    start:	mov ax, data
    		mov ds, ax
    		
    		mov bx, 0
    		mov cx, 4
    	s:	mov al, [bx+3]
    		and al, 11011111B
    		
    		mov [bx+3], al
    		add bx, 10
    		loop s
    		
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    
  • 2.实现将字符全部大写,我们需要进行4*3次的双重循环

  • assume cs:code,ds:data,ss:stack
    
    data segment
    	db '1. edit   '
    	db '2. file   '
    	db '3. view   '
    	db '4. help   '
    data ends
    
    stack segment
    	dw 0,0,0,0,0,0,0,0   ;定义栈区,用来存放cx循环的值  16个字节
    stack ends
    
    code segment
    start:	mov ax, stack
    		mov ss, ax
    		mov sp, 16
    		
    		mov ax, data
    		mov ds, ax
    		
    		mov bx, 0
    		mov cx, 4		;定义外层循环
    	s0: push cx			;将cx的值进行压栈
    		mov si, 3
    		mov cx, 4		;定义内层循环
    	s:	mov al, [bx+si]
    		and al, 11011111B
    		mov [bx+si], al
    		inc si
    		loop s
    		
    		add bx,10
    		pop cx			;从栈顶弹出原来cx的值
    		loop s0			;外层循环将cx减一
    		
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    

1.7 word ptr

  • 下面的指令中,用word ptr指明了指令访问内存单元是一个字单元数据

  • mov word ptr ds:[0], 1
    add word ptr ds:[0], 1
    inc word ptr [bx]
    
    下面的指令中,用word ptr指明了指令访问内存单元是一个字节单元数据
    mov byte ptr ds:[0], 1   ;
    
  • 在没有寄存器参与的内存单元访问指令中,用word ptr byte ptr显性的指出所要访问内存单元的长度是很有必要的

  • 否则CPU无法得知所要访问的是字单元,还是字节单元

1.8 寻址方式的综合应用

  • 一般来说,我们用[bx+idata+si] 的方式来访问结构体中的数据
  • 用bx定义结构体,idata定义结构体中的某一个数据项,用si定位数据项中单个元素

1.9 div指令

  • division 是除法指令 注意事项

  • 除数:8位或者16位在寄存器中或者在内存单元中

  • 被除数:默认放在AX 或DX和AX中

  • 除数是8位的话 商存储在al中 余数存储到ah中
    除数是16位的话 商存储在ax中 余数存储到dx中

  • 计算10/3

  • assume cs:code,ds:data
    
    data segment
    	db 3							;定义除数
    data ends
    
    code segment
    
    start: 	mov ax, data
    		mov ds, ax
    		
    		mov ax, 10					;定义被除数
    		mov bx, 0
    		div byte ptr [bx] 			;指向定义的除数
    		
    		mov ax, 4c00H
    		int 21H
    		;除数是8位的话  商存储在al中  余数存储到ah中
    		;除数是16位的话 商存储在ax中  余数存储到dx中
    code ends
    
    end start
    		
    
  • 如果除数是16位的话

  • assume cs:code,ds:data
    
    data segment
    	db 3
    data ends
    
    code segment
    
    start: 	mov ax, data
    		mov ds, ax
    		
    		mov ax, 1				;0000 0000 0000 0001
    		mov dx, 1				;0000 0000 0000 0001
    		mov bx, 0
    		div word ptr [bx] 		;这里就是dx在高位 ax在地位 0000 0000 0000 0001 0000 0000 0000 0001 
    								;十进制65537/3
    								;商存在AX中
    								;余数存储到DX中
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    		
    
  • 如果除数是16位的话 被除数是32位,高16位在dx中,低16位在ax中,如上代码

2.0 伪指令 DD dd

  • dd是用来定义dword(double word)双字型数据 32个字节

  • dd 31415926  ;占32个字节     正常定义即可
    

2.1 dup duplicate 复制

  • dup是一个操作符,在汇编语言中同db dw dd一样,是由编译器处理的符号

  • 它是配合db dw dd 符号使用的,用来数据的重复

  • db 3 dup(0)  ;定义三个字节他们的值都是0
    db 0,0,0     ;相当于这样
    
    db 3 dup(0,1,2)  		;定义九个个字节他们的值是0,1,2,0,1,2,0,1,2
    db 0,1,2,0,1,2,0,1,2    ;相当于这样
    
    assume cs:code,ds:data
    
    data segment
    	db 2 dup('helloworld')    ;连续定义两个以字节为单位的helloworld
    data ends
    
    code segment
    
    start: 	mov ax, data
    		mov ds, ax
    		mov ax, 4c00H
    		int 21H
    		
    code ends
    
    end start
    

总结 实验

  • 将data中数据按格式存入table段中
  • 可以用循环来减少代码
assume cs:code,ds:data,es:table,ss:stack

data segment
	db '1990','1991','1992','1993','1994','1995','1996','1997','1998','1999','2000'
	db '2001','2002','2003','2004','2005','2006','2007','2008','2009','2010'  ;最近21年的年份
	;计算年份的偏移地址 4*21=84  十六进制54H用53H
	dd 116,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,5840  ;21年每年的收入
	;计算收入的偏移地址 54H+54H=A8H  用A7H
	dw 1,6,9,12,113,6,9,12,113,6,9,12,113,6,9,12,113,6,9,12,50				;21年每年的人数
	;计算人数的偏移地址 A8H+2A=D2  用D1
data ends		

table segment
	db 21 dup('year summ ne !! ')
table ends

stack segment
	dw 8 dup('0')
stack ends

code segment
start:	mov ax, data
		mov ds, ax		;将ds和data挂钩
		
		mov ax, table
		mov es, ax		;将es和table挂钩
		
		mov bx, 0		;初始化参数
		mov si, 0
		mov di, 0
		mov cx, 21      ;设置循环次数21次
	s:	mov al, ds:[bx]		;存放年份
		mov es:[di], al
		
		mov al, ds:[bx+1]
		mov es:[di+1], al
		
		mov al, ds:[bx+2]
		mov es:[di+2], al
		
		mov al, ds:[bx+3]
		mov es:[di+3], al
		
		mov ax, [bx+54H]	;存放收入
		mov dx, [bx+56H]
		mov es:[di+5H], ax
		mov es:[di+7H], dx
		
		mov ax, [si+0A8H]	;存放人数
		mov es:[di+0AH], ax
		
		mov ax, [bx+54H]	;存放人均收入
		mov dx, [bx+56H]
		
		div word ptr ds:[si+0A8H]
		mov es:[di+0dH], ax
		
		add bx, 4
		add di, 16
		add si, 2
		loop s
		
		mov ax, 4c00H
		int 21H
code ends

end start

标签:定位,code,灵活,data,mov,al,ax,内存地址,bx
来源: https://www.cnblogs.com/immortal-mode/p/14106171.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有