彙編裏的數組
一維數組
編譯器爲Visual Studio 2019
一維數組在彙編裏看到其實就是簡化版的聲明n個變量而已,學過java的可以理解爲一個語法糖?
int arr[5] = { 0,1,2,3,4 };
__asm{
mov dword ptr [ebp-3Ch],0
mov dword ptr [ebp-38h],1
mov dword ptr [ebp-34h],2
mov dword ptr [ebp-30h],3
mov dword ptr [ebp-2Ch],4
}
//等價於
int arr_0=0;
int arr_1=1;
int arr_2=2;
int arr_3=3;
int arr_4=4;
尋址方式
#include<stdio.h>
void function() {
int x = 1;//mov dword ptr [ebp-8],1
int y = 2;//mov dword ptr [ebp-14h],2
int r;
int arr[5] = { 0,1,2,3,4 };
r = arr[1];
__asm{
mov eax,4
shl eax,0
mov ecx,dword ptr [ebp+eax-3Ch]
mov dword ptr [ebp-20h],ecx
}
r = arr[x];
__asm{
mov eax,dword ptr [ebp-8]
mov ecx,dword ptr [ebp+eax*4-3Ch]
mov dword ptr [ebp-20h],ecx
}
r = arr[x + y];
__asm{
mov eax,dword ptr [ebp-8]
add eax,dword ptr [ebp-14h]
mov ecx,dword ptr [ebp+eax*4-3Ch]
mov dword ptr [ebp-20h],ecx
}
r = arr[x * 2 + y];
__asm{
mov eax,dword ptr [ebp-8]
mov ecx,dword ptr [ebp-14h]
lea edx,[ecx+eax*2]
mov eax,dword ptr [ebp+edx*4-3Ch]
mov dword ptr [ebp-20h],eax
}
}
int main()
{
function();
return 0;
}
一個很顯著的特徵就是,這個形式可能會繞暈?稍微調換一下位置就很明瞭了,像這樣,是啥?不就是arr[0]的地址嗎?至於爲什麼是乘以4,其實是因爲這是一個int數組,如果換成short就是乘以2,換成char就是乘以1.
內存分配
之所以開頭說明了編譯器是啥,是因爲每個編譯器在申請內存時申請的大小都不盡相同,當然不同的僅僅是大小而已,依然遵守原則的。之所以提到這一點,首先來看一個問題
char arr[3] = {1,2,3};與 char arr[4] = {1,2,3,4};哪個更節省空間,從反彙編的角度來說明你的觀點
說到這個又不得不提一下本機尺寸,對應尺寸大小的數據在處理上會更快,例如32位機器在處理32位的數據時反而會比16位,8位的數據更快。編譯器在內存大小和處理速度之間選擇了處理速度。
接下來依然是一段實例代碼
eg1:有3個char的數組arr1
#include<stdio.h>
void function() {
char arr1[3] = { 0,1,2 };
}
int main()
{
function();
return 0;
}
eg2:有4個char的數組arr2
#include<stdio.h>
void function() {
char arr2[4] = { 0,1,2,3 };
}
int main()
{
function();
return 0;
}
eg3:有5個char的數組arr3
#include<stdio.h>
void function() {
char arr3[5] = { 0,1,2,3,4 };
}
int main()
{
function();
return 0;
}
可以看到eg1中的內存和eg2中的內存一樣,而eg3中明明只是多一個char但是內存卻多了一個DWORD(D0h-CCh=4h),這就是爲了符合本機尺寸使得處理速度更快做出的調整。
那麼問題的答案顯而易見了,從反彙編的角度來看節省排名是arr2>arr1>arr3。
多維數組
內存分配
從彙編的角度來說,不管你是幾維在彙編來看都是一維
int arr1[4] = { 0,1,2,3 };
__asm{
mov dword ptr [ebp-14h],0
mov dword ptr [ebp-10h],1
mov dword ptr [ebp-0Ch],2
mov dword ptr [ebp-8],3
}
int arr2[2][2] = { 4,5,6,7 };
__asm{
mov dword ptr [ebp-2Ch],4
mov dword ptr [ebp-28h],5
mov dword ptr [ebp-24h],6
mov dword ptr [ebp-20h],7
}
尋址方式
尋址方式就跟一維數組不太一樣了
int arr1[4] = { 0,1,2,3 };
int n = arr1[3];
__asm{
mov eax,4
imul ecx,eax,3
mov edx,dword ptr [ebp+ecx-14h]
mov dword ptr [ebp-38h],edx
}
int arr2[2][2] = { 4,5,6,7 };
int m = arr2[1][0];
__asm{
mov eax,8---->2*4
shl eax,0
lea ecx,[ebp+eax-2Ch]
mov edx,4
imul eax,edx,0
mov ecx,dword ptr [ecx+eax]
mov dword ptr [ebp-44h],ecx
}
簡單來說假設聲明一個n維數組
String str="int arr[a_0][a_1]···[a_n]";
String str="我們想要查找arr[m][m]···[m]的元素";
String str="定義一個mul(int num)運算符,表示a_(num)*a_(num+1)···*a_(n)"
那麼尋址公式是這樣的