Как точка высокого уровня, я не совсем уверен, почему вы пытаетесь использовать встроенную сборку для простого вызова printf, так как все, что вы сделали, - это создали неверную версию вызова функции (ваш встроенный помещает что-то в стек, но никогда не выталкивает его, что, скорее всего, вызывает проблемы, потому что GCC не знает, что вы изменили указатель стека в середине функции. Это нормально в тривиальном примере, но может привести к очевидные ошибки в более сложной функции)
Вот правильная реализация вашей главной функции:
int encrypt(void)
{
char *text="Hello World";
char *formatString = "%s\n";
// volatile really isn't necessary but I just use it by habit
asm volatile("pushl %0;\n\t"
"pushl %1;\n\t"
"call printf;\n\t"
"addl $0x8, %%esp\n\t"
:
: "r"(text), "r"(formatString)
);
return 0;
}
Что касается вашего последнего вопроса, обычный код операции для RET - "C3", но есть много вариантов, посмотрите на http://pdos.csail.mit.edu/6.828/2009/readings/i386/RET.htm
Ваша идея поиска RET также ошибочна из-за того факта, что когда вы видите байт 0xC3 в случайном наборе инструкций, это НЕ означает, что вы встретили ret. Поскольку 0xC3 может просто представлять собой данные / атрибуты другой инструкции (в качестве примечания, особенно трудно попытаться проанализировать инструкции x86, поскольку вы делаете это из-за того факта, что x86 является архитектурой CISC с длинами команд между 1-16 байтами )
Как еще одно примечание, не все ОС допускают изменение сегмента текста / кода (где хранятся исполняемые инструкции), поэтому код, который вы используете в main, может не работать независимо.