iT邦幫忙

2022 iThome 鐵人賽

DAY 7
1

今天談到呼叫慣例,因為在呼叫函數時,總是會有需要傳遞參數的時候,但參數究竟要放進哪個暫存器 ? 順序又要怎麼擺放 ? 這時候就要參考呼叫慣例,將參數放進對的暫存器,這樣在呼叫函式時才不會造成參數傳遞錯誤。這也是我當初在學習組合語言時所碰到的問題,也就是我們今天的主題--呼叫慣例。

但在談到呼叫慣例之前我們要先談到應用二進制介面 ( ABI ), ABI 描述到呼叫官吏、資料大小定義、記憶體對齊、檔案格式與其他細項,如果想了解其他部分可以到 ABI 微軟官方文檔瀏覽。

呼叫慣例又叫 Calling Convention,因為參數時常長度不一樣,因此應該會是傳遞參考,今天這篇主要要講的是另一份Calling Convention 微軟官方文檔中的 Parameter Passing 參數傳遞。

https://ithelp.ithome.com.tw/upload/images/20220922/20151538liK4wZewG5.png
根據文章的描述,其實已經標示得很明顯了,整數的第一個參數值放在 RCX,第二個參數放在 RDX,蒂絲個放在 R8,第四個放在 R9,第五個以後的都放在 Stack 中,此文章的這個表格下也有舉例與註解,可以去看看。

若回去注意前幾天寫的 HelloWorld ,可以發現我並沒有使用暫存器去傳遞參數,而是 push 進 Stack 中,因為我使用的方法是參數傳遞中的 stdcall 。

可以參考到這篇Argument Passing and Naming Conventions,前兩段提的方法就是文檔中的 cdecl ,將值存進暫存器中,其他的放進 Stack。但我的方法是 stdcall,將要傳遞的值全放進 Stack 中,然後再呼叫函數,在函數結束後將參數彈出來。但是在使用時要注意,放參數是有順序的,要先從最右邊的參數開始放,例如說

	scanf("%d",&a);

就需要先將 a 的位置放進 Stack 中,再將 "%d" 的格式化輸出放進 Stack,記得要先將格式化輸出 "%d" 宣告成一個變數再放進 Stack 中喔。所以在後面的第二個練習,我們會用到輸入,也就是 scanf 的函式。

那其實 stdcall 與 cdecl 非常相似,cdecl 也是參數傳遞的一種方法,兩者的差別在於維護 Stack 的位置,stdcall 在被呼叫函數回傳前調整 Stack , cdecl 在被呼叫函數回傳後由呼叫的函式去調整。

其他參考連結
痞客幫


上一篇
Day5 暫存器
下一篇
Day7 實作 Microsoft rand() - 介紹
系列文
絕對花心的30天組合語言13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言