2013-03-03 91 views
3

我一直在玩最近的Visual C++內聯彙編,我想知道是否可以直接將值添加到堆棧上的局部變量,例如:組裝,對棧上的局部變量進行算術運算

push 5 
add [esp], 7 

可以這樣做嗎?我問,因爲我已經在隨機有一些奇怪的問題,這樣做(儘管大多數的正常工作時間),但是如果我去通過寄存器我完全沒有任何問題,就像這樣:

push 5 
mov eax, [esp] 
add eax, 7 
mov [esp], eax 
+0

你的「奇怪問題」的性質是什麼?頭髮生長在奇怪的地方?鮮花盛開季節? – NovaDenizen 2013-03-03 02:16:19

+0

基本上在某些時候,我只是沒有得到我期望得到的價值,就好像堆棧被損壞了或者什麼。 – user2127922 2013-03-03 02:22:54

+2

編譯器可能無法正確評估指針的大小。 嘗試使用: add DWORD PTR [esp],7 – 2013-03-03 07:18:58

回答

0

正如Vlad Krasnov在對這個問題的評論中所說的,問題來自編譯器(和/或彙編器)不知道代碼中參數的大小,如add [esp], 7。如果您正在編寫此問題,則不會出現此問題,例如,add [esp], eax

如果你是編譯器,你會如何解釋這條指令?您被要求將7添加到ESP指向的內存位置。但是7和[esp]都沒有指定添加的參數有多大。一個字節?兩個字節?四個字節?如果這不是內聯彙編(即64位代碼中不允許),則甚至可能有8個字節。

請注意,雖然ESP是4字節,但它指向的內存位置可以是任意大小。即時值7也是如此,它可以適用於任意數量的字節。

Vlad Krasnov在評論中再次提到的解決方案是明確指定操作數的大小。你可以檢查你最喜歡的彙編程序的文檔,但在這種情況下,如果你想要32位加法,你可以寫add DWORD PTR [esp], 7。這顯然說[esp]指向內存中的DWORD(這是MASM 32位。)

另外請注意,不是所有的x86指令支持具有立即值和他們內存地址的形式。對於每條指令,您都可以查看「英特爾架構軟件開發指南」,第2卷(這是指令集參考),以確保您嘗試使用的指令實際存在!

而且,您應該始終檢查編譯器的彙編輸出(因爲您正在使用內聯彙編)以確保編譯器生成的代碼實際上是您的意圖。指示編譯器生成彙編代碼非常容易,而且它非常易讀!