2013-04-23 127 views
5

我在c:__asm__("mov $10, %rsi"); printf("%x")中輸入此代碼,它打印a
我在gdb調試它,發現結果存儲int register esi
問題:爲什麼結果是esic printf(「%x」),它打印什麼?

+0

好問題!編輯:ybungalobill已經偷走了答案! – 2013-04-23 08:31:58

+0

你是怎麼確定結果(大概你的意思是printf的返回值,應該是2)存儲在esi中? – nos 2013-04-23 09:18:15

+0

'__asm __(「mov $ 10,%rsi」);'編輯'esi/rsi'值,我嘗試了一些其他的值。 – sumous 2013-04-23 09:21:11

回答

11

printf("%x")試圖獲得第二個參數,但它不在那裏,所以它只是讀取應該出現的內存,找到存在的任何垃圾並將其打印出來。

簡而言之:它是未定義的行爲。

編輯:你看到相同的值作爲esi寄存器的原因,是這個值計算程序中的一些早期的(但最近的)計算的一部分,並儲存在printf試圖讀取相同的位置從。兩個地點重合的事實純粹是偶然的,在未定義的行爲範圍內。

+1

它發現,它將視爲一個無符號整數並打印十六進制代碼(小寫)(這是%x所做的)。 – Thilo 2013-04-23 08:32:16

+0

@ybungalobill它如何知道地址應該在哪裏?換句話說,它從哪裏讀取? – 2013-04-23 08:34:25

+1

@Armin:這是「實現定義」。查看庫/編譯器的源代碼,或者查閱您的編譯器或ABI文檔。 – 2013-04-23 08:35:42

2

當調用printf("%x")時,會發生它需要的參數被推送到堆棧(以相反的順序),並最終使用匯編命令call調用該函數。當提供格式字符串"%x"時,printf()預計至少有一個參數在下面,所以它會讀取堆棧上的下一個值,可能是任何東西......
所以這種行爲實際上是未定義的,並且通常是利用的原因,因爲您可能會損壞堆棧。

也許有點excourse關於這個話題。

+0

不是將返回地址推入堆棧,而是一旦參數按相反順序推入? – 2013-04-23 08:40:46

+0

@SheerFish:通常(包括x86和amd64體系結構)它是'call'指令。 – ybungalobill 2013-04-23 08:42:07

+0

我現在不是百分之百肯定,但我認爲是這樣......它必須在某個地方,以便ESP/RSP知道下一步該去哪裏。但這是實施和操作系統的依賴... – 2013-04-23 08:43:04

相關問題