簡體   English   中英

為什么GCC內聯匯編程序需要blobbering信息,但MSVC不需要

[英]Why does GCC inline assembler require clobbering information, but MSVC doesn't

我不明白這是怎么回事。

GCC內聯匯編程序很難做到,但是對於標記符號信息非常具體,因此編譯器知道你正在做什么。

Microsoft Visual C ++的inline assember非常容易使用(它似乎總是Just Work),但我不知道它對你的代碼有什么樣的保證或假設。

VC ++是否試圖“自動檢測”哪些寄存器被破壞? 它如何知道如何更改寄存器和堆棧指針? 它做出任何假設嗎? 如果是這樣,你如何解決這些假設?

至於為什么海灣合作委員會不像MSVC那樣做,有幾個原因:

  1. GCC是一個可重定向的編譯器,但匯編語法只是原始文本。 為了使clobber檢測自動化,GCC必須解析匯編語言以了解哪些寄存器被破壞(包括由操作碼未命名寄存器的指令隱式破壞的寄存器)。 這必須適用於所有架構。 目前,GCC不解析匯編語言; 在執行%替換后,它只是將其粘貼到程序集輸出中。 我們的想法是生成並避免解析。

  2. 在GCC內聯匯編語言中, clobbering寄存器是例外而不是規則 原因是它是一種比MSVC更復雜的語言。 GCC的內聯匯編語言為您分配寄存器。 所以你通常不直接使用%eax類的東西,而是使用像%0這樣的代碼,GCC代替可用的寄存器。 (要做到這一點,編譯器不必理解匯編語言!你表達了約束,這些約束確保GCC用適當的寄存器替換適合用法的%0 。) 如果你的匯編代碼被重寫,你只需要clobber - 編碼寄存器,而不是它覆蓋GCC為您分配的輸出操作數

請注意,使用GCC內聯匯編時,您不必編寫從生成其初始值的C表達式加載匯編語言操作數的代碼,也不必將結果操作數存儲到C目標中。 例如,您只是表示存在類型為"r" (寄存器)的輸入操作數,該操作數派生自表達式foo->bar + 1 GCC分配寄存器並生成代碼以從foo->bar + 1加載它,然后將匯編模板中%0出現替換為該寄存器的名稱。

文檔引用:

使用__asm在C / C ++函數中編寫匯編語言時,不需要保留EAX,EBX,ECX,EDX,ESI或EDI寄存器。 例如,在使用內聯匯編編寫函數的POWER2.C示例中,power2函數不會保留EAX寄存器中的值。 但是,使用這些寄存器會影響代碼質量,因為寄存器分配器不能使用它們來跨__asm塊存儲值。 此外,通過在內聯匯編代碼中使用EBX,ESI或EDI,可以強制編譯器在函數序言和結尾中保存和恢復這些寄存器。

您應該保留您使用的其他寄存器(例如DS,SS,SP,BP和標志寄存器)作為__asm塊的范圍。 您應該保留ESP和EBP寄存器,除非您有某些理由更改它們(例如,切換堆棧)。 另請參閱優化內聯匯編

暫無
暫無

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

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