從歷史上看,C編譯器生成彙編代碼,然後由彙編器翻譯成機器代碼。內聯彙編是一個簡單的功能 - 在中間彙編代碼中,在這一點上,注入一些用戶選擇的代碼。一些編譯器直接生成機器碼,在這種情況下,它們包含彙編程序或調用外部彙編程序來爲內聯彙編代碼段生成機器碼。
彙編代碼最常見的用法是使用編譯器無法生成的專用處理器指令。例如,禁用關鍵部分的中斷,控制處理器功能(緩存,MMU,MPU,電源管理,查詢CPU功能等),訪問協處理器和硬件外圍設備(例如,x86上的inb
/outb
指令)等。很少發現asm("movl %ecx %eax")
,因爲它會影響其周圍的C代碼也在使用的通用寄存器,但asm("mcr p15, 0, 0, c7, c10, 5")
之類的東西也有其用處(ARM上的數據存儲器障礙)。 OSDev wiki有幾個示例代碼片段。
彙編代碼對實現破壞C的流控制模型的功能也很有用。一個常見的例子是線程之間的上下文切換(無論是協作還是搶佔,無論是否在相同的地址空間中)都需要彙編代碼來保存和恢復寄存器值。
彙編代碼也可用於手動優化內存或速度的小部分代碼。隨着編譯器變得越來越聰明,現在在應用程序級別上這很少相關,但它在大多數嵌入式世界中仍然很有用。
有兩種方法可以將裝配與C結合:通過內聯裝配,或將裝配模塊與C模塊鏈接。鏈接可以說是更乾淨但並不總是適用的:有時你需要一個函數中間的一條指令(例如,用於上下文切換的寄存器保存,函數調用會打破寄存器),或者你不想支付成本的函數調用。
大多數C編譯器都支持內聯彙編,但語法各不相同。它通常由關鍵字asm
,_asm
,__asm
或__asm__
引入。除了彙編代碼本身之外,內聯彙編構造還可以包含額外的代碼,這些代碼允許您在彙編和C之間傳遞值(例如,請求將局部變量的值複製到輸入中的寄存器)或聲明彙編代碼破壞或保留某些寄存器。
要跟進「你真的需要知道你在做什麼」。謹慎的說,您打算內聯的確切的彙編行並不總是完全由編譯器完成。我經歷了編譯器的微妙變化。編譯後總是要仔細看看反彙編,以確保它完全符合預期的要求。 – BabaBooey
我相信,如果你還添加'volatile'說明符,例如'__asm__ volatile(「instrs」);' – slugonamission
您還需要知道您的代碼將運行在哪個處理器(系列)上,某些情況下還需要知道哪個內存模型。幾乎任何處理器和操作系統都可以編譯ANSI-C,但是asm指令不可*便攜。 –