<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
用簡單的程式碼用以分析go的呼叫約定及多返回值的返回方式。
package main func vals(c, d int) (a int, b int) { e := 1 f := 2 a = c + d + e + f b = d * 2 return } func testMutil() { i, j := vals(1, 2) i = i + 1 j = j + 1 } func main() { testMutil() }
編譯go build -gcflags "-N -l" test.go並通過反編譯軟體獲得部分組合:
main_vals: sub rsp, 18h mov [rsp+18h+var_8], rbp lea rbp, [rsp+18h+var_8] mov [rsp+18h+arg_10], 0 mov [rsp+18h+arg_18], 0 mov [rsp+18h+var_10], 1 mov [rsp+18h+var_18], 2 mov rax, [rsp+18h+arg_0] add rax, [rsp+18h+arg_8] add rax, [rsp+18h+var_10] add rax, 2 mov [rsp+18h+arg_10], rax mov rax, [rsp+18h+arg_8] shl rax, 1 mov [rsp+18h+arg_18], rax mov rbp, [rsp+18h+var_8] add rsp, 18h retn main_vals endp main_testMutil: mov rcx, gs:28h mov rcx, [rcx+0] cmp rsp, [rcx+10h] jbe short morestack_noctxt sub rsp, 48h mov [rsp+48h+var_8], rbp lea rbp, [rsp+48h+var_8] mov [rsp+48h+var_48], 1 mov [rsp+48h+var_40], 2 call main_vals mov rax, [rsp+48h+var_38] mov [rsp+48h+var_10], rax mov rax, [rsp+48h+var_30] mov [rsp+48h+var_18], rax mov rax, [rsp+48h+var_10] mov [rsp+48h+var_20], rax mov rax, [rsp+48h+var_18] mov [rsp+48h+var_28], rax mov rax, [rsp+48h+var_20] inc rax mov [rsp+48h+var_20], rax mov rax, [rsp+48h+var_28] inc rax mov [rsp+48h+var_28], rax mov rbp, [rsp+48h+var_8] add rsp, 48h retn morestack_noctxt: call runtime_morestack_noctxt main_testMutil endp
__stdcall呼叫約定:函數的引數自右向左通過棧傳遞,被呼叫的函數在返回前清理傳送引數的記憶體棧。
_cdecl是C和C++程式的預設呼叫方式。每一個呼叫它的函數都包含清空堆疊的程式碼,所以產生的可執行檔案大小會比呼叫_stdcall函數的大。函數採用從右到左的壓棧方式。注意:對於可變引數的成員函數,始終使用__cdecl的轉換方式。
__fastcall呼叫約定:它是通過暫存器來傳送引數的(實際上,它用ECX和EDX傳送前兩個雙字(DWORD)或更小的引數,剩下的引數仍舊自右向左壓棧傳送,被呼叫的函數在返回前清理傳送引數的記憶體棧)。
thiscall僅僅應用於”C++”成員函數。this指標存放於CX暫存器,引數從右到左壓。thiscall不是關鍵詞,因此不能被程式設計師指定。
naked call採用1-4的呼叫約定時,如果必要的話,進入函數時編譯器會產生程式碼來儲存ESI,EDI,EBX,EBP暫存器,退出函數時則產生程式碼恢復這些暫存器的內容。naked call不產生這樣的程式碼。naked call不是型別修飾符,故必須和_declspec共同使用。
sub rsp, 18h mov [rsp+18h+var_8], rbp ... mov rbp, [rsp+18h+var_8] add rsp, 18h
這段程式碼分別對應棧幀的構造與銷燬。
根據反組合並且偵錯,可以發現go語言引數是自右向左通過棧傳遞,被呼叫的函數在返回前清理傳送引數的記憶體棧。所以GO語言符合__stdcall呼叫約定。
go語言可以返回多個返回值, 但同為編譯型語言的C、C++卻不支援。
1.C/C++返回值返回方式。
C/C++是通過eax/rax(32/64bit)暫存器返回的返回值。
2.go語言多返回值返回方式
可以看到vals函數的組合,通過偵錯,可知arg_10與arg_18就是返回值a和b, arg_0與arg_8分別是引數c和d。其中
mov [rsp+18h+arg_10], rax ... mov [rsp+18h+arg_18], rax
分別將引數值返回到引數上。之後在main_testMutil中將引數返回值拷貝到對應區域性變數中
mov rax, [rsp+48h+var_38] mov [rsp+48h+var_10], rax mov rax, [rsp+48h+var_30] mov [rsp+48h+var_18], rax
這就是go語言多返回值的實現方法了。
go語言採用的是__stdcall呼叫約定。go多返回值是通過棧傳遞的。將多個返回值先傳回引數上,函數棧幀銷燬後並不會銷燬引數部分(這裡用作返回值),再將引數部分進行拷貝然後再參與運算。
以上就是解析go語言呼叫約定多返回值實現原理的詳細內容,更多關於go呼叫約定多返回值的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45