动态线条
动态线条end

内存寻址方式

处理字符问题

处理字符问题

汇编程序中,用单引号将字符括起来,编译器在编译过程中将字符转换为对应的ascii码值

ASCII表

image-20220109161937274

解决大小写转换问题

转换原理

1)对比大写A与小写a的ascii码值的二进制形式(其他字符同下述对比过程)
     A:‭0 1 0 0 0 0 0 1‬

     a:‭0 1 1 0 0 0 0 1‬

2)经多组对比发现,大写字符与小写字符的区别在于第六位二进制,如果为1,那么该字符为小写,反之为大写

3)因此如果进行大小写转换,可利用 or 和 and 操作符进行操作

     如:A变为a

    0 1 0 0 0 0 0 1
or  0 ‬0 1 0 0 0 0 0
---------------------
    0 1 1 0 0 0 0 1‬

4)小写变成大写:a变为A

     0 1 1 0 0 0 0 1
and1‬ 1 1 0 1 1 1 1 1
---------------------
     0 1 0 0 0 0 0 1

汇编实现代码如下

assume cs:code,ds:data
data segment
	db 'asdfgh'			;将小写变为大写
	db 'ZXCVBN'			;将大写变为小写
data ends

code segment
start:
	mov ax,data
	mov ds,ax			;初始化数据段的位置
	
	mov ax,0			;存放临时数据
	
	mov bx,0			;将偏移量初始化为0
	mov cx,6			;循环六次
l:
	mov al,ds:[bx]		;取出数据段数据
	and al,1‬1011111b	 ;进行与运算
	mov ds:[bx],al		;将运算结果存入刚刚取出该数据的空间
	inc bx				;bx自行加一,向后偏移
loop l
	
	mov cx,6			;循环六次
	
ll:
	mov al,ds:[bx]		;取出数据段数据
	or  al,00100000b	;进行或运算
	mov ds:[bx],al		;将运算结果存入刚刚取出该数据的空间
	inc bx				;bx自行加一,向后偏移
loop ll
	
	
	mov ax,4c00H
	int 21H
code ends
end start

image-20220109174015962

[bx + idata] 方式寻址

含义

1)[bx + idata]表示一个内存单元,它的偏移地址为(bx) + idata(bx中的数值加上idata)

2)mov ax,[bx + 200] 的含义

     1)将一个内存单元送入ax

     2)这个内存单元的长度为2字节(字单元),存放一个字

     3)内存单元的段地址在ds中,偏移地址为200加上bx的数值

     4)数学化描述:ax = ((ds)* 16 + 200 + bx)

上述寻址方式的常见写法

1)mov ax,[200 + bx]

2)mov ax,200[bx]

3)mov ax,[bx].200

更改大小写转换代码(前提:同长度字符串)

.....
	mov bx,0			;将偏移量初始化为0
	mov cx,6			;循环六次
l:
	mov al,ds:[bx]		;取出数据段数据
	and al,1‬1011111b	 ;进行与运算
	mov ds:[bx],al		;将运算结果存入刚刚取出该数据的空间

	mov al,ds:[bx + 6]		;取出数据段数据
	or  al,00100000b	;进行或运算
	mov ds:[bx],al		;将运算结果存入刚刚取出该数据的空间
	inc bx				;bx自行加一,向后偏移
loop l
.....

SI与DI寄存器(变址寄存器)

BX:通用寄存器,在计算机存储地址时,常作为基址寄存器使用

SI:source index,源变址寄存器

DI:destination index,目标变址寄存器

三种寄存器可实现相同的功能

mov bx,0
mov ax,[bx + 常量]

mov si,0
mov ax,[si + 常量]

mov di,0
mov ax,[di + 常量]

用寄存器SI和DI实现将字符串'welcome to masm!'复制到它后面的数据区中。

assume cs:code,ds:data
data segment
	db 'welcome to masm!'
	db '................'
data ends
code segment
start:
	mov ax,data
	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
code ends
end start

[si + bx] 与 [di + bx] 寻址方式

下述汇编代码

mov ax,2000H
mov ds,ax
mov bx,1000H
mov si,0
mov ax,[bx + si]
inc si
mov cx,[bx + di]
inc si
mov di,si
mov ax,[bx + di]

对内存的寻址方式

形式 名称 特点 意义 示例
[idata] 直接寻址 用一个常量/立即数表示地址 用于直接定位一个内存单元 mov ax,[200]
[bx] 寄存器间接寻址 用一个变量来表示内存地址 用于间接定位一个内存单元 mov bx,0
mov ax,[bx]
[bx + idata] 寄存器相对寻址 用一个变量和常量表示地址 可在一个起始地址的基础上用变量间接定位一个内存单元 mov bx,4
mov ax,[bx + 200]
[bx + si] 基址变址寻址 用两个变量表示地址 mov ax,[bx + si]
[bx + si + idata] 相对基址,变址寻址 用两个变量和一个常量表示地址 mov ax,[bx + si + 200]

如果汇编程序中出现了需要双重循环的情况,解决办法如下:

1)利用寄存器保存循环时需要的循环次数

.....
	mov cx,4	;外层循环需要循环四次
waiceng:
	mov bx,cx	;将cx中的剩余循环次数放置到bx
	mov cx,3	;内层循环需要循环三次
neiceng:
	.....
	loop neiceng
	mov cx,bx	;将剩余的循环次数放置到cx中进行递减一
	loop waiceng
.....

但是该方式必须占用一个寄存器当做存储空间,但是寄存器只有14个(8086CPU),因此占一个寄存器进行存储临时值不现实。

2)用固定的内存空间保存数据

.....
	mov cx,4			;外层循环需要循环四次
waiceng:
	mov ds:[40H],cx		;将cx中的剩余循环次数放置到指定内存空间
	mov cx,3			;内层循环需要循环三次
neiceng:
	.....
	loop neiceng
	mov cx,ds:[40H]		;将剩余的循环次数放置到cx中进行递减一
	loop waiceng
.....

但是这种情况造成的情况就是,占用的空间位置是固定的,如果该空间被其他程序所占用,那么如果对该空间数值进行更改,可能会造成无法预见的错误。

3)利用栈解决存储

.....
	mov cx,4	;外层循环需要循环四次
waiceng:
	push cx		;将cx中的剩余循环次数放置到bx
	mov cx,3	;内层循环需要循环三次
neiceng:
	.....
	loop neiceng
	pop cx		;将剩余的循环次数放置到cx中进行递减一
	loop waiceng
.....

该情况较为完美的解决了临时数据的存储

用于寻址的寄存器

寻址寄存器

BX:通用寄存器,在计算机存储地址时,常作为基址寄存器使用

SI:source index,源变址寄存器

DI:destination index,目标变址寄存器

BP:指针寄存器

在[ ]中只能存在上述四种寻址寄存器,而类似 mov cx,[ax] 的指令操作是错误的

四种寄存器可产生的 合法 组合

1)bx + di

2)bx + si

3)bp + di

4)bp + si

bp与bx区别

1)bx默认指向ds段

2)bp默认指向ss段

汇编指令 数学含义
mov ax,[bp] ax = ((ss) * 16 + (bp))
mov ax,ds:[bp] ax = ((ds) * 16 + (bp))
mov ax,es:[bp] ax = ((es) * 16 + (bp))
mov ax,[bx] ax = ((ds) * 16 + (bx))
mov ax,ss:[bx] ax = ((ss) * 16 + (bx))
mov ax,[bp + idata] ax = ((ss) * 16 + (bp) + idata)
mov ax,[bp + si] ax = ((ss) * 16 + (bx) + (si))
mov ax,[bp + si + idata] ax = ((ss) * 16 + (bp) + (si) + idata)

数据在哪里?有多长?

汇编语言中数据位置的表达

1)立即数(idata)

     对于直接包含在机器指令中的数据,被称为立即数,数据包含在指令中

2)寄存器

     指令要处理的数据在寄存器中,在汇编指令中给出响应的寄存器名称

3)内存:段地址(SA)和偏移地址(EA)

     指令要处理的数据在内存中,有SA:EA确定内存单元

汇编语言中指令要处理的数据有多长(8086CPU)

1)字word操作:十六位寄存器,十六位操作

2)字节byte操作:八位的字节操作

在没有寄存器参与的内存单元访问指令中,用word ptr与byte ptr进行标明所要访问的内存房源长度是很必要的,否则cpu无法得知所要访问的单元时字单元还是字节单元。

mov word ptr ds:[0],1
inc word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx],2
mov byte ptr ds:[0],1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx],2

div指令实现除法

div是除法指令,使用div做除法时

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

2)除数:八位或十六位,在寄存器或内存单元中

3)结果

div指令格式

1)div 寄存器

2)div 内存单元

被除数 AX DX和AX
除数 八位内存或寄存器 十六位内存或寄存器
AL AX
余数 AH DX

dup设置内存空间

功能:dup和db、dw、dd等数据定义伪指令配合使用,用来进行数据的重复。

示例:

指令 功能 等同
db 3 dup (0) 定义了三个字节,值全为0 db 0,0,0
db 2 dup (0,1,2) 定义了九个字节,由0、1、2重复三次构成 db 0,1,2,0,1,2,0,1,2
db 3 dup ('abc','ABC') 定义了十八个字节,由'abcABC'循环三组构成 db 'abcABCabcABCabcABC'

dup使用格式

1)db 重复的次数 dup(重复的字节型数据)

2)dw 重复的次数 dup(重复的字型数据)

3)dd 重复的次数 dup(重复的双字型数据)

实例应用

定义一个200个字节的栈段

db 200 dup (0)

应用于汇编程序

assume cs:code,ds:data
data segment
	db 3 dup (0)
	db 3 dup (0,1,2)
	db 80 dup (0)
	db 3 dup ('abc','ABC')
data ends
code segment
	mov ax,data
	mov ds,ax
	
	mov ax,4c00H
	int 21H
code ends

posted @ 2022-01-16 14:39  v1v1v1  阅读(518)  评论(0)    收藏  举报