Сделать простой CRT0 на C или ассемблере

Я вернулся к C/C++ и ASM и хочу немного поиграть с огнем. Я обнаружил, что когда вы компилируете и компонуете код в исполняемый файл для Windows, он динамически компонуется с некоторыми библиотеками, которые должны существовать на любом компьютере, где ожидается запуск этого приложения. Вы можете указать компилятору не связываться с ними и создавать для этого свои собственные библиотеки.

Кроме того (и, пожалуйста, поправьте меня, если я ошибаюсь во всем, что я здесь говорю) есть объектный файл, который всегда скомпилирован и связан с основным кодом нашего приложения. Это файл crt0.o (среда выполнения C), и, как я знаю, он подготавливает стек, получает argc и argv и вызывает основную функцию (и, возможно, другие вещи). Я также считаю, что это первый фрагмент кода, вызываемый системой при выполнении приложения.

Итак, я пытаюсь создать простой crt0.obj и связать его с простым объектным файлом С++.

int main(int argc, char** argv) {
    return 0; 
}

Я использую GCC и не хочу использовать стандартную библиотеку, поэтому моя команда выглядит так:

g++ -s -nostartfiles -nodefaultlibs -nostdlib testapp.cpp -o test.exe crt0.o

Я предполагаю, что директива -nostartfiles говорит компоновщику не встраивать файл crt0.o по умолчанию, поэтому он ожидает, что я дам каждое определение для любой функции и обработаю запуск приложения. Я немного смущен здесь.

В любом случае, я хочу создать очень простой объектный файл crt0, которого будет достаточно, чтобы GCC создал мой исполняемый файл и чтобы система его запустила. Я знаю, что в Интернете есть много файлов кода (C и ASM), но я хочу написать свой собственный, чтобы узнать, как он работает. Мне нужен не только код, но и небольшая помощь в том, что он должен делать и как компилировать/связывать, чтобы добиться этого. Если вы знаете какую-либо полезную ссылку, которая также очень ценится.

Мои сомнения:
1. Как компилятор/ссылка создает окончательный файл из моего кода и среды выполнения C? Должен ли я вызывать основную функцию из crt0.o (используя директиву extern)? Когда я выполняю g++ -s -nostartfiles -nodefaultlibs -nostdlib testapp.cpp -o test.exe, я получаю ошибку "*неопределенная ссылка на __main*". Определена ли основная функция в файле crt0.o? Странно, что если я меняю int main на int start, я не получаю никакой ошибки. Что это значит?
2. Какие основные операции должен содержать crt0 (например, получение аргументов командной строки, вызов main)?
3. Мой файл кода - CPP, а crt0 - это часть сборки внутри файла C (скомпилированного с помощью GCC). Я опубликую некоторый «франкенкод», который мне удалось создать из найденных и частично понятых фрагментов:

// crt0.c
__asm(".section .text\n" 
".global _start\n"
"_start:\n"
"mov $0, %ebp\n"
"push %ebp\n"
"mov %esp, %ebp\n"
"push %esi\n"
"push %edi\n"
"call _init\n"
"pop %edi\n"
"pop %esi\n"
"call main\n"
"movl %eax, %edi\n"
"call exit\n"
".section .init\n"
".global _init\n"
"_init:\n"
"push %ebp\n"
"mov %esp, %ebp\n"
".section .fini\n"
".global _fini\n"
"_fini:\n"
"push %ebp\n"
"mov %esp, %ebp\n");

4.) Итак, в этом файле я сделал несколько вызовов функций инициализации. Уже созданы функции init и fini (выглядят как простые конструкторы и деструкторы, не знаю) Еще есть функция main, которая не знаю как связана с основной функцией .cpp. Я имею в виду, я должен импортировать его? Я получаю undefined reference ошибок как для основной функции, так и для функции выхода.
5.) Должен ли c0 иметь определенный формат или содержать определенную функцию, чтобы система нашла ее запуск?

Ну, я не вижу ничего сложного в том, чтобы сделать маленький crt0 и заставить компилятор прикрепить его к исполняемому файлу, но есть некоторые вещи, которые я не могу правильно увидеть. Я надеюсь, что кто-то может помочь мне собрать все это вместе. Спасибо


person ali    schedule 23.02.2013    source источник
comment
Какова ваша ДЕЙСТВИТЕЛЬНАЯ цель здесь?   -  person Mats Petersson    schedule 23.02.2013
comment
Создайте простой crt0 в C, свяжите его с файлом C++ и заставьте этот файл работать только с ним.   -  person ali    schedule 23.02.2013
comment
Да, но вы, например, ожидаете, что сможете сделать cout << "hello world!\n", вызвать rand(), вызвать new/delete или использовать объекты со статической продолжительностью хранения и т. д. и т. д.? Это все вещи, которые готовятся во время запуска.   -  person Mats Petersson    schedule 23.02.2013
comment
Нет, только для того, чтобы иметь возможность запускать основную функцию, ничего больше.   -  person ali    schedule 23.02.2013
comment
Так что все, что вам действительно нужно сделать, это позвонить main из _start:. Предполагая, что вам не нужны argc и argv, которые также входят в список вещей, настроенных CRT0.   -  person Mats Petersson    schedule 23.02.2013
comment
Да. Я могу добавить больше функций инициализации перед main позже, но сейчас я просто хочу увидеть, что я могу создать простую функцию int main() и мне не нужны никакие библиотеки или прочее, кроме моего маленького crt0   -  person ali    schedule 23.02.2013
comment
Вы можете заглянуть на microsoft.com/msj/archive/S569.aspx, msdn.microsoft.com/library/bb985746.aspx и benshoof.org/blog/minicrt.   -  person Matteo Italia    schedule 23.02.2013


Ответы (1)


У меня нет компьютера с Windows для тестирования, но это должны быть основные биты, которые вам нужны:

#// crt0.c
__asm(".section .text\n" 
".global _start\n"
"_start:\n"
"mov $0, %ebp\n"
"push %ebp\n"
"mov %esp, %ebp\n"
"call main\n"
"pop  %ebp\n"
"ret\n");

Редактировать: пусто __main:

__asm(".global __main\n"
      "__main:\n" 
      "ret\n");
person Mats Petersson    schedule 23.02.2013
comment
Да, но я получаю неопределенную ссылку на __main, когда компилирую cpp, содержащий основную функцию. Итак, я не знаю, как заставить компилятор знать, где найти main, который я вызываю из этого кода. - person ali; 23.02.2013
comment
Если вы разберете свой main.o, он случайно не вызовет __main? Я думаю, что MingW делает это для вызова некоторых конструкторов и тому подобного. В этом случае вам придется добавить код, который я отредактировал выше [код в комментариях превращается в кашу...] - person Mats Petersson; 23.02.2013