彙編裏的數組

彙編裏的數組

一維數組

編譯器爲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;
}

一個很顯著的特徵就是[ebp+edx43Ch][ebp+edx*4-3Ch],這個形式可能會繞暈?稍微調換一下位置就很明瞭了,像這樣[ebp3Ch+edx4][ebp-3Ch+edx*4],[ebp3Ch][ebp-3Ch]是啥?不就是arr[0]的地址嗎?至於爲什麼是乘以4,其實是因爲這是一個int數組,如果換成short就是乘以2[ebp3Ch+edx2][ebp-3Ch+edx*2],換成char就是乘以1[ebp3Ch+edx][ebp-3Ch+edx].

內存分配

之所以開頭說明了編譯器是啥,是因爲每個編譯器在申請內存時申請的大小都不盡相同,當然不同的僅僅是大小而已,依然遵守原則的。之所以提到這一點,首先來看一個問題

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;
}
11.png

可以看到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維數組arr[a0][a1][an]arr[a_0][a_1]···[a_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)"

那麼尋址公式是這樣的x=0nmmul(x)\sum_{x=0}^{n}{m*mul(x)}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章