2012-02-28 72 views
1

我試圖對c代碼進行反向工程,但是這部分程序集無法真正理解。我知道這是SSE擴展的一部分。但是,有些東西與我在x86指令中習慣的不同。C代碼中的SSE2指令

static int sad16_sse2(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h) 
{ 
    int ret; 
    __asm__ volatile(
     "pxor %%xmm6, %%xmm6   \n\t" 
     ASMALIGN(4) 
     "1:        \n\t" 
     "movdqu (%1), %%xmm0   \n\t" 
     "movdqu (%1, %3), %%xmm1  \n\t" 
     "psadbw (%2), %%xmm0   \n\t" 
     "psadbw (%2, %3), %%xmm1  \n\t" 
     "paddw %%xmm0, %%xmm6   \n\t" 
     "paddw %%xmm1, %%xmm6   \n\t" 
     "lea (%1,%3,2), %1    \n\t" 
     "lea (%2,%3,2), %2    \n\t" 
     "sub $2, %0      \n\t" 
     " jg 1b       \n\t" 
     : "+r" (h), "+r" (blk1), "+r" (blk2) 
     : "r" ((x86_reg)stride) 
    ); 
    __asm__ volatile(
     "movhlps %%xmm6, %%xmm0   \n\t" 
     "paddw %%xmm0, %%xmm6   \n\t" 
     "movd %%xmm6, %0    \n\t" 
     : "=r"(ret) 
    ); 
    return ret; 
} 

什麼是%1,%2和%3? (%1,%2,%3)是什麼意思?另外「+ r」,「-r」,「= r」是什麼意思?

+0

此代碼使用_two disjointed_內聯彙編塊是無效的;它可能有效,但不能保證,因爲編譯器在其無限智慧中可能會選擇在輸入第二個__asm__塊之前對第二個「__asm__」塊的「非聲明輸入」(regs'%xmm0' /'%xmm6')做些什麼。請參閱http://stackoverflow.com/questions/8891139/why-is-this-inline-assembly-not-working關於如何解決該問題的一些細節。 – 2012-02-28 10:56:28

回答

0

內聯彙編程序的工作原理類似於宏預處理程序。正好與一個領先的百分之操作數通過在順序輸入參數替換,因爲它們出現在參數列表中,在這種情況下:

%0 h    output, register, r/w 
%1 blk1    output, register, r/w 
%2 blk2    output, register, r/w 
%3 (x86_reg)stride input, register, read only 

的參數是正常C表達式。它們可以通過「約束」進一步指定,在這種情況下,「r」表示該值應該在寄存器中,與作爲內存操作數的「m」相反。約束脩飾符「= r」使其成爲只寫操作數,「+ r」是讀寫操作數,「r」和正常讀操作數。

在第一個冒號後面出現輸出操作數,第二個輸入操作數之後和第三個可選的第三個破壞寄存器之後。

所以指令序列計算了blk1blk2的每個字節的絕對差值之和。這發生在16個字節的塊中,所以如果stride是16,塊是連續的,否則會有空洞。每條指令出現兩次是因爲一些最小的循環展開完成,h參數是要處理的32字節塊的數目。第二個asm塊似乎毫無用處,因爲psadbw指令僅在目標寄存器的低16位中求和。 (你是否遺漏了一些代碼?)