2011-11-25 19 views
8

Ho due macro, una è scritta in assembly e l'altra in C. La seconda macro utilizza la prima macro. Tuttavia, voglio anche scrivere la seconda macro in assembly con volatile, così posso controllarne il posizionamento nel codice. E si noti che tid è un valore di runtime, non una costante come n.Come scrivere tutto questo in assembly

Qual è un buon modo per scriverlo in assembly? Inoltre, è possibile controllare il posizionamento di un codice C come assembly con volatile?

#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 è un valore di runtime, non una costante come n. – MetallicPriest

+0

(Non importa, non ha senso.) –

+1

È possibile memorizzare i valori 'tsp ' e 'msp ' in un array? –

risposta

6

Si può chiedere gcc la sua idea di come scrivere il codice in assembly: gcc -S foo.c o gcc -Wa,-alh=foo.s -c foo.c. Potresti voler migliorare i risultati, ovviamente. Sarà necessario fare un piccolo extra: utilizzare %0 per il parametro che si passa per il blocco dell'assembly e dichiarare i registri che sono stati danneggiati. Cercare Assembler Instructions with C Expression Operands in the GCC manual se non si è familiari. Ecco come potrebbe essere (avviso, digitato direttamente nel browser e non si conosce la sintassi dell'assembly 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)) 

Procedimento più elaborato comporterebbe capire quanti byte ogni movq - movq - blocca jmp richiederà (nota: non ho controllato, io uso 8) e facendo un salto calcolata in esso; qualcosa come

__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

Supponendo che si sta utilizzando GCC, si potrebbe tentare di utilizzare un'estensione GNU per mappare il registro stack pointer ad una variabile C:

static register int stack_pointer0 asm("msp0"); 

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

OK, che, probabilmente, non fa cosa ha fatto il tuo codice originale (non mi era chiaro quale fosse l'obiettivo), ma dovresti essere in grado di capire il resto da quello.

Penso di avere la sintassi giusta, ma mi scuso se non. So che questo funziona per i registri generali, e sono abbastanza fiducioso che GCC sappia cosa fare per i registri speciali, ma non si sa mai.

Spero che questo aiuti.

Problemi correlati