GCC 裡的 Inline Assembly

Update:感謝某長輩提醒,標題從「Unix 環境下的 Inline Assembly」改成「GCC 裡的 Inline Assembly」。

從大二修 Assembly 後就很久沒寫組語了,當時修的時候還是用 Intel 語法寫,就一直沒學到 AT&T 語法,後來從網路上看也只知道 src 與 dst 的位置通常是相反的,以及 register 前面要用 % 修飾,其他的像是記憶體的定址要怎麼寫都不知道,所以在 Unix 下一直不會寫 Assembly...

前幾天有個學弟剛好在寫作業,要用 MMX 計算一個整數 Vector (看做是 1*n 的 Matrix) 乘上整數 Matrix (n*n) 的結果 (其中 n 會是 4 的倍數,另外每個整數都是 16 bits),趁著這個機會摸索 GCC 裡要怎麼寫 Inline Assembly,以及 AT&T 語法與 Intel 語法不同的地方...

這是剛摸索出來怎麼寫,基本上請不要太要求... :p 編譯環境是 6.1 系統內附的 GCC (gcc version 3.4.4 [FreeBSD] 20050518)。

void matrixMMX(const unsigned int n,
    const uint16_t const *vec, const uint16_t const *mat,
    uint16_t *result)
{
    const unsigned int n2 = n / (64 / 16);

    // First empty the result array
    bzero(result, sizeof(uint16_t) * n);

    asm volatile("\\
        mov %1, %%edi;\\
        mov %3, %%ecx;\\
        mov %2, %%edx;\\
loop1:\\
        mov %0, %%esi;\\
        push %%ecx;\\
        mov %4, %%ecx;\\
loop2:\\
        movq (%%esi), %%mm0;\\
        pmaddwd (%%edi), %%mm0;\\
\\
        movd %%mm0, %%eax;\\
        mov %%eax, %%ebx;\\
        shr $16, %%eax;\\
        add %%ax, %%bx;\\
        add %%bx, (%%edx);\\
\\
        psrlq $32, %%mm0;\\
\\
        movd %%mm0, %%eax;\\
        mov %%eax, %%ebx;\\
        shr $16, %%eax;\\
        add %%ax, %%bx;\\
\\
        add %%bx, (%%edx);\\
\\
        add $8, %%edi;\\
        add $8, %%esi;\\
        loop loop2;\\
\\
        add $2, %%edx;\\
        pop %%ecx;\\
        loop loop1;\\
\\
        emms;"::
        "X"(vec), "X"(mat), "X"(result), "X"(n), "X"(n2):
        "eax", "ebx", "ecx", "edx", "esi", "edi", "mm0");
}

5 thoughts on “GCC 裡的 Inline Assembly”

  1. 試試看 NASM 吧。可以 output 出 ELF 格式,可是還是用 intel 語法。這是我以前當 TA 代大三必修的 compiler 學會的。

    不過在 UNIX 上寫 assembly 還滿鳥的,光是 Linux 和 FreeBSD 的 system call 方式就不一樣,很不 portable 。

  2. nasm 我知道,我有寫另外一個 .s,可以用 Intel 語法,在台大資工網頁上有 nasm 很基本的教學,看完就知道要怎麼搞了,再去 nasm 的網頁上看一下 proc/endproc 怎麼用就差不多了 :p

    btw... 會用 assembly 叫 syscall 本來就沒打算 portable 吧...

Leave a Reply

Your email address will not be published. Required fields are marked *