如果我有一個函數foo(arg1,arg2)。在IA32堆棧中,首先推入arg2,然後推入arg1,這樣被調用函數通過%ebp + 8訪問arg1並通過%ebp + 12訪問arg2,但是推回的原因是什麼? (我們的處理器提到了一些關於printf和count的內容,但我不太明白)。另外一般來說,調用函數從不傳遞參數的數量(有多少個參數),那麼被調用函數怎麼知道呢? 非常感謝!爲什麼在IA32堆棧過程中向後傳遞參數?
1
A
回答
1
在彙編層面,如果您以書面或倒序的方式在堆棧上傳遞參數並不重要,但所選方法必須與被調用函數所使用的方法相同。 C通常以相反的順序推送值,因爲它需要支持varargs
- 可變數量的參數。如果按照書面順序推送參數,那麼得到第一個參數並不容易。
像Java或C#(以及.NET一般)等現代語言可以正常推送值,因爲它們處理數組的附加參數(所以只有一個參數傳遞給被調用的函數 - 指向數組的指針)。
C的例子:
.data
format: db "Your lucky number is %d", 0
....
;code is equivalent to printf("Your lucky number is %d", 10);
push dword 10
push format
call printf
Java示例:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Your lucky number is %d
5: iconst_1
6: anewarray #4 // class java/lang/Object
9: dup
10: iconst_0
11: bipush 10
13: invokestatic #5 // Method java/lang/Integer.valueOf(I)Ljavava/lang/Integer;
16: aastore
17: invokevirtual #6 // Method java/io/PrintStream.printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
20: pop
+0
「推10」從哪裏來? – user1849043
+0
這是要打印的號碼。 – user35443
相關問題
- 1. 將參數通過堆棧傳遞給MASM中的過程
- 2. 在堆棧上傳遞參數
- 3. x86程序集:通過堆棧將參數傳遞給函數
- 4. 繞過核心數據堆棧傳遞
- 5. 通過堆棧傳遞數據
- 6. python - 通過堆棧裝飾器傳遞函數參數
- 7. 過程遞歸和堆棧
- 8. 什麼用戶參數從MEAN堆棧中的服務器傳遞到前端?
- 9. 爲什麼要通過線程函數傳遞參數?
- 10. c/C++通過參考堆棧幀佈局的指針/參數傳遞參數
- 11. 爲什麼堆棧中總會有無用的函數參數?
- 12. 堆棧爲空...爲什麼?
- 13. 爲什麼2堆棧對於後序橫向如此有效
- 14. 參數在變量參數函數中如何傳遞到堆棧上?
- 15. 什麼在堆棧中?
- 16. 爲什麼在堆棧中零片段
- 17. 爲什麼堆棧溢出?
- 18. 爲什麼堆棧有界?
- 19. 爲什麼堆棧炸燬
- 20. 爲什麼遞歸懶惰列表在Scala中打擊堆棧?
- 21. MEAN堆棧傳遞參數在路由器內
- 22. 不能在passport.js傳遞的參數 - MEAN堆棧
- 23. 在NASM堆棧上傳遞參數的問題
- 24. 程序集:在使用堆棧時將參數傳遞給函數有什麼好處嗎?
- 25. 爲什麼在通過參數傳遞值時會得到零?
- 26. 你爲什麼不傳遞參數?
- 27. 傳遞通過引用一個堆棧中分配參數的陣列
- 28. 將函數的參數傳遞給堆棧還是寄存器?
- 29. 數組的使用堆棧(參數傳遞/返回)
- 30. 線程堆棧和進程堆棧有什麼區別
這只是C調用約定。 C支持具有可變數量參數的函數,main()和printf()是常見的例子。通過將它們「向後」傳遞,第一個參數總是在已知位置。 –
被調用者將「知道」有多少個參數,因爲*編譯器*在編譯時知道並且看到保留適當數量的堆棧空間並生成代碼來訪問這些值。任何數量的var-args都會隱式轉換爲單個*數組*(加上數組的長度),並作爲參考傳遞給被調用者。 – JimmyB
而在C約定中,參數的可變數總是第一個?這是有道理的。然而,如果你按照正常順序推動它們,你也會知道「參數的數量」總是最後一個,對吧? – user1849043