2013-04-03 59 views
4

我需要在x86程序集中將CH的內容添加到EAX,但沒有地址模式似乎支持它。理想的情況是我希望像一個尋址模式:如何在x86程序集中將CH添加到EAX中?

ADD EAX,r8 

ADD r32,r8 

ADD r/m32,r8 

ADD沒有任何一種模式。我不能屏蔽ECX,因爲它有其他垃圾,我在其他地方使用,而且我用完了所有其他寄存器,所以我唯一的選擇似乎是使用內存訪問。任何想法我可以如何解決這個問題?

注意我不能使用像r/m8,r8這樣的模式,因爲那樣就不會有進位。

+3

它的時間去爲x64和獲得這些額外的寄存器。 :) – 2013-04-03 18:36:45

+0

[省略幀指針](http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Optimize-Options.html)可以幫助您釋放更多的寄存器,更快地調用函數並生成更小的代碼與貿易更難調試。但無論如何,去64位更好 – 2014-03-06 14:23:18

回答

3

x86只是沒有這種靈活的尋址模式,正如你所觀察到的。您無法在一個步驟中將8位寄存器添加到32位寄存器。你的選擇是釋放一個寄存器和零/符號擴展,然後添加r32,r32,或者添加r8,r8,然後在進位標誌上跳轉來調整結果。

我建議你應該將一個寄存器溢出到內存中,在現代處理器上,一對內存訪問比分支要便宜得多(因爲它會從存儲緩衝區中加載),並且你可能會重寫其他代碼在泄漏周圍。

2

使用像r/m8,r8這樣的模式,並在必要時向EAX添加常量0x100來傳播進位。

2

如果你泄漏了一個寄存器,你可以避免分支。例如,

subl $4, %esp 

使用的指令序列:

movl %eax, (%esp) 
... 
movzbl %ch, %eax 
... 
addl (%esp), %eax 

,並在年底恢復堆棧指針:

addl $4, %esp 

這可能嚴重破壞任何試圖調試中這個代碼塊,如果這是一個問題。


或者,下面的道格·柯里的建議:

addb %ch, %al 
jnc done 
addl 0x100, %eax 
done: 
+0

是不是上述代碼與「推EAX」(後面跟着「彈出EAX」)? – selbie 2013-04-03 19:08:02

+0

是的 - 但我不知道這是否需要在一個循環中,所以我想我會明確。 – 2013-04-03 19:09:31

0

您還可以添加32位值,並撤消了24 MSB的添加:S:

add eax, ecx 
xor cl,cl   // also `and ecx, 0xffffff00` is possible 
sub eax, ecx 

這自然破壞了要添加的價值,但保留了垃圾。 (重新閱讀這個問題,實際上需要圍繞代碼塊xchg cl,ch,這使得解決方案對任務來說不是最理想的。)

1

改寫Doug的回答(在Intel語法):

add al, ch 
    jnc no_carry 
    add eax, 100h 
no_carry: 
1

它操作簡單,對EAX:

add al,ch 
adc ah,0 
rorx eax,16 
adc ax,0 
rorx eax,16 

在第一條指令添加下部並保留進位標誌,在第二條指令將進位標誌添加到寄存器的較高部分。它也保留了來源的內容。注意寄存器暫停,並將代碼與其他指令混合以避免它。
補充:

add al,ch 
adc ah,0 
bswap eax 
xchg al,ah 
adc ax 
xchg al,ah 
bswap eax 
+0

雖然只適用於haspwell(宏爲短暫旋轉不帶版本,需要1個週期)... 其他選項是bswap,xchg – Programmer 2014-10-18 12:34:18

+0

間接跳轉可能有更大的懲罰比更大的指令量,所以它是有道理的使用更多的指令 – Programmer 2014-10-18 13:08:53

相關問題