Подтвердить что ты не робот

Вызов функций сборки из c

Я пытаюсь использовать функцию в сборке, вызванную из проекта C. Эта функция должна вызывать функцию libc, скажем printf(), но я продолжаю получать ошибку сегментации.

В .c файле у меня есть объявление функции let say

int do_shit_in_asm()

В файле .asm у меня есть

.extern printf
.section .data
         printtext:
              .ascii "test"
.section .text
.global do_shit_in_asm
.type do_shit_in_asm, @function

do_shit_in_asm:
    pushl %ebp
    movl %esp, %ebp
    push printtext
    call printf
    movl %ebp, %esp
    pop %ebp
ret

Любые <забавные > указатели будут оценены.

as func.asm -o func.o

gcc prog.c func.o -o prog
4b9b3361

Ответ 1

Измените push printtext на push $printtext.

Как бы то ни было, вы загружаете значение из адреса printtext и нажимаете это, а не нажимаете адрес. Таким образом, вы передаете 'test' как 32-битное число, а не указатель, а printf пытается интерпретировать это как адрес и сбой.

Ответ 2

Один из лучших способов начать работу с функциями языка ассемблера - написать аналогичную функцию в C, а затем создать его с помощью компилятора, который генерирует список сборок (-S on gcc). Затем вы можете изучить вывод того, что сделал компилятор, и изменить по мере необходимости.

Это особенно полезно, если вы вызываете такие функции, как printf, которые используют другое соглашение о вызове (из-за переменного количества аргументов). Вызов этих функций может сильно отличаться от вызова функций, отличных от varargs.

Ответ 3

проблема заключалась в том, что я использовал

pushl printtext

скорее, чем

pushl $printtext

Спасибо всем за вашу помощь и жаль тратить ваше время: P

Ответ 4

После этого:

push printtext
call printf

Вы хотите:

addl $4, %esp

Дальнейшее объяснение:

Поскольку вы используете x86 Linux, я предполагаю, что для вызывающего соглашения требуется, чтобы вызывающий вызывал очистку параметров. Поскольку вы нажали указатель перед вызовом printf, ваш стек отключен на 4 после выполнения этой команды ret.

Update:

Да, хорошо, я привык к синтаксису Intel, поэтому я получил порядок аргументов в голове. На самом деле отсутствие addl back to esp не имеет значения, потому что вы правильно восстанавливаете esp рядом с вашим ret. Моя следующая догадка заключается в том, что строка, передаваемая в printf, не имеет нулевого ограничителя... Позвольте мне увидеть, что gas делает...

Обновление 2:

ОК, gas null завершает строки для вас, поэтому, я думаю, моя вторая догадка была неправильной. Похоже, вы нашли проблему, так что вопрос спорный.