2009-11-30 12 views
5

ho rilevato un errore durante l'esecuzione del seguente codice AssemblyAssemblea Segmentation Fault

#cpuid using C library Functions 
.section .data 
output: 
.asciz "The Processor Vendor ID is '%s'\n" 
.section .bss 
.lcomm buffer, 12 
.section .text 
.globl main 
main: 
movq $0, %rax 
cpuid 
movq $buffer, %rdi 
movq %rbx, (%rdi) 
movq %rdx, (%rdi) 
movq %rcx, (%rdi) 
pushq $buffer 
pushq $output 
call printf 
addq $8, %rsp 
pushq $0 
call exit 

Si incontra segmentation fault alla parte di libreria C Calling: chiamata printf è in esecuzione in modalità x86_64. Qualcosa che ho perso durante la compilazione del codice x64 per quanto riguarda la libreria c? O c'è qualcosa di sbagliato con il codice

Grazie

+2

potrebbe desiderare di aumentare% rdi di una quantità appropriata tra quelle di movq – Managu

+1

Grazie a tutti, ho risolto il problema. E 'stata la libreria errata che ho caricato funziona bene dopo averla ld manualmente con /lib/ld-linux-x86-64.so.2 e ho sostituito la funzione principale con _start. Lo faccio come collegamento dinamico. Ci scusiamo per il cattivo inglese –

risposta

0
non

familiarità con il montaggio, quindi un salto nel buio: sono entrambe le corde con zero finale?

+0

'.asciz' aggiunge automaticamente il null che termina. – querist

4

Viene richiamata l'inizializzazione della libreria runtime C? Deve essere eseguito prima per poter impostare lo stdout. A proposito, una traccia di stack eliminerebbe dubbi sulla causa del problema.

Inoltre, evitare che la conversione% s trabocchi il buffer con% .12s, o semplicemente metti un byte NUL dopo il buffer.

0

È necessario terminare con null la stringa che si scrive in $ buffer, anziché scrivere sopra una parola tre volte. Inoltre, wallyk ha ragione: sei sicuro che il CRT sia stato inizializzato?

Onestamente, è davvero molto meglio scrivere questo programma, che chiama una funzione di libreria C, in C. Scrivi il codice CPUID come assembly inline all'interno di una funzione __cdecl, fallo scrivere il suo risultato in un puntatore stringa, e poi chiama quella funzione da un programma C.

void GetCPUID(char *toStr) 
{ 
// inline assembly left as exercise for the reader.. 
// write ebx to *toStr, ecx to *toStr+4, edx to *toStr+8, and 0 to *toStr+12 
} 

void PrintCPUID() 
{ 
    char cpuidstr[16]; 
    GetCPUID(cpuidstr); 
    printf("cpuid: %s\n", cpuidstr); 

} 
2

Gli inviti assembler per 64bit fprintf sono apparentemente cambiate, quindi o linkare la libreria a 32 bit o utilizzare il seguente codice:

#cpuid using C library Functions 
.section .data 
output: 
.asciz "The Processor Vendor ID is '%s'\n" 
.section .bss 
.lcomm buffer, 12 
.section .text 
.globl main 
main: 
movq $0, %rax 
cpuid 
movq $buffer, %rdi 
movq %rbx, (%rdi) 
movq %rdx, 4(%rdi) 
movq %rcx, 8(%rdi) 
movq $buffer, %rsi #1st parameter 
movq $output, %rdi #2nd parameter 
movq $0, %rax 
call printf 
addq $8, %rsp 
pushq $0 
call exit 
+0

le istruzioni di movq non incrementano '(% rdi)', quindi a meno che manchi qualcosa, 'movq $ buffer, (% rdi)' verrà semplicemente sovrascritto dal tuo 'movq $ output,% rdi' alcuni linee più tardi. Posso vedere cosa stai facendo, ma perché usare '% rdi' quando stai andando a copiare' $ buffer' su '% rsi' poche righe dopo comunque? – querist