Я подозреваю, что вы могли бы написать такую вещь, но в конце должен был бы быть бесконечный цикл, потому что вы не можете попросить операционную систему выйти из вашего процесса. И ты не мог сделать ничего полезного.
Хорошо начните с компиляции программы ELF, изучите спецификацию ELF и соберите вместе заголовок, сегменты программы и другие части, необходимые для программы. Ядро загрузит ваш код и перейдет на некоторый начальный адрес. Вы могли бы поставить бесконечный цикл там. Но без знания ассемблера это все равно безнадежно с самого начала.
Файл start.S
, используемый glibc, может быть полезен в качестве начальной точки. Попробуйте изменить его так, чтобы вы могли собрать из него автономный исполняемый файл. Этот файл start.S является точкой входа всех приложений ELF и вызывает __libc_start_main
, что, в свою очередь, вызывает main
. Вы просто измените его так, чтобы он соответствовал вашим потребностям.
Хорошо, это было теоретически. Но теперь, какое практическое применение это имеет?
Ответ на обновленный вопрос
Хорошо. Существует библиотека под названием libgloss
, которая обеспечивает минимальный интерфейс для программ, предназначенных для работы во встроенных системах. Библиотека newlib
C использует ее в качестве интерфейса системных вызовов. Общая идея заключается в том, что libgloss - это слой между библиотекой C и операционной системой. Таким образом, он также содержит файлы запуска, в которые загружается операционная система. Обе эти библиотеки являются частью проекта GNU binutils. Я использовал их для создания интерфейса для другой ОС и другого процессора, но, похоже, нет порта libgloss для Linux, поэтому, если вы вызываете системные вызовы, вам придется делать это самостоятельно, как уже заявили другие .
Абсолютно возможно писать программы на языке программирования Си. ядро Linux является хорошим примером такой программы. Но также возможны пользовательские программы. Но минимально требуется библиотека времени выполнения (если вы хотите сделать что-то серьезное). Такой содержит действительно базовые функции, такие как memcpy, базовые макросы и так далее. Стандарт C имеет специальный режим соответствия, называемый freestanding , для которого требуется только очень ограниченный набор функций, подходящий также для ядер. На самом деле, у меня нет понятия о ассемблере x86, но я попытал счастья для очень простой программы на C:
/* gcc -nostdlib start.c */
int main(int, char**, char**);
void _start(int args)
{
/* we do not care about arguments for main. start.S in
* glibc documents how the kernel passes them though.
*/
int c = main(0,0,0);
/* do the system-call for exit. */
asm("movl %0,%%ebx\n" /* first argument */
"movl $1,%%eax\n" /* syscall 1 */
"int $0x80" /* fire interrupt */
: : "r"(c) :"%eax", "%ebx");
}
int main(int argc, char** argv, char** env) {
/* yeah here we can do some stuff */
return 42;
}
Мы счастливы, он на самом деле компилируется и запускается:)