Re: [問題] pascal call convention in c
※ 引述《LPH66 (杇瑣)》之銘言:
: 先回答你的 Q2 和 Q3
: 可變參數跟哪一邊清堆疊這兩件事是有關連的
: 所謂可變參數就是 callee 可能不會知道傳進來的參數有多少個
: 因此既然 callee 不知道 只好讓知道的 caller 來清堆疊
: 最簡單的例子就是 printf
: 我們在使用 printf 時會丟一堆有的沒有的參數進去
: 那 compiler 不可能在編譯 printf 這支函式的時候就知道以後誰會丟什麼參數進來
: 所以只好把清除堆疊的工作交給呼叫 printf 的函式 (caller)
: 相對的 不支援可變參數表示所有函式的參數個數都是固定的
: 也就是說 callee 會明確的知道自己有哪些參數傳進來
: 因此 callee 就能夠在結束時幫忙把參數給清除
: 在 Win 系統上面的 Win32 API 所使用的 stdcall 就是 callee 清除堆疊
: 因為這些 API 的參數都是固定的 沒有必要為了這些東西增加程式碼長度
: (以 x86 assembly 來說
: callee 清除堆疊只需要在 ret 指令加上一個 16-bit 常數指定清除的位元組數
: 但 caller 清除堆疊則通常需要額外的一個 add $xx,%esp 的加法指令)
: 這兩件事跟左到右還是右到左都沒什麼相關
: 這個方向只是一個約定而已
: 只不過兩邊得要一致才不致於搞錯到底哪個參數是哪個 (就像你的 foo4 一樣)
: 那現在常用的 calling convention 大多數都是右到左而已
: 另外你在 Q3 多問的那個問題
: 你的問題應該是卡在編譯器看似是知道你這一趟傳了 3 個參數進去
: 但其實不是這樣的
: 可變參數代表我要扔幾個參數進去都可以
: 那也許我這一次呼叫 foo4(1, 2, 3);
: 下一次我呼叫 foo4(5, "Hello World!", 0.12345, NULL);
: 等等的
: 這些參數的個數跟型態都不固定 (除了有指定的前幾個以外)
: 那 foo4 這個函數自己要如何才能知道第一個在哪裡?
: 前一種情形也許要加上 $0xc 後一種情形可能要加上 $0x14 或等等的
: 在編譯 foo4 這個函數時是不可能知道這回事的
: 在由左而右的順序裡要加多少只有在一個狀況可以完全確定
: 就是這個函數的參數個數跟型態都完全固定的時候
: 因此像你的 foo2 才能夠用 mov 0x8(%esp),%eax 找到第一個參數
: 這也順帶說明了為什麼現在大多都是採由右而左的順序
: 特別是支援可變參數的一定會採用右到左
: 理由就是由右到左推入堆疊的話 第一個參數會在堆疊的高處 = 接近堆疊指標處
: 那麼第一個參數的位置就一定是堆疊指標往下數固定大小
: 不論有沒有可變參數這件事都是對的
: 而在有可變參數的情況下 第一個參數的位置就會是固定的
: 因此也能夠方便地由這個參數的位置去定位出其他的參數
: (這正是 va_begin() va_arg() va_end() 這幾個 macro 在做的事)
: 再來是 Q1
: 其實我從來沒聽說過 pascal convention 效率比較好
: 你聽到的說法可能是程式碼會少一個指令之類的
: 但是那個指令只不過是我上面所提到的 add $xx,%esp 而已
感謝回應, 我得花點時間消化一下, 先提 效率 這事:
http://en.wikipedia.org/wiki/X86_calling_conventions#Callee_clean-up
When the callee cleans the arguments from the stack it needs to be known at
compile time how many bytes the stack needs to be adjusted. Therefore, these
calling conventions are not compatible with variable argument lists, e.g.
printf(). They may be, however, more space efficient, as the code needed to
unwind the stack does not need to be generated for each call.
因為看到 pascal call convention 效率會比較好 (不記得在那看到的),
看了 wiki, 應該是指 space efficient, 不是速度上的快。
----------------------
我應該再跑個參數不同的版本 ex:
x=foo3(1, 2, 3);
x=foo3(1, 2, 3, 4, 5, 6);
也許能有更清楚的想法
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.125.239.46
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 3 之 3 篇):