行內組合陳述式範例

範例 1: 下列範例說明 volatile 關鍵字的用法。
#include <stdio.h>

inline bool acquireLock(int *lock){
  bool returnvalue = false;
  int lockval;
  asm volatile(
              /*--------a fence here-----*/
               
               "  0: lwarx %0,0,%2   \n" // Loads the word and reserves
                                         // a memory location for the subsequent
                                         // stwcx. instruction.

               "     cmpwi %0,0      \n" // Compares the lock value to 0.
               "     bne- 1f         \n" // If it is 0, you can acquire the 
                                         // lock. Otherwise, you did not get the
                                         // lock and must try again later.
                                           
               "     ori %0,%0,1     \n" // Sets the lock to 1. 
               "     stwcx. %0,0,%2  \n" // Tries to conditionally store 1
                                         // into the lock word to acquire 
                                         // the lock.
                                           
               "     bne- 0b         \n" // Reservation was lost. Try again.

               "     isync           \n" // Lock acquired. The isync instruction 
                                         // implements an import barrier to 
                                         // ensure that the instructions that
                                         // access the shared region guarded by
                                         // this lock are executed only after 
                                         // they acquire the lock.
 
               "     ori  %1,%1,1    \n" // Sets the return value for the 
                                         // function acquireLock to true.

               "  1:                 \n" // Did not get the lock. 
                                         // Will return false.

               /*------a fence here------*/

               :     "+r"   (lockval),
                     "+r"   (returnvalue) 
               :     "r"    (lock)       // "lock" is the address of the lock in 
                                         // memory.

               :     "cr0"               // cr0 is clobbered by cmpwi and stwcx.
               );
                	         
  return returnvalue;
}
int main()
{
  int myLock;
  if(acquireLock(&myLock)){
       printf("got it!\n");
  }else{ 		
       printf("someone else got it\n");
  } 
  return 0;
}

在此範例中, %0 參照第一個運算元 "+r"(lockval)%1 參照第二個運算元 "+r"(returnvalue),而 %2 參照第三個運算元 "r"(lock)

組合陳述式使用鎖定來控制對共用儲存體的存取; 在取得鎖定之前,沒有任何指令可以存取共用儲存體。

volatile 關鍵字暗示組合指示群組周圍有柵欄,因此無法將組合指示移出組合區塊或在組合區塊周圍移動。

如果沒有 volatile 關鍵字,編譯器可以移動指示以進行最佳化。 這可能會導致部分指示存取共用儲存體而不獲得鎖定。

在此組件陳述式中不需要使用 memory clobber ,因為指示不會以非預期的方式修改記憶體。 如果您使用 memory clobber ,則程式在功能上仍然正確。 不過, memory clobber 會導致許多不必要的重新載入,導致效能降低。

範例 2: 下列範例說明輸入及輸出運算元的符號名稱用法。
int a ;
int b = 1, c = 2, d = 3 ;  
__asm("  addc %[result], %[first], %[second]" 
      : [result]      "=r"       (a)
      : [first]       "r"        (b), 
        [second]      "r"        (d)
      );

在此範例中, %[result] 是指輸出運算元變數 a%[first] 是指輸入運算元變數 b,而 %[second] 是指輸入運算元變數 d

範例 3: 下列範例顯示一般使用 clobbbers中的條件暫存器。
  asm ("   add. %0,%1,%2  \n"     
       :   "=r"    (c)                    
       :   "r"     (a),
           "r"     (b)
       :   "cr0"
       );
在此範例中,除了組件陳述式 輸入輸出 中列出的暫存器之外, add. 指令也會影響條件暫存器欄位 0。 因此,您必須將 cr0 新增至 clobbers,以通知編譯器這一點。
範例 4: 下列範例顯示 memory clobber 的用法。
 asm volatile ("   dcbz 0, %0      \n" 
               :   "=r"(b)
               : 
               :   "memory"
               );
在此範例中,指示 dcbz 會清除快取區塊,且可能已變更記憶體位置中的變數。 編譯器無法知道哪些變數已變更。 因此,編譯器會假設所有資料都可能與該指令所變更的記憶體建立別名。

因此,在完成組合陳述式之後,必須從記憶體重新載入所需的所有項目。 memory clobber 可確保程式正確性,但犧牲程式效能,因為編譯器可能會重新載入與組合陳述式無關的資料。

範例 5: 下列範例顯示 + 修飾元及 K 限制的用法。
 asm ("   addi %0,%0,%2"
      :   "+r"    (a)
      :   "r"     (a),
          "K"     (15)
      );

此組合陳述式會新增運算元 %0 及運算元 %2,並將結果寫入運算元 %0。 輸出運算元使用 + 修飾元來指示可由指令讀取及寫入運算元 %0K 限制指出載入至運算元 %2 的值必須是 不帶正負號 16 位元 常數值。

範例 6: 下列範例顯示 % 修飾元及 f 限制的用法。
asm("   fadd %0, %1, %2"
    :   "=f"    (c)
    :   "%f"    (a),
        "f"     (b)
    ); 
此組合陳述式會新增運算元 ab,並將結果寫入運算元 c% 修飾元指出如果編譯器可以在這樣做時產生更好的程式碼,則可以切換運算元 ab 。 每一個運算元都有 f 限制,指出需要浮點暫存器。
範例 7: 下列範例顯示 b 限制的用法。
char res[8]={'a','b','c','d','e','f','g','h'};
char a='y';
int  index=7;

asm ("   stbx %0,%1,%2       \n"     \
     :                               \
     :    "r"    (a),
          "b"    (index),
          "r"    (res)
     ); 
在此範例中, b 限制項指示編譯器為輸入運算元 %1選擇 r0 以外的一般暫存器。 此程式的結果字串為 abcdefgy
範例 8: 下列範例顯示 m 限制的用法。
 asm ("   stb %1,%0       \n"     \
      :   "=m"    (res)           \
      :   "r"     (a)
      );

在此範例中,指令 stb 的語法為 stb RS,D(RA),其中 D 是位移, R 是暫存器。 D+RA 會形成有效位址,從 D(RA)計算。 透過使用限制 m,您不需要透過個別指定暫存器及位移來手動建構有效位址。

您可以使用單一限制 mo 來參照指令中的兩個運算元,不論正確的偏移應該是什麼,以及它是堆疊偏移還是 TOC (目錄) 偏移。 這可讓編譯器選擇正確的暫存器 (例如r1 代表自動變數) ,並自動套用正確的位移。