2016-05-30 12 views
7

Nel kernel di Linux linux/arch/x86/boot/main.c, ho trovato un pezzo di linea di codice asm:Cosa significa% Stand P in assembly inline gcc

asm("leal %P1(%%esp),%0" 
     : "=r" (stack_end) : "i" (-STACK_SIZE)); 

Questo frammento di codice è piuttosto semplice, ma %P1 mi ha confuso. Ho controllato alcuni tutorial di linguaggio assembly, ma non ho trovato nulla a riguardo.

Quindi qualcuno può darmi qualche indizio su questo?

+1

non cito me, ma credo che su alcune versioni del _GCC_ il prefisso di dimensione operando 'P' assume un valore immediato e spoglia il' '$ firmare in modo che il valore possa essere utilizzato per i valori di spostamento x86. Se hai appena usato '% 1', l'output sarebbe stato simile a' leal $ stackdisp (% esp) '. (dove stackdisp era il valore dell'operando 1). Se il '$' sarebbe stato emesso, l'assemblatore si sarebbe lamentato di ciò. –

+1

Possibile duplicato di [gcc inline assembly usando il modificatore "P" e vincolo "p" su "m" nel kernel Linux] (http://stackoverflow.com/questions/20965114/gcc-inline-assembly-using-modifier-p -e-constraint-p-su-m-in-linux-kern) –

+2

Parte della tua confusione deriva senza dubbio dal fatto che il modificatore 'P' non è documentato (vergogna su linux per l'utilizzo di funzionalità del compilatore non documentate). In generale, @MichaelPetch ha questo diritto: disattiva le "decorazioni" in cui gcc potrebbe essere tentato di applicare a% 1 come @PLT e BYTE PTR (non esitare a cercare "P" nell'origine: https: // gcc. gnu.org/viewcvs/gcc/trunk/gcc/config/i386/i386.c). Dato il vincolo "i", mi aspetterei davvero che questo sia scritto usando il modificatore (documentato!) '% C1', ma qui potrebbe esserci una cronologia. –

risposta

3

Il modificatore uscita P Ufficiosamente documentato in un commento in gcc/config/i386/i386.md:

;; The special asm out single letter directives following a '%' are: 
... 
;; P -- if PIC, print an @PLT suffix. 
;; p -- print raw symbol name. 

Il modificatore maiuscole P probabilmente non è ciò che si vuole qui, ma quando non è la compilazione di PIC (Posizione Codice Indipendente), quindi si comporta come il modificatore p minuscolo. L'intento di impedire al compilatore di emettere l'operando utilizzando il formato normalmente utilizzato per i valori immediati, che non funzionerebbe qui. Come David Wohlferd ha detto che sarebbe stata una buona idea usare il modificatore c, che è documented ed è pensato specificamente per gestire i valori immediati. Tenete presente che questo codice è stato probabilmente scritto prima che il modificatore c sia stato documentato, poiché per molto tempo nessuno dei modificatori è stato documentato.

Dato che l'istruzione di assemblaggio inline viene eseguita solo una volta al momento dell'avvio, le prestazioni non sono importanti, quindi non mi sarei preoccupato di cercare di essere intelligente utilizzando LEA. È possibile evitare i modificatori operandi completamente con qualcosa di semplice come:

char *stack_pointer; 
asm ("mov %%esp, %0" : "=r" (stack_pointer)); 
stack_end = stack_pointer - STACK_SIZE;