Задать вопрос
Ответы пользователя по тегу Assembler
  • Как link`овать fasm + c(++)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    я починил эту ос, теперь хотел понемногу добавлять C, т.к. на чистом ассемблере далеко не уйдешь. Если получится запустить хоть Hello, World! - буду очень благодарен

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

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

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

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему не работает препроцессорное ветвление в GAS?
    .macro my_macro arg1,arg2
    ...
    .if arg2 == 1


    Нужно добавить \ чтобы gas выполнил макроподстановку: .if \arg2 == 1.
    Ответ написан
    Комментировать
  • Как сделать дальний прыжок при переключении из 16 битного в 32 битный режим?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В отладчике я видел это:

    gdb здесь ожидает увидеть 64-битный код, чтобы он корректно интерпретировал 32-битный код надо ему скомандовать что-то типа set arch i386:x86-64 перед соединением.
    Ответ написан
  • Как скомпоновать код ассемблере с кодом на С для ядра?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Может надо сделать их объектными elf файлами, затем скомпоновать и зачистить формат?

    Использование стандартных форматов и инструументов для работы с ними -- это традиционный способ облегчить себе жизнь. Стандартная связка при использовании gnu-тулчейна -- использовать gcc для компиляции исходников на С (*.c) и ассемблере (*.S), gcc или ld для линковки, objcopy для преобразования ELF-файла с выхода линковщика в бинарник.
    Кроме того, в QEMU можно прямо ELF загружать.
    Ответ написан
    Комментировать
  • Почему не работают цепные команды в ассемблере?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему у меня не хотят работать корректно цепные команды?

    Что конкретно не работает? В формате: "ожидаю X, происходит Y".

    В коде два странных места. Первое:
    mov      ax,Data2
    mov      es,ax     ; запис адреси data2 в ds
    ...
    lea si, node1  ;  <---

    node1 находится в сегменте Data2, адрес которого загружен в es, но команда lodsb загружает данные из ds:si.

    Второе:
    @finish_cycle_namex:
    inc I_struc ;+1 до ітерації
    add si, 5

    Зачем здесь добавлять 5 к si? si указывает на область памяти в которой лежит массив 5-символьных имён, внутренний цикл как раз перемещает si на следующее имя.
    Ответ написан
  • Почему от добавления функций помимо main() в начало кода ядро перестает работать?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему от добавления функций помимо main() в начало кода ядро перестает работать?

    смотри: ты собираешь образ kernel следующей командой:
    i686-elf-ld -Ttext 0x7E00 --oformat binary kernel.o -o kernel -e main

    а запускаешь следующей:
    ; Jump to the kernel's entry point
        JMP 0x0000:0x7E00

    как по-твоему здесь используется информация о точке входа -e main?

    Ответ
    никак, выполнение всегда начинается с начала образа kernel, куда выполняет переход начальный загрузчик; что там будет, то и начнёт выполняться. Эта информация даже никуда не записывается, потому что файл формата binary -- это тупо склеенные вместе загружаемые сегменты, там нет места для метаинформации. Если бы ты собирал ELF, то этот адрес был бы записан в поле e_entry заголовка ELF.

    Если не модифицировать загрузчик, то образ ядра должен начинаться с кода точки входа, в твоём случае -- с кода main(). Чтобы поместить нужный код в нужное место собранного образа обычно используют скрипт линковщика.
    Ответ написан
    Комментировать
  • Как из одного сегмента вызвать функцию другого сегмента?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    // Получаю ошибку:
    7FFF0000: The instruction at 0x7FFF0000 referenced memory at 0x7FFF0000. The memory could not be executed -> 7FFF0000 (exc.code c0000005, tid 6332)

    В чем проблема?

    По видимому в том, что вызвать функцию получилось, но память по адресу 7FFF0000 -- не исполняемая.

    Как починить?

    Начать с того, что сделать память по адресу 7FFF0000 исполняемой. После этого вывод в лог должен заработать, но будет падать после него, потому что функция mySuperFunction не возвращается.
    Ответ написан
  • Error: no multiboot header found при загрузке своей ОС, как исправить?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Нужны подробности сборки. Согласно спецификации заголовок multiboot должен быть в пределах 8192 байт от начала, но если в сборку не подсовывать никаких дополнительных ключей и потом пытаться загружать elf-файл, то в нём multiboot header может оказаться дальше 8К от начала:

    $ gcc -m32 boot.s -nodefaultlibs -nostartfiles -Wl,-Tlinker.ld -no-pie -o boot.elf
    $ readelf -S boot.elf
    There are 8 section headers, starting at offset 0x3140:
    
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            00000000 000000 000000 00      0   0  0
      [ 1] .note.gnu.bu[...] NOTE            00100000 001000 000024 00   A  0   0  4
      [ 2] .multiboot        PROGBITS        00101000 003000 00000c 00      0   0 4096
      [ 3] .text             PROGBITS        00102000 002000 000009 00  AX  0   0 4096
      [ 4] .bss              NOBITS          00103000 003000 004000 00  WA  0   0 4096
      [ 5] .symtab           SYMTAB          00000000 00300c 0000a0 10      6   9  4
      [ 6] .strtab           STRTAB          00000000 0030ac 00004d 00      0   0  1
      [ 7] .shstrtab         STRTAB          00000000 0030f9 000044 00      0   0  1
    Key to Flags:
      W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
      L (link order), O (extra OS processing required), G (group), T (TLS),
      C (compressed), x (unknown), o (OS specific), E (exclude),
      D (mbind), p (processor specific)


    При такой сборке секция .multiboot оказалась по смещению 0x3000.
    Ответ написан
    Комментировать
  • Как включить SVGA VESA режим в x86 GAS?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    movw $0x4F02, %ax
    movb $0x03, %bl
    int $0x10

    в bh остался мусор, а этот вызов принимает аргумент в bx.
    Ответ написан
    Комментировать
  • Как вводить и выводить отрицательные числа turbo assembler?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    возможно, я неправильно использую sf флаг?
    mov al, mas[si]
    cmp ax, ax
    jns positiveOut   ;;;;

    cmp ax, ax сравнивает ax с самим собой, результат немного предсказуем: они равны, т.е. sf = 0, zf = 1. Чтобы узнать знак числа нужно либо сравнивать его с нулём, либо использовать вместо cmp логическую операцию -- test, or или and.

    Кстати, mov al, mas[si] загружает из памяти только al, в ah остаётся мусор от предыдущих операций. По-нормальному после mov нужно сделать знаковое расширение al в ax, если собираешься дальше работать с ax, например так:
    mov al, mas[si]
    cbw


    sub ax, 1                 
    not ax

    Зачем две инструкции, когда есть neg ax?
    Ответ написан
    Комментировать
  • Как написать ассембли код x86 nasm для Linux?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Твой traverse_loop держит указатель на текущую запись в eax, но первый же вызов PrintName портит почти все регистры и не восстанавливает их, поэтому первый же movzx esi, byte [eax + 10h] после этого вызова обращается мимо памяти и вызывает segfault. Проще всего это исправить каким-нибудь pusha / popa вокруг тела PrintName. После этого ты доберёшься до вызова PrintMark, где увидишь, что эта функция ожидает в eax + 10h текстового представления оценки, а у тебя пока есть только двоичное.
    Ответ написан
    Комментировать
  • Не работает код, что не так?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    что не так
    mov ecx, 5 ; Загружает количество гласных

    inc ecx ; Увеличивает счетчик гласных

    loop checkVowels ; Переходит к проверке следующей гласной

    test ecx, ecx ; Проверяет, содержится ли гласная буква в слове

    ты используешь ecx для двух разных целей, и, похоже, не догадываешься об этом. Из цикла поиска гласных ecx выходит со значением 0 если последняя буква слова -- не гласная.
    Ответ написан
    Комментировать
  • Не работает код, что делать?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    ; Вывод суммы элементов выше главной диагонали
        mov ah, 2
        mov dl, cl
        int 21h

    функция 2 прерывания int21h выводит один символ с кодом в dl. Если код суммирования работает верно, это 2 + 3 + 6 = 11. Символ с кодом 11 -- непечатный, и, даже если бы он был печатным, подозреваю, что это не то, что тебе было нужно. В общем случае нужно переводить полученную сумму в строку цифр и эту строку печатать.
    Ответ написан
    8 комментариев
  • Что делает компьютер, когда получает машинную инструкцию поделить на ноль?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что же сделает программа на чистом ассемблере?

    Программа "на чистом ассемблере" всё равно выполняется в каком-то окружении. От этого окружения и зависит, что именно произойдёт. С программой запущенной на x86 в реальном режиме произойдёт одно (прерывание int 0), запущенной под windows -- другое (исключение -> SEH -> завершение программы), запущенной под linux -- третье (но довольно похожее -- исключение -> сигнал -> завершение программы), а запущенной на микроконтроллере с ядром arm -- так и вообще ничего не произойдёт: разделит и глазом не моргнёт, вернёт 0 в качестве результата деления.
    Ответ написан
    Комментировать
  • Как выявить нужные данные из таблицы в отладчике Turbo Assembler при произведении трассировки программы CPU?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    у меня получилось найти только…

    Если ты нашёл машинный код, то его длину ты легко получишь посчитав символы, 6 16-ричных цифр -- это 3 байта. Ну или вычтя из адреса следующей инструкции пдрес текущей.
    Физический адрес в реальном режиме можно посчитать как cs * 10h + ip. В твоём случае получается 48ff9.
    Из твоей записи непонятно, нашёл ты значения регистров или нет, если что, вон они, в среднем окошке в верхнем ряду, а флаги -- в правом.
    Ответ написан
  • Ассемблер, почему дизассемблированном коде много ненужных операций?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему не переписать вместо этого
    add ebx,dword ptr [rbp+ECX*4+10h]

    Буквально так написать нельзя, потому что нет такого режима адресации в котором можно было бы использовать вместе Rbp (64-битный) и Ecx (32-битный). Можно было бы написать add ebx,dword ptr [rbp+rcx*4+10h], но для этого счётчик цикла должен был бы быть 64-битным, а он, как мы видим, 32-битный (int i). Т.е. ответ на вопрос "для чего это": для беззнакового расширения 32-битного счётчика цикла в регистр, который можно использовать для доступа к памяти.

    Другое дело, что из исходного кода очевидно, что при обращениях к памяти i не выходит из диапазона 0..9, так что разницы между ecx и rcx нет и не может быть. Возможно я что-то упускаю и у компилятора другое мнение на этот счёт, но может быть он просто туповат и не имеет кода который бы мог использовать эту возможность оптимизации, а может такая оптимизация и есть, но она не была включена во время генерации этого кода.
    Ответ написан
    Комментировать
  • Пытаюсь собрать прошивку для stm32. Ошибка "src/core_cm3.c: Assembler messages"?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    g++  ...   src/core_cm3.c src/system_stm32f10x.c -o build/main


    src/core_cm3.c: Assembler messages:
    src/core_cm3.c:447: Error: no such instruction: `mrs %eax,psp'


    На какой системе ты выполняешь сборку, на x86? Тогда чтобы получить код для arm тебе нужен не g++, а какой-нибудь arm-linux-gnueabi-g++.
    Ответ написан
    2 комментария
  • Почему не работает загрузчик?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    я так понял, происходит прыжок в никуда?

    Расскажи, как ты это понял?

    почему может не работать?

    Первая ошибка здесь: твой код собран под 0:7c00, но ты загрузил в ds 7c00 вместо нуля.
    Ответ написан
  • Что обозначает инструкция?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    помогите понять инструкцию на MASM:
    mov dx, es:[bx].StartCluster

    Это mov dx, es:[bx + StartCluster], загрузка из базового адреса в регистре + смещения, только в псевдо-С записи. Где-то раньше должна быть определена структура с полем StartCluster, которое используется здесь в качестве смещения.
    Ответ написан
    5 комментариев
  • Что не так с моим кодом assembler?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что не так

    Я не нашёл ответов в доступной документации, за исключением следующей ремарки в описании ключа /AT командной строки:
    Enables tiny-memory-model support.
    Enables error messages for code constructs
    that violate the requirements for .com format files.

    Подозреваю, что assume не может использоваться в masm в исходниках .com, поскольку такие исходники не могут иметь символьных ссылок на сегменты.

    Если вопрос -- "что делать", то ответ -- выкинуть директиву assume из кода.
    Ответ написан