【asm基础】寻址

寻址

寻址根据操作数的不同可以分为三个大类:

1. 立即数寻址,如mov ecx, 0h; 这里的0h就是一个立即数;

2. 寄存器寻址,如mov eax, ebx; 这里的eax、ebx,包括前面的ecx都是寄存器寻址;

3. 存储器寻址,如mov eax, [src]; 这里的src(见之后的例子)是一个内存操作数,它表示的必须是一个有效的内存地址。

另外,根据寻址方式的不同,还可以分为直接寻址间接寻址两个大类。

直接寻址

首先看一个例子:

得到的结果如下:

mov操作中的src,src+4实际上就是一个地址,通过src可以得到该地址位置的值。

需要注意几点:

1. 对于MASM来说,这里的[]可加可不加,结果都是得到地址内的值;

2. 对于MASM来说并没有做有效地址的判断,因此存在越界的可能:

上例中就踩到了dest的数据区域了。

由于src实际上就是一个地址,所以可以得到它的具体的地址值:

使用lea和OFFSET得到的结果是一样的,区别在于lea是运行时得到的,而OFFSET是编译时决定的。也就是说实际上src的值在编译时就决定了。如果同时运行两个程序,得到的地址会不会是一样的呢?

开启两个不同的程序,得到的结果是一样的:

第一个程序结果:

第二个程序结果:

为什么两个程序会用到同一个地址?

由于每次启动程序,得到的src的地址都是固定的011A5880h,因此可以确定的是一定是编译器决定了src的值(两次编译得到的值都不同)。而为什么两个不同的程序都使用了相同的地址,这个应该是因为在保护模式下,每个程序都有一个独立的4G的寻址空间。另外还需要了解的是这里的src实际上重定位后的地址,不过这个以后讲,先不关注。

回到直接寻址来,因为实际上src的地址值就是011A5880h,那是否可以直接在mov指令中使用这个地址来寻址呢?

从得到的结果可以看到,至少在MASM,这种类型的直接寻址是不能使用的

这种mov ebx, 011A5880h; 可以说是真正的直接寻址。而mov eax, [src]; 这种有另外一个名字叫基址寻址。两种类型可以认为类似,但是在MASM里面不能使用直接地址的寻址。

间接寻址

使用寄存器作为指针并操纵寄存器的值来寻址,就是间接寻址。

首先需要了解汇编中的指针,包含其它变量地址的变量,就是指针变量,简称指针。

上例中的ptr1和ptr2就是指针。可以看到指针和变量并没有本质的区别。

如果将指针复制给寄存器,并用寄存器来访问指针所指向的变量的值,就是间接寻址了:

ptr1实际上就是src的地址,因此也可以直接使用OFFSET来实现间接寻址:

注意这里的[]就不能省略了,如果省略:

所以这里的[eax]表示eax表示的地址中的值。在MASM中,对于寄存器,[xxx]和xxx是不一样的,而对于普通的地址(比如src),效果是相同的。对于[eax],eax是一个间接操作数。

间接操作数可以作为源操作数,也可以作为目的操作数:

红框中的[edi]表示的间接寻址将dest中的FFh替换成了00h,得到的结果也符合预期:

注意红框中的DWORD PTR不可少,如果不加会报错:

因为[edi]只是表示了一个地址,通过它不能确定移动数据的大小;而00h是一个立即数,也没有一个确定的大小(00h可以表示成一个BYTE,也可以表示成一个WORD 0000h,等等),因此需要DWORD PTR确定了数据移动的大小。

另外,对指针还有一个需要补充的东西,在C语言中,对于指针p的p++操作有不同的解释,如果p是int指针,则是加4(假设int是4字节的);对于char指针,则是加1(假设char是1字节的),那么汇编中的指针是否也相同呢?

通过inc ptr1,ptr1的值只增加1,此时指向的值EBX并不是期望的01h。实际上这个例子是有问题的,汇编中的inc和C语言中的p++并不是对应的。inc就是简单的加1,而p++中的++实际上转化成汇编后会根据p指向的类型而加不同的值。

这一点可以通过反汇编来证明:

反汇编的结果中有:

如果将i的类型改成char,结果如下:

间接寻址的地址表示方式可以有多种,下面这一种和C语言中的数组很类似:

PS:文中代码使用VS2012进行编译,文中使用的部分代码,如DumpRegs来自《Intel汇编语言程序设计》,具体使用方法可参见【asm基础】vs下使用汇编

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值