2011-11-25 41 views
8

我有兩個宏,一個用匯編語言編寫,另一個用C語言編寫。第二個宏使用第一個宏。不過,我也想用volatile編寫第二個宏程序,所以我可以控制它在代碼中的位置。請注意,tid是一個運行時值,而不是像n這樣的常量。如何在彙編中編寫所有這一切

什麼是在彙編中編寫的好方法?另外,是否可以通過volatile來控制類似程序集的C代碼的放置?

#define SAVE_SP(n) __asm__ __volatile__ ("movq %rsp, msp"#n";" \ 
    "movq ts"#n", %rsp;" \ 
    ) 

#define SAVE_STACK_POINTER(tid) \ 
    switch(tid) \ 
    { \ 
     case 0: \ 
      SAVE_SP(0); \ 
      break; \ 
     case 1: \ 
      SAVE_SP(1); \ 
      break; \ 
     case 2: \ 
      SAVE_SP(2); \ 
      break; \ 
     case 3: \ 
      SAVE_SP(3); \ 
      break; \ 
    } 
+0

tid是一個運行時值,而不是像n那樣的常量。 – MetallicPriest

+0

(不要緊,這是無稽之談。) –

+1

是否可以將'tsp '和'msp '的值存儲在數組中? –

回答

6

你可以問的gcc其如何編寫代碼彙編的想法:gcc -S foo.cgcc -Wa,-alh=foo.s -c foo.c。當然,您可能想要改進結果。您需要做一些額外的工作:使用%0作爲傳遞給裝配體塊的參數,並聲明已經破壞的寄存器。如果你不熟悉,請查閱Assembler Instructions with C Expression Operands in the GCC manual。這可能是這樣的(警告,直接輸入瀏覽器,並且不知道x86彙編語法)。

#define SAVE_STACK_POINTER(tid) __asm__ __volatile__ (" \ 
     cmpl $0, %0         \n\ 
     je .SAVE_STACK_POINTER_0      \n\ 
     cmpl $1, %0         \n\ 
     je .SAVE_STACK_POINTER_1      \n\ 
     cmpl $2, %0         \n\ 
     je .SAVE_STACK_POINTER_2      \n\ 
     cmpl $3, %0         \n\ 
     je .SAVE_STACK_POINTER_3      \n\ 
     jmp .SAVE_STACK_POINTER_done     \n\ 
     .SAVE_STACK_POINTER_0:       \n\ 
     movq %%rsp, msp0        \n\ 
     movq ts0, %%rsp        \n\ 
     jmp SAVE_STACK_POINTER_done     \n\ 
     .SAVE_STACK_POINTER_1:       \n\ 
     movq %%rsp, msp1        \n\ 
     movq ts1, %%rsp        \n\ 
     jmp SAVE_STACK_POINTER_done     \n\ 
     .SAVE_STACK_POINTER_2:       \n\ 
     movq %%rsp, msp2        \n\ 
     movq ts2, %%rsp        \n\ 
     jmp SAVE_STACK_POINTER_done     \n\ 
     .SAVE_STACK_POINTER_3:       \n\ 
     movq %%rsp, msp3        \n\ 
     movq ts3, %%rsp        \n\ 
     .SAVE_STACK_POINTER_done:      \n\ 
    " : : "r" (tid)) 

票友方法將涉及找出多少字節每movq - movq - jmp塊需要(注:我沒有檢查,我使用8),使一個計算跳了進去;像

__asm__("      \n\ 
    movl %0, %eax    \n\ 
    mul 8, %eax     \n\ 
    add 4, %eax     \n\ 
    jmp . + %eax     \n\ 
    movq %%rsp, msp0    \n\ 
    movq ts0, %%rsp    \n\ 
    jmp .SAVE_STACK_POINTER_done \n\ 
    … 
    .SAVE_STACK_POINTER_done:  \n\ 
" : : "r" (tid) : "%eax") 
1

假設你使用GCC,你可以嘗試使用GNU擴展堆棧指針寄存器映射到C變量:

static register int stack_pointer0 asm("msp0"); 

void myfn() { 
    ...... 
    saved_stack_pointer = stack_pointer0; 
    ...... 
} 

OK,這可能不會做你原來的代碼做了什麼(我不清楚目標是什麼),但你應該能夠從中找出其他的。

我想我的語法正確,但是,如果不是,我會道歉。我知道這適用於通用寄存器,我非常有信心GCC知道如何處理特殊寄存器,但你永遠不知道。

希望有所幫助。