下文中出现的"idata",指的都是任意常量
一,基于BX、SI、DI等寄存器的寻址形式
在第五篇中曾介绍过DS寄存器的作用,简要复习一下->速通汇编(五)认识段地址与偏移地址,CS、IP寄存器和jmp指令,DS寄存器_arm汇编 前两个地址是什么-CSDN博客
可以如此说:汇编中出现的形如**[偏移地址]** 形式的地址,指的都是**[DS:偏移地址]** ,即DS*16+偏移地址处的内存
为了更灵活的使用这个语法,CPU提供了BX、SI、DI等寄存器来方便我们表达**[偏移地址]**
(一)[bx+idata]
BX原名是"基址寄存器",当需要使用**[偏移地址]** 这个语法时,可以将BX中的数据作为这里的偏移地址,写作**[bx+idata](AX、CX、DX等寄存器是不能这样写的!),它代表的意思很清晰:指的就是DS*16+BX+idata**处的内存
下图演示idata==0
下图演示idata==2
(二)[si/di+idata]
si和di各自都可以单独使用成**[偏移地址]** 这个语法,即**[si+idata]和[di+idata]**
其效果与[bx+idata]是一模一样的
这里简略带过,读者自行验证
(三)[bx+si/di+idata]
[bx+si+idata]和[bx+di+idata]
这个语法让**[偏移地址]**这个语法的表达更加灵活,但本质都是一样的
无非是各种寄存器和一个常数加起来组成一个偏移地址罢了,下面简单做个实验验证语法
修改DS==2000,BX==1000,SI==0003,DI==0006
写入汇编【mov ax,[bx+si] 】【mov cx,[bx+di] 】【mov dx,[bx+si+3]】
先预测结果:ds==2000,bx+si==1000+0003==1003,因此ax的值应该取地址[2000:1003]处的数据,其余两条汇编同理
故ax==5566,cx==2233,dx==2233
执行完后,结果符合预期
注意,以下表示**[偏移地址]** 的语法是错误的!
[bx+si+di+idata] ×si和di各自都能和bx组合,但不可以同时出现
[bx+ax/cx/dx] ×虽然bx和ax/cx/dx都是常用寄存器,但只有bx可以出现在[偏移地址]这个语法中
(四)总结
(1)[idata]用一个常量来表示地址,可用于直接定位一个内存单元
(2)[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元
(3)[bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元
(4)[bx+si/di]用两个变量表示地址
(5)[bx+si/di+idata]用两个变量和一个常量表示地址
二,BP寄存器
说明完BX、SI、DI的各种组合寻址之后,BP寄存器就非常容易解释了
在寻址功能这块,你可以把BP和BX看成亲戚
[bp+idata]≈[bx+idata]
[bp+si/di+idata]≈[bx+si/di+idata]
说是"亲戚"的原因,在于它们寻址的差别在段地址上
BX寄存器基于这种寻址方式时,默认的段地址取的是DS寄存器中的数据,这一点在上面已经验证过
BP寄存器基于这种寻址方式时,默认的段地址取的是SS寄存器中的数据
SS寄存器在上一篇介绍栈时已经阐明,它配合SP寄存器指向的其实是一段被视作"栈"的内存空间,下面进行简单实验验证
①写入并执行以下汇编指令,并查看栈中数据
执行前
执行后,ax,bx,cx的值被压入栈中,按照从高地址(栈底)向低地址(栈顶),这里解释算复习上篇的内容了
②现在先思考一下,如果想要用形如[bp+si/di+idata]的语法取到栈中的数据放入AX中,例如[073F:00F9]处的内容,该如何编写汇编?
答案很多,因为这个表达式很灵活,总之凑出中括号[]中的内容等于[00F9]即可,CPU会将其用作偏移地址,将此时SS(而不是DS)的073F用作段地址
例如bp和di的组合
bp+di+3==00F0+0006+3==00F9
三,寻址方式总结
(注:本图取自《王爽汇编》P165处表8.2,不商用,仅供学习参考。)
下图表格中第4列【常用格式举例】中出现的一些特殊表示形式
如[bx].idata,[bx][idata],[bx].idata[si],都是**[偏移地址]**的特殊形式,其本质都是相加
如[bx].idata==[bx+idata],[bx][idata]==bx+idata,[bx].idata[si]==bx+idata+si