日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C和汇编---数组

發布時間:2023/12/1 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C和汇编---数组 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

0x01 初始化數組

1、沒有初始化數組

#include "stdio.h" int main(void) {int data[4];for (int i=0;i<4;i++){printf("%d\t",data[i]);}return 0; }

不同系統,輸出結果可能不一樣:

反匯編:

4: int data[4]; 5: for (int i=0;i<4;i++) 00401028 C7 45 EC 00 00 00 00 mov dword ptr [ebp-14h],0 0040102F EB 09 jmp main+2Ah (0040103a) 00401031 8B 45 EC mov eax,dword ptr [ebp-14h] 00401034 83 C0 01 add eax,1 00401037 89 45 EC mov dword ptr [ebp-14h],eax 0040103A 83 7D EC 04 cmp dword ptr [ebp-14h],4 0040103E 7D 17 jge main+47h (00401057) 6: { 7: printf("%d\t",data[i]); 00401040 8B 4D EC mov ecx,dword ptr [ebp-14h] 00401043 8B 54 8D F0 mov edx,dword ptr [ebp+ecx*4-10h] 00401047 52 push edx 00401048 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040104D E8 3E 00 00 00 call printf (00401090) 00401052 83 C4 08 add esp,8 8: } 00401055 EB DA jmp main+21h (00401031) 9: 10: return 0; 00401057 33 C0 xor eax,eax 11: }

我們可以看到int data[4];沒有生成機器碼,說明cpu到這里不會干任何事情。從上面的輸出結果可以得出,定義一個數組,會給這個數組分配內存空間如果沒有初始化,數組的內容是相應分配空間的內容,這里我們稱之為垃圾值

  • jge:大于等于轉移

2、部分初始化

#include "stdio.h" int main(void) {int data[4]={1,2};for (int i=0;i<4;i++){printf("%d\t",data[i]);}return 0; }

結果:

反匯編:

4: int data[4]={1,2}; 00401028 C7 45 F0 01 00 00 00 mov dword ptr [ebp-10h],1 0040102F C7 45 F4 02 00 00 00 mov dword ptr [ebp-0Ch],2 00401036 33 C0 xor eax,eax 00401038 89 45 F8 mov dword ptr [ebp-8],eax 0040103B 89 45 FC mov dword ptr [ebp-4],eax 5: for (int i=0;i<4;i++) 0040103E C7 45 EC 00 00 00 00 mov dword ptr [ebp-14h],0 00401045 EB 09 jmp main+40h (00401050) 00401047 8B 4D EC mov ecx,dword ptr [ebp-14h] 0040104A 83 C1 01 add ecx,1 0040104D 89 4D EC mov dword ptr [ebp-14h],ecx 00401050 83 7D EC 04 cmp dword ptr [ebp-14h],4 00401054 7D 17 jge main+5Dh (0040106d) 6: { 7: printf("%d\t",data[i]); 00401056 8B 55 EC mov edx,dword ptr [ebp-14h] 00401059 8B 44 95 F0 mov eax,dword ptr [ebp+edx*4-10h] 0040105D 50 push eax 0040105E 68 1C 20 42 00 push offset string "%d\t" (0042201c) 00401063 E8 28 00 00 00 call printf (00401090) 00401068 83 C4 08 add esp,8 8: } 0040106B EB DA jmp main+37h (00401047) 9: 10: return 0; 0040106D 33 C0 xor eax,eax 11: }

從下面這段代碼可以看出,部分初始化,編譯器會給數組分配連續的空間,將有值的部分賦值到相應的內存,沒有初始化的,復制為0,這就是為什么上面的輸出結果為什么后面沒有賦值的是0

4: int data[4]={1,2}; 00401028 C7 45 F0 01 00 00 00 mov dword ptr [ebp-10h],1 0040102F C7 45 F4 02 00 00 00 mov dword ptr [ebp-0Ch],2 00401036 33 C0 xor eax,eax 00401038 89 45 F8 mov dword ptr [ebp-8],eax 0040103B 89 45 FC mov dword ptr [ebp-4],eax

3、全部初始化數組

#include "stdio.h" int main(void) {int data[4]={1,2,3,4};for (int i=0;i<4;i++){printf("%d\t",data[i]);}return 0; }

4: int data[4]={1,2,3,4}; 00401028 C7 45 F0 01 00 00 00 mov dword ptr [ebp-10h],1 0040102F C7 45 F4 02 00 00 00 mov dword ptr [ebp-0Ch],2 00401036 C7 45 F8 03 00 00 00 mov dword ptr [ebp-8],3 0040103D C7 45 FC 04 00 00 00 mov dword ptr [ebp-4],4 5: for (int i=0;i<4;i++) 00401044 C7 45 EC 00 00 00 00 mov dword ptr [ebp-14h],0 0040104B EB 09 jmp main+46h (00401056) 0040104D 8B 45 EC mov eax,dword ptr [ebp-14h] 00401050 83 C0 01 add eax,1 00401053 89 45 EC mov dword ptr [ebp-14h],eax 00401056 83 7D EC 04 cmp dword ptr [ebp-14h],4 0040105A 7D 17 jge main+63h (00401073) 6: { 7: printf("%d\t",data[i]); 0040105C 8B 4D EC mov ecx,dword ptr [ebp-14h] 0040105F 8B 54 8D F0 mov edx,dword ptr [ebp+ecx*4-10h] 00401063 52 push edx 00401064 68 1C 20 42 00 push offset string "%d\t" (0042201c) 00401069 E8 22 00 00 00 call printf (00401090) 0040106E 83 C4 08 add esp,8 8: } 00401071 EB DA jmp main+3Dh (0040104d) 9: 10: return 0; 00401073 33 C0 xor eax,eax

可以看出如果一開始全部初始化數組,會立即分配連續空間給數組,每個空間賦值為數組相應位置的值
4、總結
不初始化數組,數組元素存儲的是垃圾值;部分初始化數組,剩余的被初始化為0;全部初始化,將值賦值到相應內存空間,而且數組的物理地址連續

0x02多維數組是如何分配空間的

多維數組的初始化情況和一維數組一樣,那么多維數組是如何分配空間的呢?我們以二維數組為列:

#include "stdio.h" int main(void) {int data[2][2]={{1,2},{3,4}};return 0; }

反匯編:

4: int data[2][2]={{1,2},{3,4}}; 00401028 C7 45 F0 01 00 00 00 mov dword ptr [ebp-10h],1 0040102F C7 45 F4 02 00 00 00 mov dword ptr [ebp-0Ch],2 00401036 C7 45 F8 03 00 00 00 mov dword ptr [ebp-8],3 0040103D C7 45 FC 04 00 00 00 mov dword ptr [ebp-4],4 5: 6: return 0; 00401044 33 C0 xor eax,eax 7: }

我們可以看出先將1,2存到連續空間。再將3,4存到接下來的空間(數組的內存空間是連續的),所以這就是為什么上課時老師說把二維數組當成一維數組來理解了,data[0]和data[1]分別為一個一維數組,二維數組按照從左到右,從上到下存儲,地址連續

  • int data[2][2]:data是一個兩個元素的數組,每個元素內含2個int類型元素的數組
  • data的首地址是data[0],data[0]是一個內含2個int類型值的數組,所以data[1]也是這樣

0x03 指針和數組

1、一維數組
我們知道數組名是數組的首地址,可為什么呢?接下來我們分析

#include "stdio.h" int main(void) {int data[4]={1,3,7,4};int *p;p=data;printf("%d\n",p[0]);printf("%d\n",*p+2);printf("%d\n",*(p+2));return 0; }

結果:

反匯編:

4: int data[4]={1,3,7,4}; 0040D738 C7 45 F0 01 00 00 00 mov dword ptr [ebp-10h],1 0040D73F C7 45 F4 03 00 00 00 mov dword ptr [ebp-0Ch],3 0040D746 C7 45 F8 07 00 00 00 mov dword ptr [ebp-8],7 0040D74D C7 45 FC 04 00 00 00 mov dword ptr [ebp-4],4 5: int *p; 6: p=data; 0040D754 8D 45 F0 lea eax,[ebp-10h] 0040D757 89 45 EC mov dword ptr [ebp-14h],eax 7: printf("%d\n",p[0]); 0040D75A 8B 4D EC mov ecx,dword ptr [ebp-14h] 0040D75D 8B 11 mov edx,dword ptr [ecx] 0040D75F 52 push edx 0040D760 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D765 E8 26 39 FF FF call printf (00401090) 0040D76A 83 C4 08 add esp,8 8: printf("%d\n",*p+2); 0040D76D 8B 45 EC mov eax,dword ptr [ebp-14h] 0040D770 8B 08 mov ecx,dword ptr [eax] 0040D772 83 C1 02 add ecx,2 0040D775 51 push ecx 0040D776 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D77B E8 10 39 FF FF call printf (00401090) 0040D780 83 C4 08 add esp,8 9: printf("%d\n",*(p+2)); 0040D783 8B 55 EC mov edx,dword ptr [ebp-14h] 0040D786 8B 42 08 mov eax,dword ptr [edx+8] 0040D789 50 push eax 0040D78A 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D78F E8 FC 38 FF FF call printf (00401090) 0040D794 83 C4 08 add esp,8 10: return 0; 0040D797 33 C0 xor eax,eax

從數組初始化我們看不出來data是數組的首地址嗎,但可以從p=data看出

6: p=data; 0040D754 8D 45 F0 lea eax,[ebp-10h] 0040D757 89 45 EC mov dword ptr [ebp-14h],eax

把 [ebp-10h]偏移地址給eax,eax再賦值給dword ptr [ebp-14h],ebp-10h是第一個元素1的地址,所以data是數組首地址,我們將data值賦值給p,此時p和data可以看成等同的,p[0]就是data[0]。

  • 指針加1是增加一個存儲單元,比如說*(p+2),p+2就是增加兩個存儲單元(int是4byte),所以輸出*(p+2)是7
  • 輸出p+2,此時p是1,加2是3所以會輸出3

2、多維數組
以二維數組為例

#include "stdio.h" int main(void) {int data[3][3]={{1,2,3},{4,5,6},{7,8,9}};int (* p)[3]; //指向一個含有3個int類型的數組p=data;printf("%d\n",p);printf("%d\n",*p);printf("%d\n",*(p+1));printf("%d\n",**p);printf("%d\n",p[0]);printf("%d\n",*p[0]);return 0; }


反匯編:

4: int data[3][3]={{1,2,3},{4,5,6},{7,8,9}}; 0040D738 C7 45 DC 01 00 00 00 mov dword ptr [ebp-24h],1 0040D73F C7 45 E0 02 00 00 00 mov dword ptr [ebp-20h],2 0040D746 C7 45 E4 03 00 00 00 mov dword ptr [ebp-1Ch],3 0040D74D C7 45 E8 04 00 00 00 mov dword ptr [ebp-18h],4 0040D754 C7 45 EC 05 00 00 00 mov dword ptr [ebp-14h],5 0040D75B C7 45 F0 06 00 00 00 mov dword ptr [ebp-10h],6 0040D762 C7 45 F4 07 00 00 00 mov dword ptr [ebp-0Ch],7 0040D769 C7 45 F8 08 00 00 00 mov dword ptr [ebp-8],8 0040D770 C7 45 FC 09 00 00 00 mov dword ptr [ebp-4],9 5: int (* p)[3]; 6: p=data; 0040D777 8D 45 DC lea eax,[ebp-24h] 0040D77A 89 45 D8 mov dword ptr [ebp-28h],eax 7: printf("%d\n",p); 0040D77D 8B 4D D8 mov ecx,dword ptr [ebp-28h] 0040D780 51 push ecx 0040D781 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D786 E8 05 39 FF FF call printf (00401090) 0040D78B 83 C4 08 add esp,8 8: printf("%d\n",*p); 0040D78E 8B 55 D8 mov edx,dword ptr [ebp-28h] 0040D791 52 push edx 0040D792 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D797 E8 F4 38 FF FF call printf (00401090) 0040D79C 83 C4 08 add esp,8 9: printf("%d\n",*(p+1)); 0040D79F 8B 45 D8 mov eax,dword ptr [ebp-28h] 0040D7A2 83 C0 0C add eax,0Ch 0040D7A5 50 push eax 0040D7A6 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D7AB E8 E0 38 FF FF call printf (00401090) 0040D7B0 83 C4 08 add esp,8 10: printf("%d\n",**p); 0040D7B3 8B 4D D8 mov ecx,dword ptr [ebp-28h] 0040D7B6 8B 11 mov edx,dword ptr [ecx] 0040D7B8 52 push edx 0040D7B9 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D7BE E8 CD 38 FF FF call printf (00401090) 0040D7C3 83 C4 08 add esp,8 11: printf("%d\n",p[0]); 0040D7C6 8B 45 D8 mov eax,dword ptr [ebp-28h] 0040D7C9 50 push eax 0040D7CA 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D7CF E8 BC 38 FF FF call printf (00401090) 0040D7D4 83 C4 08 add esp,8 12: printf("%d\n",*p[0]); 0040D7D7 8B 4D D8 mov ecx,dword ptr [ebp-28h] 0040D7DA 8B 11 mov edx,dword ptr [ecx] 0040D7DC 52 push edx 0040D7DD 68 1C 20 42 00 push offset string "%d\t" (0042201c) 0040D7E2 E8 A9 38 FF FF call printf (00401090) 0040D7E7 83 C4 08 add esp,8 13: return 0; 0040D7EA 33 C0 xor eax,eax
  • 從p=data;, printf("%d\n",p[0]);,printf("%d\n",**p);的反匯編看出,數組名和數組名[0]是首元素的地址,printf("%d\n",*p);,數組名像是指向數組名[0]的指針,這就是為什么二維數組的元素可以看成一維數組
  • printf("%d\n",*(p+1));從反匯編里看出,加了0ch,就是加12,并不是加4,二維數組的元素是一維數組,一維數組占3個int類型,所以12,所以*(p+1)指向data[1]
  • 函數里使用二維數組:比如說int sum(int data[][3]),第一個[]表明data是一個指針

總結

以上是生活随笔為你收集整理的C和汇编---数组的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。