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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C/C++拾遗录--关于一个C语言小程序的分析

發(fā)布時間:2023/12/13 c/c++ 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C/C++拾遗录--关于一个C语言小程序的分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

雖然編了幾年程序,但是對于程序到底是什么規(guī)則變成匯編代碼的,在這里搞了一個小程序。用VC查看了一下匯編代碼。在此之前先介紹一下關于函數(shù)運行是堆棧變化的細節(jié)。

在高級語言編寫程序時,函數(shù)的調(diào)用是很常見的事情,但是在函數(shù)調(diào)用過程中堆棧的變化通常有幾個細節(jié):

1.父函數(shù)將函數(shù)的實參按照從右至左的順序壓入堆棧;

2.CPU將父函數(shù)中函數(shù)調(diào)用指令Call的下一條指令地址EIP壓入堆棧;

3.父函數(shù)通過Push Ebp指令將基址指針EBP的值壓入堆棧,并通過Mov Ebp,Esp指令將當前堆棧指針Esp值傳給Ebp;

4.通過Sub Esp,m(m是字節(jié)數(shù))指令可以為存放函數(shù)中的局部變量開辟內(nèi)存。函數(shù)在執(zhí)行的時候如果需要訪問實參或局部變量,都可以通過EBP指針來指引完成。

windows系統(tǒng)下常用的函數(shù)調(diào)用通常有種,__cdecl和__stdCall。

1.在VC、.net等開發(fā)環(huán)境中,編寫命令行程序時的Main或者_tmain函數(shù),以及大家自己定義的很多函數(shù)都是默認采用__cdecl調(diào)用方式;

2.通過MFC編寫圖形界面程序的時候,其主函數(shù)聲明為extern "C" int WINAPI tWinMain(參數(shù)),該函數(shù)的調(diào)用約定是__stdCall。WINAPI和PASCAL等都是__stdCall的宏定義,是一個意思,此外,大家平時調(diào)用的API函數(shù),絕大多數(shù)都是采用__staCall的調(diào)用方式;

3.__cdecl調(diào)用方式的函數(shù),父函數(shù)在調(diào)用子函數(shù)的時候,先將子函數(shù)的實參按照從右至左的順序壓入堆棧中,子函數(shù)返回后,父函數(shù)通過Sub Esp,n(n=函數(shù)實參個數(shù)*4)指令來恢復堆棧;

4.__stdCall調(diào)用約定函數(shù),子函數(shù)調(diào)用時實參入棧順序也是從左到右,但是堆棧恢復是子函數(shù)返回時自己通過Ret n指令來完成的。

下邊就是針對這些知識進行的部分實踐:

[cpp] view plaincopy
  • #include<stdio.h>??
  • #include<windows.h>??
  • #include<stdlib.h>??
  • int?fun(char?*szIn,?int?nTest)??
  • {??
  • ????char?szBuf[9];??
  • ????printf("%d\n",nTest);??
  • ????strcpy(szBuf,szIn);??
  • ????return?0;??
  • }??
  • int?main(int?argc,?char?*argv[])??
  • {??
  • ????char?sz_In[]?=?"1234567";??
  • ????fun(sz_In,888);??
  • ????return?0;??
  • }??

  • 匯編代碼

    [plain] view plaincopy
  • 00401003???int?????????3??
  • 00401004???int?????????3??
  • @ILT+0(?fun@@YAHPADH@Z):??
  • 00401005???jmp?????????fun?(00401020)????//進入fun函數(shù)??
  • @ILT+5(_main):??
  • 0040100A???jmp?????????main?(00401080)????//進入main函數(shù),該位置是整段代碼的入口??
  • 0040100F???int?????????3??
  • 00401010???int?????????3??
  • 00401011???int?????????3??
  • 00401012???int?????????3??
  • 00401013???int?????????3??
  • 00401014???int?????????3??
  • 00401015???int?????????3??
  • 00401016???int?????????3??
  • 00401017???int?????????3??
  • 00401018???int?????????3??
  • 00401019???int?????????3??
  • 0040101A???int?????????3??
  • 0040101B???int?????????3??
  • 0040101C???int?????????3??
  • 0040101D???int?????????3??
  • 0040101E???int?????????3??
  • 0040101F???int?????????3??
  • ---?c:\project\heap1\heap1.cpp??--------------------------------------------------------------------------------------------------------------------------------------??
  • 1:????#include<stdio.h>??
  • 2:????#include<windows.h>??
  • 3:????#include<stdlib.h>??
  • 4:????int?fun(char?*szIn,?int?nTest)??
  • 5:????{??
  • 00401020???push????????ebp??
  • 00401021???mov?????????ebp,esp???????????????//保存基址指針,并將現(xiàn)在的棧頂保存為基址指針。??
  • 00401023???sub?????????esp,4Ch???????????????//騰出一部分堆棧區(qū)用于存放局部變量。??
  • 00401026???push????????ebx??
  • 00401027???push????????esi??
  • 00401028???push????????edi???????????????????//保存三個寄存器的值。??
  • 00401029???lea?????????edi,[ebp-4Ch]??
  • 0040102C???mov?????????ecx,13h??
  • 00401031???mov?????????eax,0CCCCCCCCh??
  • 00401036???rep?stos????dword?ptr?[edi]???????//將騰出的4Ch的空間初始化值為0xCC。???
  • 6:????????char?szBuf[9];??
  • 7:????????printf("%d\n",nTest);??
  • 00401038???mov?????????eax,dword?ptr?[ebp+0Ch]??
  • 0040103B???push????????eax??
  • 0040103C???push????????offset?string?"%d\n"?(0042201c)????//先后壓入棧中兩個地址,nTest,一個是一個字符串指針。??
  • 00401041???call????????printf?(004011d0)????????????????????????????//調(diào)用printf函數(shù)時,它會自動做到堆棧平衡。??
  • 00401046???add?????????esp,8????????????????????????????????????????//由于剛才壓入和兩個參數(shù),所以在這里手動將兩個參數(shù)彈出堆棧??
  • 8:????????strcpy(szBuf,szIn);??
  • 00401049???mov?????????ecx,dword?ptr?[ebp+8]?????????????????????????
  • 0040104C???push????????ecx???????????????????????????//壓入szIn的指針。這個參數(shù)在高出基址的8位處,也就是調(diào)用該函數(shù)前壓入棧中的。??
  • 0040104D???lea?????????edx,[ebp-0Ch]??
  • 00401050???push????????edx?????????????????//壓入szBuf的指針,這個函數(shù)在低于基址的OCh位處,這是調(diào)用函數(shù)后分配的。局部變量的分配大??
  • 00401051???call????????strcpy?(004010e0)???//小都是按4的倍數(shù)分配的,所以盡管szBuf[9]但是也分配在了0Ch處。??
  • 00401056???add?????????esp,8??
  • 9:????????return?0;??
  • 00401059???xor?????????eax,eax?????????????//返回值在EAX中。??
  • 10:???}??
  • 0040105B???pop?????????edi??
  • 0040105C???pop?????????esi??
  • 0040105D???pop?????????ebx?????????????????//彈出保存的數(shù)據(jù)。??
  • 0040105E???add?????????esp,4Ch?????????????//消除為局部變量騰出的空間。??
  • 00401061???cmp?????????ebp,esp??
  • 00401063???call????????__chkesp?(00401250)?//檢驗是否在用戶自定義匯編代碼中修改了ebp和esp的相對關系。一般情況下EBP>ESP??
  • 00401068???mov?????????esp,ebp?????????????//將原基址恢復給棧頂寄存器。??
  • 0040106A???pop?????????ebp?????????????????//彈出原調(diào)用函數(shù)的堆棧基址。??????????????
  • 0040106B???ret?????????????????????????????//函數(shù)返回。???
  • ---?No?source?file??--------------------------------------------------------------------------------------------------------------------------------------------------??
  • 0040106C???int?????????3??
  • 0040106D???int?????????3??
  • 0040106E???int?????????3??
  • 0040106F???int?????????3??
  • 00401070???int?????????3??
  • 00401071???int?????????3??
  • 00401072???int?????????3??
  • 00401073???int?????????3??
  • 00401074???int?????????3??
  • 00401075???int?????????3??
  • 00401076???int?????????3??
  • 00401077???int?????????3??
  • 00401078???int?????????3??
  • 00401079???int?????????3??
  • 0040107A???int?????????3??
  • 0040107B???int?????????3??
  • 0040107C???int?????????3??
  • 0040107D???int?????????3??
  • 0040107E???int?????????3??
  • 0040107F???int?????????3??
  • ---?c:\project\heap1\heap1.cpp??--------------------------------------------------------------------------------------------------------------------------------------??
  • 11:???int?main(int?argc,?char?*argv[])??
  • 12:???{??
  • 00401080???push????????ebp??
  • 00401081???mov?????????ebp,esp???????????????????????//保存堆棧基址??
  • 00401083???sub?????????esp,48h???????????????????????//騰出局部變量空間????
  • 00401086???push????????ebx??
  • 00401087???push????????esi??
  • 00401088???push????????edi???????????????????????????//保存3個寄存器????
  • 00401089???lea?????????edi,[ebp-48h]??
  • 0040108C???mov?????????ecx,12h??
  • 00401091???mov?????????eax,0CCCCCCCCh????????????????//初始化局部變量空間??
  • 00401096???rep?stos????dword?ptr?[edi]??
  • 13:???????char?sz_In[]?=?"1234567";??
  • 00401098???mov?????????eax,[string?"1234567"?(00422020)]??
  • 0040109D???mov?????????dword?ptr?[ebp-8],eax??
  • 004010A0???mov?????????ecx,dword?ptr?[string?"1234567"+4?(00422024)]??
  • 004010A6???mov?????????dword?ptr?[ebp-4],ecx?????????//將字符串通過寄存器將字符拷貝到分配的空間中。??
  • 14:???????fun(sz_In,888);??
  • 004010A9???push????????378h???????????????????????????
  • 004010AE???lea?????????edx,[ebp-8]??
  • 004010B1???push????????edx??????//從右至左將參數(shù)壓入堆棧中,數(shù)字直接壓入數(shù)值,字符串則壓入字符串指針??
  • 004010B2???call????????@ILT+0(fun)?(00401005)??
  • 004010B7???add?????????esp,8????????????????????????//恢復堆棧??
  • 15:???????return?0;??
  • 004010BA???xor?????????eax,eax??????????????????????//返回值在EAX中??
  • 16:???}??
  • 004010BC???pop?????????edi??
  • 004010BD???pop?????????esi??
  • 004010BE???pop?????????ebx??????????????????????????//恢復3個寄存器??
  • 004010BF???add?????????esp,48h??????????????????????//清除局部變量空間??
  • 004010C2???cmp?????????ebp,esp??
  • 004010C4???call????????__chkesp?(00401250)??????????//檢測堆棧指針與堆棧基址?????
  • 004010C9???mov?????????esp,ebp??????????????????????//恢復調(diào)用函數(shù)的棧頂??
  • 004010CB???pop?????????ebp??????????????????????????//恢復調(diào)用函數(shù)的堆棧基址??
  • 004010CC???ret??????????????????????????????????????//函數(shù)返回??
  • ---?No?source?file??--------------------------------------------------------------------------------------------------------------------------------------------------??
  • 004010CD???int?????????3??
  • 004010CE???int?????????3??

  • 關于這個程序的堆棧使用情況也做了一下分析,如圖:

    ?

    總結

    以上是生活随笔為你收集整理的C/C++拾遗录--关于一个C语言小程序的分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。