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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

裸函数及调用约定

發布時間:2025/4/16 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 裸函数及调用约定 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

裸函數

  在函數名前面加上? __deplspec(naked),此時,編譯器對該函數不會進行任何處理。

  想要在c語言里面寫匯編的語法,使用vc中輸入__asm

  對于一個裸函數而言,就是編譯器不會為這個函數生成代碼,想用匯編怎么寫就怎么寫,如果什么都不寫,一定會報錯,因為沒有生成ret。

  

1 #include<stdio.h> 2 void __deplspec(naked) Function() 3 { 4 __asm 5 { 6 //保留棧底 7 push ebp ;此時 esp=esp+4 8 //提升棧底 9 mov ebp,esp ;此時 ebp=esp 10 sub esp,0x40 ;此處0x40即為緩沖區大小,可寫任意數值 11 12 //保存現場 13 push ebx 14 push edi 15 push esi 16 17 //往緩沖區中寫入數據 18 mov eax,0xCCCCCCCC 19 ;0xCCCC在gb2312中是燙字,寫C語言的時候出現燙燙燙就是這個原因,屯屯屯是0xCDCD,是堆的問題 20 mov ecx,0x10 ;此處的0x10是0x40除以4得到的 21 lea edi,dword ptr ds:[ebp-0x40] 22 rep stosd 23 24 //實現函數功能的地方 25 26 //恢復現場 27 pop esi 28 pop edi 29 pop ebx 30 //降低棧底 31 mov esp,ebp ;降低esp 32 pop ebp ;降低ebp 33 ret 34 } 35 36 } 37 38 void main() 39 { 40 Function(); 41 }

在上面的例子中,我沒有傳入參數,假如傳遞參數,一般是在函數調用前push入堆棧,具體再后面會提到。

實現兩個數之和的代碼:

1 #include<stdio.h> 2 void __deplspec(naked) Add(int x,int y) 3 { 4 __asm 5 { 6 //保留棧底 7 push ebp ;此時 esp=esp+4 8 //提升棧底 9 mov ebp,esp ;此時 ebp=esp 10 sub esp,0x40 ;此處0x40即為緩沖區大小,可寫任意數值 11 12 //保存現場 13 push ebx 14 push edi 15 push esi 16 17 //往緩沖區中寫入數據 18 mov eax,0xCCCCCCCC 19 ;0xCCCC在gb2312中是燙字,寫C語言的時候出現燙燙燙就是這個原因,屯屯屯是0xCDCD,是堆的問題 20 mov ecx,0x10 ;此處的0x10是0x40除以4得到的 21 lea edi,dword ptr ds:[ebp-0x40] 22 rep stosd 23 //實現兩個數之和的功能 24 mov eax,dword ptr ds:[ebp+0x8] 25 add eax,dword ptr ds:[ebp+0xC] 26 27 28 //恢復現場 29 pop esi 30 pop edi 31 pop ebx 32 //降低棧底 33 mov esp,ebp ;降低esp 34 pop ebp ;降低ebp 35 ret 8 36 } 37 38 } 39 40 void main() 41 { 42 add(2,3); 43 }

假如存在局部變量,局部變量的存儲地方是在緩沖區中。例如,

實現參數求和之后在加上一個常數z的代碼:

1 #include<stdio.h> 2 void __deplspec(naked) Add(int x,int y) 3 { 4 __asm 5 { 6 //保留棧底 7 push ebp ;此時 esp=esp+4 8 //提升棧底 9 mov ebp,esp ;此時 ebp=esp 10 sub esp,0x40 ;此處0x40即為緩沖區大小,可寫任意數值 11 12 //保存現場 13 push ebx 14 push edi 15 push esi 16 17 //往緩沖區中寫入數據 18 mov eax,0xCCCCCCCC 19 ;0xCCCC在gb2312中是燙字,寫C語言的時候出現燙燙燙就是這個原因,屯屯屯是0xCDCD,是堆的問題 20 mov ecx,0x10 ;此處的0x10是0x40除以4得到的 21 lea edi,dword ptr ds:[ebp-0x40] 22 rep stosd 23 24 //實現的功能 25 mov dword ptr ds:[ebp-0x4],1 ;ebp-0x4處存放局部變量z,z=1 26 27 mov eax,dword ptr ds:[ebp+0x8] 28 add eax,dword ptr ds:[ebp+0xC] 29 add eax,dword ptr ds:[ebp+0x10] 30 ;參數之和部分 31 32 add eax,dword ptr ds:[ebp-0x4] ;局部變量求和的部分 33 34 //恢復現場 35 pop esi 36 pop edi 37 pop ebx 38 //降低棧底 39 mov esp,ebp ;降低esp 40 pop ebp ;降低ebp 41 ret 0xC 42 } 43 44 } 45 46 void main() 47 { 48 add(2,3,4); 49 }

根據代碼可以得到,局部變量存放在ebp-0x4開始往低地址,參數是存放在ebp+0x8開始

?

?

調用約定

外平棧是指在函數外面平衡堆棧

內平棧是指在函數內部平衡堆棧

例如上面的例子中最后ret 0xC,就是內平棧,因為是在函數內部

外平棧一般是這樣

call myfunction add esp,xxxxx ;且ret后面無數字call myfunction call function_pinghengduizhan

?

轉載于:https://www.cnblogs.com/zimudao/p/8321496.html

總結

以上是生活随笔為你收集整理的裸函数及调用约定的全部內容,希望文章能夠幫你解決所遇到的問題。

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