汇编语言-内存定位方法
我们使用编程解决的问题通常都是处理数据。在学习汇编语言过程中,数据通常存储在内存中。在进行数据处理之前,我们需要读取内存中特定位置的数据,此时就涉及到内存地址定位的问题。围绕此问题,本文介绍了汇编语言中内存定位方法。文章目录
前言
本文主要介绍了6中内存定位方法,包括[0]、[bx]、[bx+idata]、SI和DI、[bx+SI(DI)及[bx+SI(DI)+data]。主要阐述了各种方法的使用方法和原理,并给出了相关实践代码。一、内存定位方式
二、使用步骤
1.[0]
[0]表示内存单元,其段地址是ds,偏移地址为0,内存单元长度取决于寄存器。类似写法为[1]、[2]、…、[n]。通用表示为[data],其段地址为ds,偏移地址为data的内存单元,物理地址=(ds)*16+(data)
mov ax,[0]
;表示将段地址为ds,偏移地址为0,长度为2个字节的内存单元中的内容放入ax中
mov al,[0]
;表示将段地址为ds,偏移地址为0,长度为1个字节的内存单元中的内容放入al中
2.[bx]
bx为数据寄存器,[bx]表示段地址为ds,偏移地址在bx中的一个内存单元,内存单元长度取决于目标寄存器位数。
mov bx,0
mov ax,[bx]
;表示将表示将段地址为ds,偏移地址为bx中的内容,长度为2个字节的内存单元中的内容放入ax中
mov bx,0
mov al,[bx]
;表示将表示将段地址为ds,偏移地址为bx中的内容,长度为1个字节的内存单元中的内容放入al中
3.[bx+idata]
bx为寄存器,data表示整数值。[bx+idata]表示一个内存单元,其段地址为ds,偏移地址为(bx)+idata(bx中的数值加上idata)。
mov ax,[bx+200]
;表示将一个内存单元的内容送入 ax,这个内存单元的长度为 2 个字节(字单元),存放一个字,偏移地址为 bx 中的数值加上 200,段地址在 ds 中。
该指令常用格式为:
mov ax,[200+bx]
mov ax,200[bx]
mov ax,[bx].200
4.SI和DI
si和di是8086CPU中和bx功能相近的寄存器,但si和di不能够分成两个8位寄存器来使用。
mov di,0
mov ax,[di]
;表示将一个内存单元的内容送入ax,这个内存单元的长度位2个字节(字单元),存放一个字,偏移地址位si中的数值,段地址在ds中
mov si,0
mov ax,[si]
;表示将一个内存单元的内容送入ax,这个内存单元的长度位2个字节(字单元),存放一个字,偏移地址位si中的数值,段地址在ds中
代码案例:用si和di实现将字符串‘welcom to masm’复制到它后面的数据区中。
assume cs:code,ds:data,ss:stack
data segment
db 'welcom to masm!'
db '...............'
data ends
stack segment
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
stack ends
code segment
start: mov dx,data
mov ds,dx
mov dx,stack
mov ss,dx
mov sp,128
mov si,0
mov di,16
mov cx,8
copyData: mov ax,[si]
mov [di],ax
add di,2
add si,2
loop copyData
mov ax,4c00H
int 21H
code ends
end start
5.[bx+si]和[bx+di]
[bx+si]和[bx+di]都表示一个内存单元,它的偏移地址为(bx)+(si)或者(bx)+(di)(即bx中的数值加上s或di中的数值)
mov ax,[bx+si]
;表示将一个内存单元的内容送入ax,这个内存单元的长度为2个字节(字单元),存放一个字,偏移地址为bx中的数值加上si中的数值,段地址在ds中
mov ax,[bx+di]
;表示将一个内存单元的内容送入ax,这个内存单元的长度为2个字节(字单元),存放一个字,偏移地址为bx中的数值加上di中的数值,段地址在ds中
6.[bx+si+idata]和[bx+di+idata]
[bx+si+idata]和[bx+di+idata]都表示一个内存单元,它的偏移地址为(bx)+(si)+idata或(bx)+(di)+idata,段地址在ds中。
mov ax,[bx+si+idata]
;表示将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为bx中的数值加上si中的数值再加上idata,段地址在ds中。
mov ax,[bx+di+idata]
;表示将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为bx中的数值加上di中的数值再加上idata,段地址在ds中
该指令的常用格式:
mov ax,[bx+200+si]
mov ax,[200+bx+si]
mov ax,200[bx][si]
mov ax,[bx].200[si]
mov ax,[bx][si].200
三、比较不同的内存定位方式
- [idata]用一个常量表示地址,可用于直接定位一个内存单元,内存单元长度取决于目标寄存器位数;
- [bx]用一个变量表示内存地址,可用于间接定位一个内存单元,内存单元长度取决于目标寄存器位数;
- [bx+idata]用一个变量和一个常量表示内存地址,可在一个起始地址的基础上用变量间接的定位一个内存单元,内存单元长度取决于目标寄存器位数;
- [si]和[di]都是用一个变量表示内存地址,可用于间接定位一个内存单元,此内存单元的长度为2个字节;
- [bx+si]和[bx+di]都是用两个变量表示地址;可用于间接定位一个内存单元,内存单元长度取决于目标寄存器位数;
- [bx+si+idata]和[bx+di+idata]都是用一个常量和两个变量表示内存地址,内存单元长度取决于目标寄存器位数;
四、使用案例分析
1.将data segment段中每个单词的头一个字母改为大写字母
assume cs:code,ds:data,ss:stack
data segment
db '1.file '
db '2.edit '
db '3.search '
db '4.view '
db '5.options '
db '6.help '
data ends
stack segment
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
stack ends
code segment
start: mov dx,data
mov ds,dx
mov dx,stack
mov ss,dx
mov sp,128
mov bx,0
mov cx,6
upFirstLetter: mov al,ds:[bx+2]
and al,11011111B
mov ds:[bx+2],al
add bx,16
loop upFirstLetter
mov ax,4c00H
int 21H
code ends
end start
代码分析: 由于题目要求仅将一个字母改为大写字母,故内存定位方式的选择使用si和di方式(原因在于其不能分为两个8位寄存器)。第二,为了简化代码,使用循环形式实现,[idata]直接定位内存方式不利用实现,故不选用此种方式。综上所述采用[bx+idata]的方式定位内存。
1.将data segment段中每个单词改为大写字母
采用[bx+si]内存定位方式
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
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
stack ends
code segment
start: mov dx,data
mov ds,dx
mov dx,stack
mov ss,dx
mov sp,128
mov bx,0
mov cx,4
upLetterRow: mov si,0
push cx
mov cx,3
upLetterColum: mov al,ds:[bx+si]
and al,11011111B
mov ds:[bx+si],al
inc si
loop upLetterColum
pop cx
add bx,16
loop upLetterRow
mov ax,4c00H
int 21H
code ends
end start