Как связать код на FASM с программами на C или C++?

У gcc существует возможность использования .ld файлов для линковки. Я пишу на fasm и не использую gas, поэтому хотел бы узнать, возможно ли применять эту линковку вместе с C (или C++, если это возможно). Существуют ли аналогичные методы линковки для данной ситуации?
  • 7 февраля 2025 г. 21:44
Ответы на вопрос 2
Связывание кода на FASM (Flat Assembler) с программами на C или C++ возможно, и для этого вам не обязательно использовать `ld` или `gas`. Вместо этого вы можете использовать встроенные механизмы компилятора, которые позволяют линковать ассемблерный код с C или C++ кодом. Вот шаги, чтобы реализовать это:

### 1. Создание ассемблерного модуля на FASM

Создайте файл, например `asm_code.asm`, где будет ваш ассемблерный код. Например:

```asm
; asm_code.asm
global my_function  ; Экспорт функции для использования в C/C++
section .text
my_function:
    ; Пример кода
    ret
```

### 2. Подготовка C/C++ кода

Создайте файл, например `main.c`, где вы будете использовать вашу ассемблерную функцию:

```c
extern void my_function();  // Объявляем ассемблерную функцию

int main() {
    my_function();          // Вызываем ассемблерную функцию
    return 0;
}
```

### 3. Компиляция и линковка

Теперь вам нужно скомпилировать и слинковать оба файла. Важно следовать правильному порядку компиляции:

1. Сначала скомпилируйте ваш C файл в объектный файл:

```bash
gcc -c main.c -o main.o
```

2. Затем, скомпилируйте ваш ассемблерный файл:

```bash
fasm asm_code.asm asm_code.o
```

3. Наконец, линкуйте оба объектных файла:

```bash
gcc main.o asm_code.o -o my_program
```

### 4. Использование C++

Если вы работаете с C++, то аналогично: объявите ассемблерную функцию в вашем C++ коде, как если бы вы делали это в C:

```cpp
extern "C" void my_function();  // Объявляем ассемблерную функцию

int main() {
    my_function();              // Вызываем ассемблерную функцию
    return 0;
}
```

### Дополнительные советы

- Убедитесь, что вы правильно определяете соглашения о вызовах (calling conventions). В большинстве случаев, функции C и C++ используют `cdecl`, что означает, что функция должна возвращать управление вызывающей функции.
- Убедитесь, что переменные и параметры передаются правильно между C/C++ и ассемблером. Имейте в виду, что вы можете использовать глобальные переменные для обмена данными.
- Если вы работаете с C++, учитывайте возможные изменения в именах функций (name mangling). Использование `extern "C"` помогает избежать этого.

### Заключение

Таким образом, вы можете успешно связывать код на FASM с C/C++, используя стандартные инструменты компиляции и линковки. Убедитесь, что вы тестируете интеграцию, чтобы избежать неожиданных сбоев при вызовах функций.
я починил эту ос, теперь хотел понемногу добавлять C, т.к. на чистом ассемблере далеко не уйдешь. Если получится запустить хоть Hello, World! - буду очень благодарен

Я положил эту ос на github и приделал к ней Makefile и hello world на C: https://github.com/jcmvbkbc/minios
Потестировать можно набрав make run и введя команду hello в консоли внутри qemu.

Я, однако, не стал интегрировать этот код на С с кодом на ассемблере. Потому что у кода на ассемблере есть пара проблем:
- код на ассемблере хардкодит координаты бинарников на диске, загружает их в фиксированные адреса в памяти и переходит прямо на них. Это стрёмная практика, я не стану её поощрять.
- этот код 16-битный, для реального режима, можно, конечно, растить его дальше, но куда практичнее было бы переключиться в нормальный защищённый режим, 32- или 64-битный, что одно, что другое не так уж сложно.

Иными словами, в ответ на вопрос из топика "Как link`овать fasm + c(++)?" скажу, что в данном случае линковать, в смысле используемом в контексте компиляторов, не имеет смысла.
Похожие вопросы