第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

C-外部組裝函數(shù)使用相同的輸入返回不同的結(jié)果

C-外部組裝函數(shù)使用相同的輸入返回不同的結(jié)果

呼如林 2021-04-09 17:14:38
我在C中有一個(gè)使用NASM函數(shù)的程序。這是C程序的代碼:#include <stdio.h>#include <string.h>#include <math.h>extern float hyp(float a); // supposed to calculate 1/(2 - a) + 6void test(float (*f)(float)){    printf("%f %f %f\n", f(2.1), f(2.1), f(2.1));}void main(int argc, char** argv){    for(int i = 1; i < argc; i++){        if(!strcmp(argv[i], "calculate")){            test(hyp);        }    }}這是NASM函數(shù):section .data    a dd 1.0    b dd 2.0    c dd 6.0section .textglobal hyphyp:    push ebp    mov ebp, esp    finit    fld dword[b]    fsub dword[ebp + 8]    fstp dword[b]    fld dword[a]    fdiv dword[b]    fadd dword[c]    mov esp, ebp    pop ebp    ret這些程序在Linux中與gcc和nasm鏈接在一起。這是Makefile:all: project cleanmain.o: main.c    gcc -c main.c -o main.o -m32 -std=c99hyp.o: hyp.asm    nasm -f elf32 -o hyp.o hyp.asm -D UNIXproject: main.o hyp.o    gcc -o project main.o hyp.o -m32 -lmclean:    rm -rf *.o程序運(yùn)行時(shí),將輸出以下內(nèi)容:5.767442 5.545455 -4.000010最后一個(gè)數(shù)字是正確的。我的問題是:即使輸入相同,為什么這些結(jié)果也不同?
查看完整描述

1 回答

?
Qyouu

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



查看完整回答
反對(duì) 回復(fù) 2021-04-16
  • 1 回答
  • 0 關(guān)注
  • 282 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)