1 回答

TA貢獻(xiàn)1786條經(jīng)驗(yàn) 獲得超11個(gè)贊
該錯(cuò)誤是您執(zhí)行此操作:
fstp dword[b]
這會(huì)覆蓋的值b,因此,下次調(diào)用該函數(shù)時(shí),常量是錯(cuò)誤的。在整個(gè)程序的輸出中,這顯示為最右邊的評(píng)估是唯一正確的評(píng)估,因?yàn)榫幾g器printf從右到左評(píng)估了參數(shù)。(可以按任意順序?qū)Χ鄥?shù)函數(shù)的參數(shù)求值。)
您應(yīng)該使用該.rodata部分作為常量。那么程序?qū)⒈罎⒍皇歉采w常量。
您可以避免使用fdivr而不是來存儲(chǔ)和重新加載中間值fdiv。
hyp:
fld DWORD PTR [b]
fsub DWORD PTR [esp+4]
fdivr DWORD PTR [a]
fadd DWORD PTR [c]
ret
或者,執(zhí)行Forth程序員會(huì)做的事情,并在其他所有內(nèi)容之前加載常量1,因此在需要時(shí)將其保存在ST(1)中。這使您可以使用fld1而不是將1.0放入內(nèi)存中。
hyp:
fld1
fld DWORD PTR [b]
fsub DWORD PTR [esp+4]
fdivp
fadd DWORD PTR [c]
ret
您不需要發(fā)出finit,因?yàn)锳BI保證在流程啟動(dòng)期間已經(jīng)完成了此操作。您不需要為此函數(shù)設(shè)置EBP,因?yàn)樗粫?huì)調(diào)用任何函數(shù)(該術(shù)語的術(shù)語是“葉子過程”),也不需要堆棧上的任何暫存空間。
如果您使用的是現(xiàn)代CPU,另一種選擇是使用較新的SSE2指令。這將為您提供普通的寄存器,而不是操作數(shù)堆棧,并且還意味著計(jì)算實(shí)際上是全部完成,float而不是80位擴(kuò)展,這可能非常重要-一些復(fù)雜的數(shù)值算法,如果它們的浮點(diǎn)精度高于整數(shù),則會(huì)出錯(cuò)。設(shè)計(jì)師期望的。但是,由于您使用的是32位ELF ABI,因此返回值仍需要在ST(0)中結(jié)束,并且SSE和x87寄存器之間沒有直接移動(dòng)指令,因此必須遍歷內(nèi)存。抱歉,我不知道如何用Intel語法編寫SSE2指令。
hyp:
subl $4, %esp
movss b, %xmm1
subss 8(%esp), %xmm1
movss a, %xmm0
divss %xmm1, %xmm0
addss c, %xmm0
movss %xmm0, (%esp)
flds (%esp)
addl $4, %esp
ret
在64位ELF ABI中,在XMM0中有浮點(diǎn)返回值(默認(rèn)情況下也將參數(shù)傳遞到寄存器中),這就是
hyp:
movss b(%rip), %xmm1
subss %xmm0, %xmm1
movss a(%rip), %xmm0
divss %xmm1, %xmm0
addss c(%rip), %xmm0
ret
添加回答
舉報(bào)