Почему я получаю ошибку:
Ошибка сегментации (дамп ядра)
Вот код сборки:
.intel_syntax noprefix
.data
message: .asciz "Hello World!\n"
.text
.global main
main:
lea rdi, message
call printf
ret
Почему я получаю ошибку:
Ошибка сегментации (дамп ядра)
Вот код сборки:
.intel_syntax noprefix
.data
message: .asciz "Hello World!\n"
.text
.global main
main:
lea rdi, message
call printf
ret
System V ABI требует, чтобы вы выровняли свой стек по 16 байтам, прежде чем вызывать функцию. Чтобы упростить задачу, ABI гарантирует, что при входе в функцию, если вы подставите указатель стека на 8 * n (n — нечетное число), ваш стек будет выровнен по 16 байтам.
Если вы не будете следовать этому соглашению о вызовах, другие библиотеки могут рухнуть, потому что они не смогут правильно выровнять свой кадр стека, если им нужно использовать инструкции, требующие специального выравнивания, такие как, например, movdqa
.
ammarfaizi2@integral:/tmp/test_asm$ cat test.S
.intel_syntax noprefix
.data
message: .asciz "Hello World!\n"
.text
.global main
main:
sub rsp, 8
xor eax, eax
lea rdi, [rip + message]
call printf
add rsp, 8
ret
ammarfaizi2@integral:/tmp/test_asm$ gcc test.S -o test
ammarfaizi2@integral:/tmp/test_asm$ ./test
Hello World!
ammarfaizi2@integral:/tmp/test_asm$
Если вы call
выполняете функцию, а следующее, что вы делаете, это ret
, вы можете упростить код с помощью хвостового вызова. Он использует jmp
для вызываемой целевой функции. Убедитесь, что вы отменили текущий кадр стека функций перед переходом, если вы настроили его раньше.
Для поддержки PIE и PIC рассмотрите возможность использования относительной адресации RIP для доступа к статическому хранилищу. Это также повышает безопасность. Компиляторы в наши дни обычно компилируют цель в PIE по умолчанию.
Эта часть является примером доступа к статическому хранилищу с относительной адресацией RIP:
lea rdi, [rip + message]
ammarfaizi2@integral:/tmp/test_asm$ cat test.S
.intel_syntax noprefix
.data
message: .asciz "Hello World!\n"
.text
.global main
main:
xor eax, eax
lea rdi, [rip + message]
jmp printf
ammarfaizi2@integral:/tmp/test_asm$ gcc test.S -o test
ammarfaizi2@integral:/tmp/test_asm$ ./test
Hello World!
ammarfaizi2@integral:/tmp/test_asm$
Добавлено xor eax, eax
для безопасности. См.: ошибки сегментации glibc scanf при вызове из функции, которая не выравнивает RSP
lea
на lea rdi, [rip + message]
, чтобы разрешить создание исполняемого файла PIE (в противном случае возникнет ошибка перемещения). Другим решением было бы указать GCC создать EX ELF с --static
(PIE — это SH ELF с непереопределяемыми символами).
- person Margaret Bloom; 17.04.2021
movaps
хранилищ. (Текущий GCC и, следовательно, текущие сборки libc, просто отметьте 0 / не-0, чтобы условно запускать все 8 или нет, поэтому нарушение ABI, связанное с возможным наличием AL > 8, на практике не вызывает проблем.) В любом случае, вы должны использовать xor eax, eax
. Или используйте puts
, который не является вариативным.
- person Peter Cordes; 18.04.2021
xor al, al
вместо xor eax, eax
?
- person Ammar Faizi; 18.04.2021
xor al,al
не используется в качестве идиомы обнуления на большинстве процессоров, поэтому mov al,0
на некоторых будет лучше. Но все же хуже, чем xor eax,eax
.
- person Peter Cordes; 19.04.2021