java函数调用约定_2020-09-04:函数调用约定了解么?
福哥答案2020-09-04:
初級回答:
stdcall和cdecl兩者的參數傳遞順序都是從右向左。
不同點是stdcall在被調用函數 (Callee) 返回前,由被調用函數 (Callee) 調整堆棧。cdecl在被調用函數 (Callee) 返回后,由調用方 (Caller) 調整堆棧,每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用_stdcall函數的大。
中級回答:
1.__stdcall
在被調用函數 (Callee) 返回前,由被調用函數 (Callee) 調整堆棧
參數從右向左壓入堆棧。
函數名自動加前導的下劃線,后面緊跟一個@符號 ,其后緊跟著參數的尺寸。
2.__cdecl
在被調用函數 (Callee) 返回后,由調用方 (Caller) 調整堆棧。
函數實參在線程棧上按照從右至左的順序依次壓棧。
函數結果保存在寄存器EAX/AX/AL中
浮點型結果存放在寄存器ST0中
編譯后的函數名前綴以一個下劃線字符
調用者負責從線程棧中彈出實參(即清棧)
8比特或者16比特長的整形實參提升為32比特長。
受到函數調用影響的寄存器(volatile registers):EAX, ECX, EDX, ST0 - ST7, ES, GS
不受函數調用影響的寄存器: EBX, EBP, ESP, EDI, ESI, CS, DS
RET指令從函數被調用者返回到調用者(實質上是讀取寄存器EBP所指的線程棧之處保存的函數返回地址并加載到IP寄存器)
3.__fastcall
__fastcall調用的主要特點就是快,因為它是通過寄存器來傳送參數的。
實際上__fastcall用ECX和EDX傳送前兩個DWORD或更小的參數,剩下的參數仍自右向左壓棧傳送,被調用的函數在返回前清理傳送參數的內存棧。
__fastcall調用約定在輸出函數名前加上一個“@”符號,后面也是一個“@”符號和其參數的字節數,格式為@function @number ,如double multi(double a, double b)的修飾名是@multi@16。
__fastcall和__stdcall很象,唯一差別就是頭兩個參數通過寄存器傳送。注意通過寄存器傳送的兩個參數是從左向右的,即第1個參數進ECX,第2個進EDX,其他參數是從右向左的入棧,返回仍然通過EAX。
fastcall調用約定和stdcall類似,它意味著:
函數的第一個和第二個DWORD參數(或者尺寸更小的)通過ecx和edx傳遞,其他參數通過從右向左的順序壓棧;
被調用函數清理堆棧;
函數名修改規則同stdcall。
Fast Calling Convention,快速調用約定。通過使用寄存器解決效率問題。特點:
函數參數部分通過寄存器傳遞,函數中最左的兩個DWORD(寄存器大小是雙字)或者更小的參數,通過寄存器傳遞。剩下的從右到左堆棧傳遞。 函數名改編:“@函數名@函數參數字節大小十進制”。 返回方式同__stdcall。
4.__thiscall
thiscall是唯一一個不能明確指明的函數修飾,因為thiscall不是關鍵字。它是C++類成員函數缺省的調用約定。由于成員函數調用還有一個this指針,因此必須特殊處理,thiscall意味著:
參數從右向左入棧;
如果參數個數確定,this指針通過ecx傳遞給被調用者;如果參數個數不確定,this指針在所有參數壓棧后被壓入堆棧;
對參數個數不定的,調用者清理堆棧,否則函數自己清理堆棧。
主要用于解決this指針問題,使用寄存器傳遞this指針。返回方式同__stdcall.
5.__nakedcall
這是一個很少見的調用約定,一般程序設計者建議不要使用。編譯器不會給這種函數增加初始化和清理代碼,更特殊的是,不能用return返回返回值,只能用插入匯編返回結果。
6.__pascal
基于Pascal語言的調用約定,參數從左至右入棧(與cdecl相反)。被調用者負責在返回前清理堆棧。 此調用約定常見在如下16-bit 平臺的編譯器:OS/2 1.x,微軟Windows 3.x,以及Borland Delphi版本1.x。
7.__vectorcall
目的是用來優化浮點向量運算,intel處理器種有很多浮點向量寄存器,傳統的調用約定(stdcall cdecl fastcall thiscall) 都是通過通用寄存器(ecx edx /rcx rdx r8 r9)以及堆棧進行參數傳遞,所以調用的時候,浮點參數需要從棧獲取。
要求盡可能在寄存器中傳遞參數。函數名改編為”@@函數名@參數字節數十進制”。這是微軟自己添加的標準。
8.syscall
與cdecl類似,參數被從右到左推入堆棧中。EAX, ECX和EDX不會保留值。參數列表的大小被放置在AL寄存器中(?)。 syscall是32位OS/2 API的標準。
9.optlink
參數也是從右到左被推入堆棧。從最左邊開始的三個字符變元會被放置在EAX, EDX和ECX中,最多四個浮點變元會被傳入ST(0)到ST(3)中----雖然這四個參數的空間也會在參數列表的棧上保留。函數的返回值在EAX或ST(0)中。保留的寄存器有EBP, EBX, ESI和EDI。 optlink在IBM VisualAge編譯器中被使用。
10.__clrcall
__clrcall是C++ .Net里面的。
總結
以上是生活随笔為你收集整理的java函数调用约定_2020-09-04:函数调用约定了解么?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: node 后台重定向_登录后重定向到用户
- 下一篇: 使用Jedis连接远程服务器的redis