最近看了下王爽著的<<汇编语言(第三版)>>,里面总结了8086 CPU编程的寻址方式。
(1)[idata]用医保常量来表示地址,可用于直接定位一个内存单元;
(2)[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元;
(3)[bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元;
(4)[bx+si]用两个变量表示地址;
(5)[bx+si+idata]用两个变量和一个常量表示地址;
8086CPU中只有bx,bp,si,di这4个寄存器可以寻址。以上1-5点的寻址方式,在汇编程序中可以方便快捷的访问到一维数组,二维数组,结构体数组等。
事实上,32位和64位汇编的寻址方式和寄存器使用更加灵活。但是大体思路和用法和8086汇编仍然是一致的。
比如如下C++代码片段:
int array1[10] = {1,2,3,4,5,6,7,8,9,10};
int array2[3][3] = {{8,8,8},{8,8,8},{8,8,8}};
int array3[4][4][4] = {9};
long array4[8] = {123,0,8};
int count = 0;
while(1)
{
test_fun1(array1[count],array2[1][count],array3[1][count][2]);
test_fun1(array4[0],array4[1],array4[2]);
count++;
if(count>3)
{
break;
}
}
Debug模式下的汇编代码片段如下:
test_fun1(array1[count],array2[1][count],array3[1][count][2]);
01303AB4 mov eax,dword ptr [count]
01303ABA shl eax,4
01303ABD mov ecx,dword ptr [ebp+eax-118h]
01303AC4 push ecx
01303AC5 mov edx,dword ptr [count]
01303ACB mov eax,dword ptr [ebp+edx*4-4Ch]
01303ACF push eax
01303AD0 mov ecx,dword ptr [count]
01303AD6 mov edx,dword ptr array1[ecx*4]
01303ADA push edx
01303ADB call test_fun1 (13011FEh)
01303AE0 add esp,0Ch
test_fun1(array4[0],array4[1],array4[2]);
01303AE3 mov eax,dword ptr [ebp-180h]
01303AE9 push eax
01303AEA mov ecx,dword ptr [ebp-184h]
01303AF0 push ecx
01303AF1 mov edx,dword ptr [array4]
01303AF7 push edx
01303AF8 call test_fun1 (13011FEh)
如上,很明显可以看到多种寻址方式。而8086中的bx寄存器,在这里更多的是使用了ebp基址寄存器(函数栈帧)。01303ABD mov ecx,dword ptr [ebp+eax-118h] 这里idata为-118h,为118h,是因为array3是局部变量,他们都是存放在函数栈帧上,跟ebp有关联。
对应8086的si,这里使用的可以是eax或者edx等。寄存器使用的不一样,寻址方式的本质其实是一样的。