Ответы пользователя по тегу Assembler
  • Почему не работает ввод?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Иван Четчасов в твоих вопросах повторяется один и тот же паттерн: у тебя что-то не работает, ты приводишь обрывок кода (обычно не относящийся к проблеме) и ничего не говоришь о том, как ты пытался решить проблему.
    Я предлагаю тебе сделать следующее с этим и всеми последующими вопросами:
    - добавить в вопрос ссылку на репозиторий со всем кодом который можно было бы склонировать и собрать
    - добавить в вопрос описание того, как ты запускаешь код, так, чтобы кто угодно мог воспроизвести твои результаты
    - добавить в вопрос описание того, как ты пытался диагностировать и решить проблему

    Без этого создаётся впечатление, что ты просто приходишь сюда покрасоваться.

    В приведённом коде я не вижу никаких проблем.
    Ответ написан
    3 комментария
  • Для чего класть в стек регистр в начале функции?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Конкретно эта последовательность помимо тупо сохранения rbp создаёт разметку кадров стека. Если все функции в цепочке вызовов делают так, то из любой функции можно проследить всю цепочку вызовов до неё зная только текущее значение rbp без какой бы то ни было дополнительной отладочной информации, потому что по адресу в rbp хранится rbp предыдущей функции, а по адресу rbp + 8 -- адрес возврата в предыдущую функцию. Но делать это, конечно же, необязательно. Например gcc вызванный с флагом -fomit-frame-pointer генерирует код без этой последовательности и использует rbp как ещё один регистр общего назначения.

    Почему тогда все регистры не помещаются в стек?

    Потому что есть документ называемый psABI, который определяет, какие регистры должна сохранять вызываемая функция. Например: x86_64 psABI, раздел 3.2.1 "Registers".
    Ответ написан
    Комментировать
  • Почему вычитается 32?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    почему вычитается 32?

    Потому что компилятор использовал стековый кадр для хранения локальных переменных:

    pushq   %rbp
    movq    %rsp, %rbp
    subq    $32, %rsp
    movsd   %xmm0, -24(%rbp)
    movsd   %xmm1, -32(%rbp)

    -- сохранил два аргумента по смещениям -32 и -24

    movsd   -32(%rbp), %xmm0
    subsd   -24(%rbp), %xmm0
    movsd   %xmm0, -8(%rbp)

    -- сохранил их разность по смещению -8

    movsd   .LC0(%rip), %xmm0
    divsd   -8(%rbp), %xmm0
    movsd   %xmm0, -16(%rbp)

    -- сохранил частное от деления MAX_RAND на разность по смещению -16

    4 слота по 8 байт -- 32-байтный стековый кадр.
    Ответ написан
    3 комментария
  • Почему линкер дает такую ошибку?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    relocation R_X86_64_32S against `.text' can not be used when making a shared object
    что делать?

    Переписать код так, чтобы избавиться от этой релокации.
    Для этого посмотреть где она: objdump -dr lib.o

    27:   0f 01 1c 25 00 00 00    lidt   0x0
    2e:   00 
                            2b: R_X86_64_32S        .text


    и переписать загрузку idt без использования константного адреса, например так (используя адресацию относительно pc):
    lea rax, [rel idtDescriptor]
    lidt [rax]


    Однако, я подозреваю, что этого будет недостаточно, потому что
    dq _idt
    -- это ещё одна релокация в текстовом сегменте. Я не вижу как от неё можно избавиться кроме перемещения этой переменной в сегмент .data или .bss и инициализации этой переменной в процессе выполнения программы.
    Ответ написан
    3 комментария
  • Что делать если компилятор nasm работает неправильно?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    выдает непонятную фигню

    Ну в программе нет проверки ввода, поэтому если вводить непонятную фигню, то и выводить она будет непонятную фигню. А если вводить цифры, так чтобы сумма не превышала 9, то приведённая программа прекрасно работает.
    Это, правда не значит, что в этой программе нет ошибок. Я вижу как минимум одну:
    res resb 1 
    …
    mov [res], eax

    классическое переполнение буфера. Её наличие, правда, на результат повлиять не может.
    Ответ написан
    Комментировать
  • Ошибка bin: fatal: more than one input file specified: BootLoader.asm?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    more than one input file specified
    nasm -felf64 bin BootLoader.asm -o BootLoader.bin

    nasm как бы говорит тебе: "выбери, или ты ассемблируешь bin или BootLoader.asm"
    Если же ты хотел формат 'bin', то выкинь -felf64 и замени его на -fbin.
    Тебе, правда, при этом прийдётся добавить что-нибудь типа use64 в исходник, чтобы сказать, что он не 16-битный.
    Ну и к тому же message у тебя лежит перед кодом, в той же секции, хороший bin из этого не получится.
    Ответ написан
  • Что нужно написать, чтобы загрузчик ос передавал управление коду в втором секторе?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Что нужно написать, чтобы загрузчик ос передавал управление коду в втором секторе?

    Нужно написать запрос в гугле: загрузчик ос и потом немного почитать.
    Ответ написан
    Комментировать
  • Почему не работает клавиатура?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    почему-то не работает прерывание 0х20 для клавиатуры

    я не буду отлаживать твой код, но предложу тебе несколько вопросов, которые помогут тебе посмотреть в нужные места:
    - посылает ли клавиатура вообще IRQ?
    - настроен ли контроллер прерываний на приём IRQ от клавиатуры?
    - размаскирована ли линия IRQ от клавиатуры в контроллере прерываний?
    - настроен ли контроллер прерываний на то чтобы вызывать int 0x20 в ответ на IRQ от клавиатуры? [1]
    - получает ли процессор прерывание от контроллера прерываний?
    - настроена ли запись в IDT для int 0x20 на вызов твоего обработчика?
    - разрешены ли прерывания в процессоре?

    [1] Коль скоро здесь ты установил базовый вектор первого PIC в 0x20, то клавиатура, посылая IRQ1, должна вызывать int 0x21.
    Ответ написан
    Комментировать
  • Почему Qemu вылетает?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Я потратил несколько дней на то, чтобы понять в чем дело. Ничего не вышло.

    Эта часть вопроса не даёт нам никакой полезной информации. Рассказывай что делал, а мы попробуем понять, что пошло не так в твоём расследовании.
    Ответ написан
  • Почему не работает печать?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    я на винде только лог qemu могу просматривать

    Иван Четчасов, этого более чем достаточно, чтобы понять, что происходит. По шагам:
    - надо узнать адрес метки printsz
    - найти в логе qemu выполнение кода по этому адресу
    - проследить за тем, какой код выполняется и что оказывается в регистрах
    - понять что не так.
    Ответ написан
    Комментировать
  • Как настроить IDT в защищенном режиме процессора(assembler)?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Я гуглил, но понятного объяснения не нашел.

    Ок, вот первая ссылка из гугла по запросу "x86 idt". Скажи, есть ли что-то на этой странице, что вызывает трудности?

    Или, если тебе больше нравятся оригинальные документы, вот классическая книжка об x86 от интела. Для понимания программирования idt следует прочитать главу 6.5 "Interrupts and exceptions" в первом томе для ознакомления с общей картиной, и главу 6 "Interrupt and exception handling" в третьем томе для понимания деталей.
    Ответ написан
  • Почему ВМ перезагружается?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Я пишу ос и у меня возникла проблема

    Возникла проблема -- отлаживай.
    Разберись, что за адрес у тебя загружается здесь в GDT.

    Вот так это можно пофиксить.
    Ответ написан
  • Почему ядро странно себя ведет?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Я пишу новую операционную систему и столкнулся с непредвиденным поведением ядра

    Обычно в этот момент люди начинают пользоваться отладчиком.

    проблема в файле kernel\kernel.asm

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

    0x00008122:  bb 00 81                 movw     $0x8100, %bx
    0x00008125:  50                       pushw    %ax
    0x00008126:  b8 00 00                 movw     $0, %ax
    0x00008129:  8e c0                    movw     %ax, %es
    0x0000812b:  58                       popw     %ax
    0x0000812c:  cd 13                    int      $0x13

    -- это вызов int 13 из бутлоадера, посмотри на адреса. Вот куда возвращается выполнение после этого int 13:

    0x0000812e:  00 00                    addb     %al, (%bx, %si)
    0x00008130:  00 00                    addb     %al, (%bx, %si)
    0x00008132:  00 00                    addb     %al, (%bx, %si)
    0x00008134:  00 00                    addb     %al, (%bx, %si)
    0x00008136:  00 00                    addb     %al, (%bx, %si)
    0x00008138:  00 00                    addb     %al, (%bx, %si)
    0x0000813a:  00 00                    addb     %al, (%bx, %si)
    0x0000813c:  00 00                    addb     %al, (%bx, %si)
    0x0000813e:  00 00                    addb     %al, (%bx, %si)
    0x00008140:  00 00                    addb     %al, (%bx, %si)
    0x00008142:  00 00                    addb     %al, (%bx, %si)
    0x00008144:  00 00                    addb     %al, (%bx, %si)


    Такие дампы ты можешь получить запуская своё ядро в qemu следующим образом:
    qemu-system-i386 -hda collector.bin -d in_asm,exec,cpu -D log
    Ответ написан
    7 комментариев
  • Как запустить другую программу на NASM-е?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Как из файла ассемблера (NASM) запустить exe-шник?

    Системным вызовом (т.е. вызовом функции ядра ОС, например execve), либо вызовом библиотечной функции, которая сделает этот системный вызов за тебя (например функции библиотеки C system или функции win32 API CreateProcess).

    Не отдельно, а как-будто ассемблерский файл это и есть ос?

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

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    А в чем заключаются эти ошибки, я не могу понять

    Когда ты на С++ пишешь строки подряд, вот так:
    "push edi"  
    "push esi"
    "mov edx,lenS"
    ...

    они склеиваются в одну строку. Когда ассемблер видит команду "push edipush esimov edx, lenS..." он резонно недоумевает.

    как их исправить

    Вставить символы конца строки \n или другие разделители инструкций в ассемблерный код.
    Ты же просил пример кода, вот же он, он компилируется и работает, воспользуйся им. Если непонятно что там написано, задавай вопросы.
    Ответ написан
  • Копирование на fasm с указанием пути?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Предполагаю как-то через ExpandEnvironmentString.
    Но не могу разобраться.

    В чём разобраться, в ExpandEnvironmentStrings? Дай ей на вход свою строку с переменными, буфер куда она запишет строку с подставленными значениями и его размер. Потом этот буфер дай на вход CopyFile.
    Ответ написан
    1 комментарий
  • Как увеличить памяти для переменных и функций ядра на C?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    При достижении или больше определённого количества переменных или функций, перестают работать все string literals в ядре C

    Определённого -- это какого?

    Вот тут
    mov bx, KERNEL_OFFSET ; Read from disk and store in 0x1000
        mov dh, 54 ;31 or 54

    ты 54 сектора ядра загружаешь в память. Есть какая-нибудь корреляция?

    как можно увеличить память для них?

    код ядра ты не привёл, что там ломается можно только догадываться, ну ты понял.
    Ответ написан
  • Почему scanf некорректно работает в FASM?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Функция scanf крушит программу

    Скорее всего ты ошибаешься, и "программу крушит" вот это:
    push numderA
    call [printf]

    printf ожидает первым параметром форматную строку.
    Ответ написан
    6 комментариев
  • У меня программа не выводит числа в консоль, как исправить?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Моя программа … выводит адрес на месте первого числа и букву на месте второго числа.
    как исправить?

    1) посмотреть, какие параметры ожидает функция printf которую ты используешь. Форматная строка для двух целых чисел -- "%d %d".
    2) узнать, как параметры передаются в функцию и что делать после возвращения из неё. Ты используешь push razmer чтобы передать адрес переменной razmer в scanf, но в printf нужно передать не адрес переменной, а её значение. Например так:
    mov eax, [razmer]
    push eax


    Помимо этого в коде есть и другие ошибки: razmer и razmer2 определены как rb 1, а должны бы быть определены как rd 1, поскольку формат %d для scanf приведёт к записи 4 байт. %t -- нет такого формата в scanf, имелся в виду, наверно, %d.
    Ответ написан
    Комментировать
  • Почему не получается деление div на ассемблере в С++?

    jcmvbkbc
    @jcmvbkbc
    http://dilbert.com/strip/1998-08-24
    Почему не получается деление div на ассемблере в С++?
    char b1 = 3, b2, b3 = 1 , res2; //1 байт el, bl, ah    ]]  cbw -> short
      short w1= 1000, w2 = 500, w3 = 2;
    //(w1 - w2) * w3 / b1

    div bl

    Потому что (1000 - 500) * 2 / 3 = 333, а это не влезает в один байт результата, а значит ты получаешь исключение. См.
    Ответ написан
    Комментировать