Проблема со сборкой проекта бутлоадера на C++ и ASM с CMAKE

Тема в разделе "WASM.BEGINNERS", создана пользователем Aoizora, 24 июл 2023.

Метки:
  1. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    362
    Пишу загрузчик ОС, пользуясь современными системами сборки типа cmake, но столкнулся с проблемой линковки ассемблерных файлов. Они не линкуются вообще. Посмотрите, пожалуйста, и подскажите, что не так в проекте? Почему он не собирается?

    https://gitflic.ru/project/aoizora/operating-systems

    Немного кода:


    Код (Text):
    1. cmake_minimum_required(VERSION 3.5)
    2.  
    3. set(LINKER_SCRIPT "linker.ld")
    4.  
    5. add_executable(boot string.cpp display.cpp start.asm)
    6.  
    7. set_target_properties(boot PROPERTIES
    8.     CXX_STANDARD 17
    9.     CXX_STANDARD_REQUIRED ON
    10. )
    11.  
    12. set_target_properties(boot PROPERTIES
    13.     LINK_DEPENDS ${LINKER_SCRIPT}
    14. )
    15.  
    16. target_include_directories(boot PRIVATE
    17.     ${CMAKE_CURRENT_SOURCE_DIR}/../include
    18. )
    19.  

    Код (ASM):
    1. .code16
    2. .text
    3. .global start
    4.  
    5. start:
    6.     ljmp 0x00, $real_start
    7.  
    8. real_start:
    9.     xor ax, ax
    10.     movw ax, ds
    11.     movw ax, ss
    12.     movw $0x7C00, %sp
    13.     addw $0x0400, %sp
    14.  
    15. loop: jmp loop
    16.  
    --- Сообщение объединено, 24 июл 2023 ---
    Ошибка странная

    :-1: error: No rule to make target 'linker.ld', needed by 'src/boot'. Stop.
    --- Сообщение объединено, 24 июл 2023 ---
    Перед этим:

    start.asm: linker input file unused because linking not done
     
  2. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.242
    можно простенько..
    Код (Text):
    1. SOURCES = $(wildcard ./*.cpp)
    2. objs:
    3.     $(CC) $(extraFlags) $(CFLAGS) -o $(SOURCES:.cpp=.o) -c $(SOURCES)
    4. final:
    5.     $(CC) $(LIBS) -o $(bin_name) $(SOURCES:.cpp=.o) $(LDFLAGS)
    bash > make clean; make objs; make final
     
  3. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    362
    Мне уже хочется разобраться со сборкой в симейке, т.к. это и для работы пригодится
    Руками бинарь из обжектов собирается, а симейком - нет
    --- Сообщение объединено, 25 июл 2023 ---
    :-1: error: /usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../../lib/libgcc_s.so.1: error adding symbols: file in wrong format
     
  4. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.242
    что за дистра?? а гцц 13?? вообще, сборщик можешь на питохе прописать.. более унифицированный подход получается :)
     
  5. alex_dz

    alex_dz Active Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    410
    CMake supports assembler out of the box. Just be sure to enable the "ASM" language in your project. If an assembler source file needs preprocessing, also set the source file's compilation options:

    Код (Text):
    1. project(assembler C ASM)
    2. set_property(SOURCE foo.s APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp")
    3. add_executable(hello foo.s bar.c)
     
  6. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.242
    по идее, симейк тут ни при чём - симейк/мейк просто скрипты сборки, а поддержка асма зависит от компиля. гцц же действительно поддерживает асм из коробки.
     
  7. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    362
    Arch Linux
    Да, gcc (GCC) 13.1.1 20230714
    Мой linker script такой: https://gitflic.ru/project/aoizora/operating-systems/blob?file=src/linker.ld&branch=master

    Может, я в форматах что-то напутал? Может, дело в том, что компилировать надо 16-битный код? Как это сделать симейком?
     
    Последнее редактирование: 25 июл 2023
  8. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.242
    я мейкфайл пользую и/ль питоху.
    так ты ручками РАБОЧИЙ бинарь собрал?
    а зачем тебе вообще 16-бит??? Ты кроссплатформу компилишь?
    арч для дэва - очень плохой выбор: он типОо самое новое тянет и будешь постоянно славливать всяку хрень - лучше бери убунту иль опенсьюз (opensuse) аль дэбю (дэбиан).
     
  9. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    362
    Я так собираю руками. В корневом каталоге выполняю:

    as src/boot.s -o build/boot.o
    gcc -c src/string.cpp -I include -o build/string.o
    gcc -c src/display.cpp -I include -o build/display.o

    В папке build получилось три объектника. Линкую их вместе:

    ld build/*.o -Tsrc/linker.ld -o build/loader

    Получился бинарник размером 776 байт. Странно, должен получиться бинарник размером 512 байт, который надо будет записать в загрузочный сектор.

    Но тут внезапно:

    objdump -D build/loader
    objdump: build/loader: формат файла не распознан
    --- Сообщение объединено, 25 июл 2023 ---
    Вот такая шляпа получается при линковке руками. Конец загрузочного сектора обозначен магическими числами 55 aa. После них идет какая-то хрень
    --- Сообщение объединено, 25 июл 2023 ---
    Собрал проект таким образом

    gcc -c -ffreestanding -fno-pie -m16 src/display.cpp -I include -o build/display.o
    ❯ gcc -c -ffreestanding -fno-pie -m16 src/string.cpp -I include -o build/string.o
    ❯ ld build/boot.o build/display.o -Tsrc/linker.ld --oformat binary -o build/loader

    Получился бинарник меньше размером - 652, но это все еще не 512 байт
    --- Сообщение объединено, 26 июл 2023 ---
    Как на встроенном в GCC C++ GNU ассемблере использовать параметры функции? Что-то типа:

    void foo(int arg) {
    __asm {
    mov eax, arg
    }
    }
     

    Вложения:

    • 0.png
      0.png
      Размер файла:
      52,3 КБ
      Просмотров:
      125
  10. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.242
    там несколько извратно это выглядит https://blog.alex.balgavy.eu/a-practical-guide-to-gcc-inline-assembly/ :)
    проблема в экзотичности твоего бинаря - это тебе надо рыть в сторону легаси а-ля https://en.wikipedia.org/wiki/Embeddable_Linux_Kernel_Subset
     
  11. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    362
    Как в C++ отключить манглинг имен, чтобы вместо _Z10KernelMainv было просто KernelMain? У меня из-за манглинга ошибка линковки.
     

    Вложения:

    • 0.png
      0.png
      Размер файла:
      31,5 КБ
      Просмотров:
      117
  12. alex_dz

    alex_dz Active Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    410
    extern "C"
     
  13. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    362
    Как одним словом называть файлы на ассемблере в ядре ос, в которых реализованы утилитные функции типа очистки экрана и которые работают через прерывания?
     
  14. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    362
    Чем отлаживать свое ядро ОС? GDB + qemu это умеют? Есть статьи о том, как это делается?
     
  15. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    998
    ключи при запуске кему -s -S и потом завешиваешься на порт уже из где-то в сторонке запущенной gdb командой target remote айпиадресс:порт это позволит смотреть на процесс запуска оси после граба (точнее не так, на паузу машина встанет перед чтением мбр-раздела вроде). Если нужно на взамиодействие биоса с осью, то там сложнее процесс.
     
  16. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.242
    если ладишь многопоточку - от гдб особого прока нет, надо логи делать.
     
  17. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    362
    Хочу написать свое ядро ОС, Вот код boot.asm:


    Код (Text):
    1. FLAGS equ 0
    2. MAGIC equ 0x1BADB002
    3. CHECKSUM equ -(MAGIC + FLAGS)
    4.  
    5. section .multiboot
    6. align 4
    7.     dd MAGIC
    8.     dd FLAGS
    9.     dd CHECKSUM
    10.  
    11. section .bss
    12. align 16
    13. stack_bottom:
    14. resb 16384
    15. stack_top:
    16.  
    17. global start
    18. extern KernelMain
    19.  
    20. section .text
    21. start:
    22.     mov rsp, stack_top
    23.     push rbx
    24.     call KernelMain
    25.     cli
    26. .hang: hlt
    27.     jmp .hang
    28. .end:

    kernel.cpp

    Код (Text):
    1. #include <stddef.h>
    2.  
    3. extern "C" void KernelMain() {
    4.     const char str[] = "H\x0F""e\x0Fl\x0Fl\x0Fo\x0F \x0Fw\x0Fo\x0Fr\x0Fl\x0F""d\x0F";
    5.     char* buf = (char*) 0xB8000;
    6.     char c;
    7.     for(size_t i = 0; c = str[i]; i++) {
    8.         buf[i] = str[i];
    9.     }
    10.     while(1);
    11. }
    Файл для линкера:

    Код (Text):
    1. ENTRY(start)
    2.  
    3. SECTIONS
    4. {
    5.     . = 1M;
    6.  
    7.     .text BLOCK(4K) : ALIGN(4K)
    8.     {
    9.         *(.multiboot)
    10.         *(.text)
    11.     }
    12.  
    13.     .rodata BLOCK(4K) : ALIGN(4K)
    14.     {
    15.         *(.rodata)
    16.     }
    17.  
    18.     .data BLOCK(4K) : ALIGN(4K)
    19.     {
    20.         *(.data)
    21.     }
    22.  
    23.     .bss BLOCK(4K) : ALIGN(4K)
    24.     {
    25.         *(COMMON)
    26.         *(.bss)
    27.     }
    28. }
    Собираю проект так:

    Компиляция boot.asm:
    nasm src/boot.asm -f elf64 -o build/boot.o

    Компиляция kernel.cpp:
    gcc -c -ffreestanding src/kernel.cpp -o build/kernel.o

    Линковка:
    ld build/boot.o build/kernel.o -T src/linker.ld -n -o build/kernel

    Получается исполняемый файл kernel. Собираю загрузочный образ. Для этого создал папки isofiles/boot/grub. Внутри isofiles/boot/grub создал grub.cfg:

    Код (Text):
    1. set default=0
    2. set timeout=0
    3.  
    4. menuentry "my kernel" {
    5.     multiboot /boot/kernel
    6.     boot
    7. }
    Ядро поместил в isofiles/boot
    Собираю образ так: grub-mkrescue -o os.iso isofiles

    После этого пытаюсь загрузить ядро в qemu: qemu-system-x86_64 -cdrom os.iso
    И ничего не выводится на экран. QEMU зависает в бесконечных попытках загрузить ядро. Как собрать ядро так, чтобы все заработало?
    --- Сообщение объединено, 30 июл 2023 ---
    Как правильно выполнить эту часть? https://habr.com/ru/articles/343690/

    Точка монтирования - это мы создаем папку в /mnt, типа /mnt/os, и при помощи команды mount монтируем?
     
  18. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.242
  19. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    998
    В кему стартовать ядро ключ кернел. Лосетап - создание блочного устройства. Это может быть полезно только для создания внутри файла файловой системы типа ехт3. Для кему можно с ключем хдд монтировать сразу имг.файл.
     
  20. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.242
    проблема скорей всего не в кему - ТС должен исходить из эталонных моделей а-ля дос древний и елкс, в сущности ничего и выдумывать не надо (достаточно уже имеющиеся решения адаптировать к своим потребам).