簡體   English   中英

C中是否有任何類似於此匯編代碼的操作?

[英]Is there any operation in C analogous to this assembly code?

今天,我在匯編代碼中使用遞增的函數指針來創建函數的備用入口點:

.386
.MODEL FLAT, C
.DATA
    INCLUDELIB MSVCRT
    EXTRN puts:PROC
    HLO DB "Hello!", 0
    WLD DB "World!", 0
.CODE
    dentry PROC
        push offset HLO
        call puts           
        add esp, 4
        push offset WLD
        call puts
        add esp, 4
        ret
    dentry ENDP
    main PROC
        lea edx, offset dentry
        call edx
        lea edx, offset dentry
        add edx, 13
        call edx
        ret
    main ENDP
END

(我知道,從技術上講,此代碼無效,因為它在未初始化CRT的情況下調用puts ,但至少在MSVC 2010 SP1上,它沒有任何匯編或運行時錯誤,但可以正常工作。)

請注意,在第二次調用dentry的過程中,像以前一樣,我將函數的地址保存在edx寄存器中,但是這次我在調用函數之前將其地址增加了13個字節。

因此,該程序的輸出為:

C:\Temp>dblentry
Hello!
World!
World!

C:\Temp>

Hello!\\nWorld! ”的第一個輸出是從調用到函數的最開始,而第二個輸出是從以“ push offset WLD ”指令開始的調用。

我想知道這種語言是否存在於要比C,Pascal或FORTRAN之類的匯編程序更高級的語言中。 我知道C不允許您增加函數指針,但是還有其他方法可以實現這種功能嗎?

您可以使用longjmp函數: http ://www.cplusplus.com/reference/csetjmp/longjmp/

這是一個非常可怕的功能,但是它將滿足您的要求。

AFAIK,您只能在asm中編寫具有多個入口點的函數。

您可以在所有入口點上放置標簽,因此可以使用常規的直接調用,而不用硬編碼與第一個函數名稱的偏移量。

這使得從C或任何其他語言正常調用它們變得容易。

如果您擔心使功能主體重疊的工具(或人員)混亂,則較早的入口點的工作方式就像插入其他功能主體的功能一樣。


如果早期的入口點做了一點點額外的工作,然后落入主函數中,則可以執行此操作。 這主要是一種節省代碼大小的技術(這可能會提高I-cache / uop-cache命中率)。


編譯器傾向於在函數之間復制代碼,而不是在稍有不同的函數之間共享大量的公共實現。

但是,您可能只用一個額外的jmp就可以完成它,例如:

int foo(int a) { return bigfunc(a + 1); }
int bar(int a) { return bigfunc(a + 2); }

int bigfunc(int x) { /* a lot of code */ }

Godbolt編譯器瀏覽器上查看真實示例

foobar bigfunc ,這比讓bar掉進bigfunc (將foo跳過bar進入bigfunc還是不錯的,尤其是如果bar不是那么簡單的話。)


一般而言,跳入函數中間並不安全,因為非平凡的函數通常需要保存/恢復某些注冊表。 因此,序言推動了它們,而序言使它們流行了。 如果您跳入中間位置,則序幕中的pop將使堆棧不平衡。 (即,將返回地址彈出到寄存器中,然后返回到垃圾地址)。

另請參見在入口點標簽前使用說明的功能是否會引起任何問題(鏈接)?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM