我在c:__asm__("mov $10, %rsi"); printf("%x")
中輸入此代碼,它打印a
。
我在gdb
調試它,發現結果存儲int register esi
。
問題:爲什麼結果是esi
?c printf(「%x」),它打印什麼?
回答
printf("%x")
試圖獲得第二個參數,但它不在那裏,所以它只是讀取應該出現的內存,找到存在的任何垃圾並將其打印出來。
簡而言之:它是未定義的行爲。
編輯:你看到相同的值作爲esi
寄存器的原因,是這個值計算程序中的一些早期的(但最近的)計算的一部分,並儲存在printf
試圖讀取相同的位置從。兩個地點重合的事實純粹是偶然的,在未定義的行爲範圍內。
它發現,它將視爲一個無符號整數並打印十六進制代碼(小寫)(這是%x所做的)。 – Thilo 2013-04-23 08:32:16
@ybungalobill它如何知道地址應該在哪裏?換句話說,它從哪裏讀取? – 2013-04-23 08:34:25
@Armin:這是「實現定義」。查看庫/編譯器的源代碼,或者查閱您的編譯器或ABI文檔。 – 2013-04-23 08:35:42
當調用printf("%x")
時,會發生它需要的參數被推送到堆棧(以相反的順序),並最終使用匯編命令call
調用該函數。當提供格式字符串"%x"
時,printf()
預計至少有一個參數在下面,所以它會讀取堆棧上的下一個值,可能是任何東西......
所以這種行爲實際上是未定義的,並且通常是利用的原因,因爲您可能會損壞堆棧。
也許有點excourse關於這個話題。
不是將返回地址推入堆棧,而是一旦參數按相反順序推入? – 2013-04-23 08:40:46
@SheerFish:通常(包括x86和amd64體系結構)它是'call'指令。 – ybungalobill 2013-04-23 08:42:07
我現在不是百分之百肯定,但我認爲是這樣......它必須在某個地方,以便ESP/RSP知道下一步該去哪裏。但這是實施和操作系統的依賴... – 2013-04-23 08:43:04
- 1. 爲什麼下面的printf打印0x32
- 2. 打印 '%' 與C的printf/C++
- 3. 爲什麼printf不打印垃圾值?
- 4. Java printf不打印
- 5. \ x在打印中做什麼
- 6. c - printf(「%s」)打印一個額外的@
- 7. C - printf(「%i」)打印一個額外的%
- 8. C printf不在線內打印?
- 9. printf()將不會打印字符串c
- 10. printf()打印垃圾字符
- 11. 爲什麼printf不在控制檯上打印「操作員」?
- 12. 爲什麼換行時使用ld打印printf失敗?
- 13. 爲什麼省略printf打印垃圾的參數?
- 14. 調用的printf打印
- 15. 爲什麼打印0(零)時沒有在C printf格式「%#x」的前面加上「0x」?
- 16. Java-爲什麼它打印出null?
- 17. 它爲什麼打印整數
- 18. 程序集中的printf如何知道要打印什麼?
- 19. 爲什麼write()在輸出重定向的printf()之前打印?
- 20. 爲什麼這個long double打印不正確使用printf?
- 21. 爲什麼printf(「%%」)只打印一個百分號(%)符號?
- 22. 爲什麼我的printf打印錯誤的值?
- 23. 怎樣的printf知道符號擴展後打印出什麼
- 24. 爲什麼第三個printf會打印未定義的值?
- 25. 爲什麼printf「$ {array [@]} \ n」打印我數組的所有元素?
- 26. 使用printf打印size_t的正確方法是什麼?
- 27. 這段代碼有什麼問題?事件printf未被打印
- 28. 將int打印爲float時,printf的行爲是什麼?
- 29. PHP - 爲什麼不打印變量,儘管它打印文本?
- 30. c#中的打印序列是什麼?
好問題!編輯:ybungalobill已經偷走了答案! – 2013-04-23 08:31:58
你是怎麼確定結果(大概你的意思是printf的返回值,應該是2)存儲在esi中? – nos 2013-04-23 09:18:15
'__asm __(「mov $ 10,%rsi」);'編輯'esi/rsi'值,我嘗試了一些其他的值。 – sumous 2013-04-23 09:21:11