2009-11-30 14 views
5

traf ich einen Fehler bei derAssembly Segmentation Fault

der folgenden Assembly-Code ausgeführt wird
#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 

Es Segmentierungsfehler in dem Teil der C-Bibliothek Berufung begegnet: Aufruf printf Es in x86_64-Modus ausgeführt wird. Alles, was ich beim Kompilieren von x64-Code in Bezug auf die C-Bibliothek verpasst habe? Oder gibt es etwas falsch mit dem Code

Dank

+2

möchten% rdi um einen entsprechenden Betrag erhöhen, zwischen denen – Managu

+1

des movq Dank jeder, ich habe das Problem gelöst. Es war die falsche lib, die ich geladen habe funktioniert gut, nachdem ich es manuell mit /lib/ld-linux-x86-64.so.2 und ich ersetzte die Hauptfunktion mit _start. I ld es als dynamische Verknüpfung. Sorry für das schlechte Englisch –

Antwort

0

nicht vertraut mit Montage, so dass ein Schuss im Dunkeln: beide Saiten Nullterminiert?

+0

'.asciz' fügt automatisch die abschließende Null hinzu. – querist

4

Wird die Initialisierung der C-Laufzeitbibliothek aufgerufen? Das muss zuerst laufen, damit stdout eingerichtet wird. Übrigens würde ein Stack-Trace Zweifel an der Ursache des Problems beseitigen.

Verhindern Sie auch, dass die% s-Konvertierung den Puffer mit% .12s überläuft oder legen Sie einfach ein NUL-Byte nach dem Puffer ab.

0

Sie müssen die Zeichenfolge, die Sie in $ buffer schreiben, null-terminieren, anstatt dreimal auf ein Wort schreiben zu müssen. Außerdem hat Wallyk Recht: Sind Sie sicher, dass der CRT initialisiert wird?

Ehrlich gesagt, Sie sind wirklich viel besser dran, dieses Programm zu schreiben, das eine C-Bibliotheksfunktion in C aufruft. Schreiben Sie den CPUID-Code als Inline-Assembly innerhalb einer __cdecl-Funktion, schreiben Sie sein Ergebnis in einen String-Zeiger und dann Rufen Sie diese Funktion von einem C-Programm auf.

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

Die Assembler-Anrufe für 64-Bit-fprintf sind scheinbar verändert, also entweder verknüpfen Sie die 32-Bit-Bibliothek oder verwenden Sie folgenden Code:

#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

Ihre movq-Anweisungen inkrementieren '(% rdi)' nicht, so dass 'movq $ buffer, (% rdi)' einfach durch Ihre 'movq $ -Ausgabe,% rdi' überschrieben wird Zeilen später. Ich kann sehen, was Sie tun, aber warum "% rdi" verwenden, wenn Sie nur ein paar Zeilen später '$ buffer' in'% rsi' kopieren wollen? – querist