内存寻址方式

1. 处理字符问题

汇编中, 用'...' 的方式致命数据是以字符的形势给出的, 编译器将把他们转化为相对应的ASCII 码

assume cs:code,ds:data
data segment
       db 'unIX'
       db 'foRK'
data ends
code segment
start: mov al,'a'
       mov bl,'b'
       mov ax,4c00h
       int 21h
code ends
end start
字符串转化为对应额ASCII

大小写转换

  • 将第一个字符串, 小写字母转换为大写
  • 将第二个字符串, 大写转换为小写
assume cs:code,ds:data
data segment
       db 'BaSiC'
       db 'iNfOrMaTiOn'
data ends

code segment
start: mov ax,data
       mov ds,ax

       mov bx,0
       mov cx,5
    s: mov al,[bx]
       and al,11011111b
       mov [bx],al
       inc bx
       loop s

       mov bx,5
       mov cx,11
   s0: mov al,[bx]
       or al,00100000b
       mov [bx],al
       inc bx
       loop s0
       
       mov ax,4c00h
       int 21h
code ends
end start
大小写转换结果
大写和小写差值

逻辑与指令add dest,src, 逻辑或指令or dest,src

2. [bx+idata] 方式寻址

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

例如:

mov ax,[bx+200]

  • 将一个内存单元的内容送入ax
  • 内存单元长度为2字节
  • 内存单元段地址在ds 中, 偏移地址为200, 加上bx 中的数值
  • 描述为: (ax)=((ds)*16+200+(bx))

其他用法

mov ax,[200+bx]

mov ax,200[bx]

mov ax,[bx].200

(bx)+idata

类似c 语言中的数组

  • 将第一个字符串转换为大写
  • 第二个转换为小写
assume cs:code,ds:data
data segment
       db 'BaSiC'
       db 'MinIX'
data ends

code segment
start: mov ax,data
       mov ds,ax

       mov bx,0
       mov cx,5
    s: mov al,[bx]
       and al,11011111b
       mov [bx],al
       
       mov al,[5+bx]
       or al,00100000b
       mov [5+bx],al

       inc bx
       loop s
       
       mov ax,4c00h
       int 21h
code ends
end start
使用偏移idata结果

相当于c 语言中的数组

char a[5]="BaSiC";
char b[5]="MinIX";
main(){
  int i;
  i=0;
  do{
    a[i]=a[i]&0xDF;
    b[i]=b[i]|0x20;
    i++;
  }
  while(i<5);
}

3. SI 和DI寄存器

两个寄存器为变址寄存器

常执行与地址有关的操作

SI 和DI 是8086cpu 中和bx 功能相近的寄存器

区别为SI 和DI 不能够区分成两个8 位寄存器来使用

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]

====================

mov bx,0
mov ax,[bx+123]

mov si,0
mov ax,[123]

mov di,0
mov ax,[di+123]

例如, 用寄存器si 和di 实现将字符串'welcome to masm' 复制到它后面的数据区中

ds:si 指向要复制的原始字符串

ds:di 指向目的空间

使用循环完成复制

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
    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和di复制字符串

4. [bx+si] 和[bx+di] 方式寻址

[bx+si] 表示一个内存单元

偏移地址为(bx)+(si), bx 中的数值加上si 的数值

指令mov ax,[bx+si] 含义

  • 将一个内存单元的内容送入ax
  • 这个内存单元长度为2 个字节
  • 偏移地址为bx 中的数值加上si 中的数值
  • 段地址在ds 中
  • 数学化描述为(ax)=((ds)*16+(bx)+(si)), 其他写法mov ax,[bx][si]
[bx+si]和[bx+di]方式寻址

5. [bx+si+idata] 和[bx+di+idata]

[bx+si+idata] 表示一个内存单元

偏移地址为(bx)+(si)+idata, bx 中的数值加上si 数值再加idata

指令mov ax,[bx+si+idata] 含义

  • 将一个内存单元内容送入ax
  • 这个内存单元长度为2 个字节
  • 偏移地址为bx 中的数值加si 数值再加idata, 段地址在ds 中
  • 描述为(ax)=((ds)*16+(bx)+(si)+idata)

其他写法

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
mov ax,[bx][si]
[bx+si+idata]和[bx+di+idata]寻址

6. 不同寻址方式的应用

形式 名称 特点 意义 示例
[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:

将data 段中的每个单词头一个字母改为大写

assume cs:code,ds:data
data segment
       db '1. file         '
       db '2. edit         '
       db '3. search       '
       db '4. view         '
       db '5. options      '
       db '6. help         '
data ends

code segment
start: mov ax,data
       mov ds,ax

       mov bx,0
       mov cx,6
    s: mov al,[bx+3]
       and al,11011111b
       mov [bx+3],al
       
       add bx,16
       loop s
       
       mov ax,4c00h
       int 21h
code ends
end start
每个单词头一个字母改为大写

案例2:

将data 段中的每个单词都改为大写

assume cs:code,ds:data
data segment
       db 'ibm             '
       db 'dec             '
       db 'dox             '
       db 'vax             '
data ends

code segment
start: mov ax,data
       mov ds,ax

       mov bx,0
       mov cx,4
   s0: mov si,0
       mov cx,3
    s: mov al,[bx+si]
       and al,110111111b
       mov [bx+si],al
       inc si 
       loop s
       add bx,16
       loop s0
       
       mov ax,4c00h
       int 21h
code ends
end start

4 个字符串, 看成一个4 行16 列的二维数组, 只要修改二维数组的每一行的前三列, 构造4*3 的二重循环

但是循环次数由cx 决定, cx 只有一个, 此段代码有问题

如何解决?

将外层循环的cx 保存到dx 中, 再将cx 设置为内循环次数3, 内循环完, 再将dx 的值赋值给cx

     s0: mov dx,cx ;将外层cx 保存到dx 中
       mov si,0
       mov cx,3 ;设置内层循环次数
    s: mov al,[bx+si]
       and al,110111111b
       mov [bx+si],al
       inc si 
       loop s
       add bx,16
       mov cx,dx ;恢复cx 外层循环次数
       loop s0

但是寄存器只有14 个, 如果dx 也已经被使用, 还是有问题

如果使用固定的内存空间保存数据, 但是这个内存空间也会被占用的可能

最终的解决方法

使用栈来管理数据

stack segment
       dw 0,0,0,0,0,0,0,0
stack ends

code segment
start: mov ax,data
       mov ds,ax

       mov bx,0
       mov cx,4
   s0: push cx ;将外层循环cx 压栈
       mov si,0
       mov cx,3
    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

7. 用于内存寻址的寄存器

正确的指令

mov ax,[bx]
mov ax,[bx+si]
mov ax,[bx+di]
mov ax,[bp]
mov ax,[bp+si]
mov ax,[bp+di]
mov ax,[bx]
mov ax,[si]
mov ax,[di]
mov ax,[bp]
mov ax,[bx+si]
mov ax,[bx+di]

mov ax,[bp+si]
mov ax,[bp+di]
mov ax,[bx+si+idata]
mov ax,[bx+di+idata]
mov ax,[bp+si+idata]
mov ax,[bp+di+idata]

只有bx, bp, si, di 可以用在[...] 对内存单元寻址

bx 以外的通用寄存器, 段寄存器不可以用在[...] 中

bx 和bp 区别

  • bx 默认指ds 段
  • bp 默认指ss 段

或者直接指定段地址

mov ax,ds:[bp]

mov ax,es"[bp]

8. 处理数据的位置和长度

数据位置的表达

立即数 寄存器 内存:段地址(SA) 和偏移地址(EA)
对于直接包含在机器指令中的数据, 称为立即数idata, 数据包含在指令中
mov ax,1
mov al,'a'
指令要处理的数据在寄存器中, 在汇编指令中给相应的寄存器名
mov ax,bx
mov ds:[0],bx
指令要处理的数据在内存中, 由SA:EA 确定内存单元
段地址偏移地址

要处理数据的长度

要处理数据的长度

9. 寻址方式的案例

一条记录

姓名: yao

生日: 19800912

球衣号码: 15

场均得分: 32

球队: SHH

修改为:

球衣 -> 11

得分 -> 13

球队 -> HOU

修改这条记录
mov ax,seg
mov ds,ax
mov bx,60h
mov word ptr [bx+0ch],11
mov word ptr [bx+0eh],13

mov si,0
mov byte ptr [bx+10h+si],'H'
inc si
mov byte ptr [bx+10h+si],'O'
inc si
mov byte ptr [bx+10h+si],'U'

如果是c 语言则是

#include <stdio.h>
struct Player{
    char name[3];
    char birthday[9];
    int num;
    int ppg;
    char team[3];
};
struct Player yao={"Yao", "19800912", 15, 32, "SHH"}
int main()
{
    int i;
    yao.num = 11;
    yao.ppg = 13;
    i = 0;
    yao.team[i] = "H";
    i++;
    yao.team[i] = "O";
    i++;
    yao.team[i] = "U";
    return 0;
}

yao.team[i]: yao是一个变量名, 指明了结构体变量的地址, team 是一个名称, 指明数据项team 的地址, i 用来定位team 中的字符

用bx 定位整个结构体, 用idata 定位结构体中的某一个数据项, 用si 定位数据项中的元素

10. div 指令实现除法

  • 被除数: 默认放在ax 或dx 和ax 中
  • 除数: 8 位或16 位, 在寄存器或内存单元中

格式为

  • div 寄存器
  • div 内存单元

结果

被除数 ax dx 和ax
除数 8 位内存或寄存器 16 位内存或寄存器
al ax
余数 ah dx
指令 被除数 除数 余数
div bl (ax) (bl) (al) (ah)
div byte ptr ds:[0] (ax) ((ds)*16+0) (al) (ah)
div byte ptr [bx+si+8] (ax) ((ds)*16+(bx) +(si)+8) (al) (ah)
div bx (dx)*10000H+(ax) (bx) (ax) (dx)
div word ptr es:[0] (dx)*10000H+(ax) ((ds)*16+0) (ax) (dx)
div word ptr [bx+si+8] (dx)*10000H+(ax) ((ds)*16+(bx) +(si)+8) (ax) (dx)

注意: 提前在默认的寄存器中设置好被除数, 且不能用在别处

11. dup 设置内存空间

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

指令 功能 相当于
db 3 dup(0) 定义3 个字节, 值都是0 db 0,0,0
db 3 dup(0,1,2) 定义9 个字节, 由0,1,2 重复3 次 db 0,1,2,0,1,2,0,1,2
db 3 dup('abc','ABC') 定义18 个字节, 构成'abcABCabcABCabcABC' db 'abcABCabcABCabcABC'
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容