Ошибка сегментации сборки

Я столкнулся с ошибкой во время выполнения следующего кода сборки

#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

Обнаружена ошибка сегментации в части библиотеки C Calling:call printf. Он работает в режиме x86_64. Что я упустил при компиляции кода x64 в отношении библиотеки c? Или что-то не так с кодом

Спасибо


person Community    schedule 30.11.2009    source источник
comment
может потребоваться увеличить %rdi на соответствующую величину между этими movq   -  person Managu    schedule 30.11.2009
comment
Спасибо всем, я решил проблему. Это была неправильная библиотека, которую я загрузил, работает нормально после того, как я вручную установил ее с помощью /lib/ld-linux-x86-64.so.2 и заменил основную функцию на _start. Я назвал это динамической компоновкой. Извините за плохой английский   -  person    schedule 01.12.2009


Ответы (4)


Вызывается ли инициализация библиотеки времени выполнения C? Это должно быть запущено первым, чтобы настроить стандартный вывод. Кстати, трассировка стека устранит сомнения относительно причины проблемы.

Кроме того, предотвратите переполнение буфера преобразованием %s с помощью %.12s или просто поместите байт NUL после буфера.

person wallyk    schedule 30.11.2009

Вызовы ассемблера для 64-битной fprintf, по-видимому, изменились, поэтому либо свяжите 32-битную библиотеку, либо используйте следующий код:

#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
person xhoch3    schedule 07.07.2011
comment
ваши инструкции movq не увеличивают (%rdi), поэтому, если я что-то не упустил, movq $buffer, (%rdi) просто будет перезаписан вашим movq $output, %rdi через несколько строк. Я понимаю, что вы делаете, но зачем использовать %rdi, если вы все равно собираетесь скопировать $buffer в %rsi несколькими строками позже? - person querist; 13.03.2016

не знаком с ассемблером, поэтому выстрел в темноту: обе ваши строки заканчиваются нулем?

person cobbal    schedule 30.11.2009
comment
.asciz автоматически добавляет завершающий нуль. - person querist; 13.03.2016

Вам нужно завершать нулем строку, которую вы записываете в $buffer, а не писать поверх одного слова три раза. Кроме того, Валлик прав: вы уверены, что ЭЛТ инициализируется?

Честно говоря, гораздо лучше написать эту программу, которая вызывает библиотечную функцию C, на языке C. Напишите код CPUID как встроенный ассемблер внутри функции __cdecl, заставьте ее записать результат в указатель на строку, а затем вызовите эту функцию из программа на Си.

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 );

}
person Crashworks    schedule 30.11.2009