Ответы пользователя по тегу Assembler
  • Nasm - почему не загружается более одного сектора диска?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Загрузчик нормально работает при загрузке 1 сектора

    Вот я собрал твой загрузчик, записал его в бут-сектор, добил двумя секторами мусора и загрузил с такого диска qemu. Выглядит так, будто бы всё работает:
    $ nasm test.s -o test
    $ head -c 2b /dev/urandom >> test
    $ hexdump -Cv test | tail -n2
    000005f0  49 93 ad 56 25 97 25 82  61 1d d9 a1 66 2a cb 19  |I..V%.%.a...f*..|
    00000600
    $ qemu-system-i386 -hda test -gdb tcp::1235 -S

    В другом терминале, см этот ответ на вопрос "как в gdb посмотреть 16-битный код выполняющийся в qemu":
    $ wget https://gist.githubusercontent.com/MatanShahar/1441433e19637cf1bb46b1aa38a90815/raw/2687fb5daf60cf6aa8435efc8450d89f1ccf2205/target.xml


    Далее в том же терминале:
    $ gdb
    (gdb) set tdesc filename target.xml
    warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
    of GDB.  Attempting to continue with the default i8086 settings.
    
    (gdb) target remote :1235
    (gdb) set disassembly-flavor intel
    (gdb) b *0x7c32
    Breakpoint 2 at 0x7c32
    (gdb) c
    Continuing.
    
    Breakpoint 2, 0x00007c32 in ?? ()
    (gdb) x/2i $pc
    => 0x7c32:      int    0x13
       0x7c34:      jb     0x7c3e

    -- тут я остановился прямо перед командой чтения. Дальше:
    (gdb) tb *0x7c34
    Temporary breakpoint 3 at 0x7c34
    (gdb) c
    Continuing.
    
    Temporary breakpoint 3, 0x00007c34 in ?? ()
    (gdb) x/16x 0x13f0
    0x13f0: 0x49    0x93    0xad    0x56    0x25    0x97    0x25    0x82
    0x13f8: 0x61    0x1d    0xd9    0xa1    0x66    0x2a    0xcb    0x19

    прочитанные байты по адресу куда должен был попасть конец второго сектора совпадают со случайными данными которые я записал в конец образа диска.

    Ну и на экране всё мило, надпись "Loading kernel...." выводится, надпись "Kernel.bin not found!" не выводится.

    Но вообще, если начать придираться, то в процедуре read_sector не инициализирован dl, так что неизвестно, с какого именно устройства происходит попытка чтения в твоём неработающем случае. Можно добавить mov dl, 80h для выбора первого ЖД, для определённости.
    Ответ написан
    Комментировать
  • AT&T синтаксис доступен только GNU Assembler-y (gas)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как я понял GAS нельзя установить на Windows.

    Понял неправильно. Он есть и в составе mingw и в составе cygwin и несложно его кросс-компилировать под венду самому.
    Ответ написан
    Комментировать
  • Как вызвать из C++ программы функции на ассемблере?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как вызвать из C++ программы функции на ассемблере?

    extern "C" void number1();
    …
    int main()
    {
    number1();
    }

    Именно так.
    Ответ написан
    Комментировать
  • Почему не обнуляется регистр cx?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему не обнуляется регистр cx?

    Сдаётся мне, ты совсем другой вопрос хочешь задать. Например, "почему подпрограмма A1 перевода строки в её числовое значение работает неправильно". Ответ на этот вопрос: потому что в следующем коде есть две ошибки:

    A1:
            push    ax
            push    cx
            push    dx
            push    di
            xor     cx, cx
    
            mov     di, 10
            mov     cx, [bx+2]

    - во-превых длина строки записана по смещению 1 в буфере, который заполняет функция 0ah прерывания 21h,
    - во-вторых, длина строки представлена одним байтом, а не словом, как ты читаешь.
    С учётом этого, код должен выглядеть вот так:
    A1:
            push    ax
            push    cx
            push    dx
            push    di
            xor     cx, cx
    
            mov     di, 10
            mov     cl, [bx+1]

    А буфер для ввода строки должен быть определён так:
    firstNum db 6,0,6 dup(?)

    Дальше, вот тут ты опять путаешь байты со словами и загружаешь в dx больше чем надо:
    .A2:
            xor     dx, dx
            mov     dx, [bx+si]
            sub     dx, '0'
            add     ax, dx

    должно быть
    .A2:
            xor     dx, dx
            mov     dl, [bx+si]
            sub     dl, '0'
            add     ax, dx


    Дальше у тебя какая-то ерунда с балансом стека:
    A1:
            push    ax
            push    cx
            push    dx
            push    di
    ...
            pop     si
            pop     di

    ты кладёшь в него одно, а снимаешь другое и в другом количестве. Но это не важно, потому что из функции A1 ты всё равно нигде не возвращаешься. Show_AX выглядит нормально.
    Ответ написан
    7 комментариев
  • Что такое Потоки на уровне ОС? В 1-ядерном процессоре же всего 1 поток?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    И К примеру выполняется такие команды, как пример инструкция чтения строки из stdin, почему вся ос не глохнет. Типа что в этот момент ожидания времени происходит, Или что ОС все 1000 потоков переключает там каждую 0.0001 секунды?

    Только готовые к выполнению потоки получают процессорное время. Потоки могут останавливаться в ожидании какого-либо примитива синхронизации, например семафора или мьютекса. Такие потоки не занимают процессор.
    Поток читающий из stdin может останавливаться, например, на семафоре, защищающем очередь данных stdin когда она пуста. Какой-то другой поток должен поместить новые данные в очередь stdin и открыть этот семафор, переведя ожидающий поток в состояние готовности к выполнению.
    Ответ написан
    Комментировать
  • Не компилится программа на ассемблере. Как исправить?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Приведённая программа -- для 32-битного ARM, ассемблер 32-битного ARM заметно отличается от ARM 64 и я не вижу у aarch64-*-as ключей которые бы говорили ему работать как 32-битный ассемблер. Ставь кросс-тулчейн для 32-битного ARM и пользуйся им.
    Ответ написан
    Комментировать
  • Ассемблер, я правильно понимаю что по умолчанию в регистрах 0x00?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    А если принять к факту, что по умолчанию в регистрах хранится значение 0x00

    Ничего в регистрах "по умолчанию" не хранится, кроме того, что в них в последний раз было записано.

    я попробовал ничего не записывать в регистр AH и вызвать прерывание 0x16, значит по умолчанию в регистре 0x00.

    Нет, это значит только то, что в этом месте твоей программы в этот раз в регистре AH был 0.

    в подпрограмме read_keyboard почему то не сохраняют регистр AX

    Потому что результат возвращают в нём.

    почему сохранили регистр BX - я не понял

    …а также cx, dx, si и di. При том, что функция 0 int 16 меняет только AX. Я думаю, что на всякий случай их сохранили, для надёжности.
    Ответ написан
    Комментировать
  • Как процессор распознает длину команды?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как процессор может отличить длину команды (1, 2, и 3 байт), чтобы выполнить следующую команду ?

    По коду операции -- части команды, которая кодирует действие команды. В процессоре закодировано соответствие кода операции и длины команды. Код операции может полностью содержаться в первом байте команды (как в 8080), либо может быть распределён между несколькими байтами команды. В последнем случае часть кода операции находящаяся в первом байте должна отличаться от кода операции любой однобайтовой команды чтобы их можно было отличить.

    Почему кроме команды Остановить все команды занимают 3 байта?

    Если речь о 8080, то это утверждение неверно. В 8080 есть несколько однобайтовых команд (nop, битовые сдвиги и вращения, push/pop, и т.д.), несколько двухбайтовых (mvi и арифметика с непосредственными значениями -- adi, aci, и т.д.) и несколько трёхбайтовых (команды с прямой адресацией -- lda, sta, и т.д., переходы, вызовы подпрограмм и т.д.). Потому что значения, с которыми оперируют команды находятся в байтах следующих за первым -- в одном, если нужен 1-байтовый операнд и в двух если нужен 2-байтовый операнд или адрес.

    Как происходить выборка команды? Как найти логическую схему выборки команды?

    Можно посмотреть в исходники отреверсированного 8080.
    Ответ написан
    Комментировать
  • Как реализовать на с или assembler асинхронную выборку из RAM?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как реализовать на с или assembler асинхронную выборку из RAM?

    Например так. Это часть реализации memcpy для MIPS. Этот код не выглядит асинхронным, но написан именно так (сначала групповая загрузка в разные регистры, потом изменение базового адреса загрузки, потом групповое сохранение, потом изменение базового адреса сохранения) с рассчётом на то, что процессор сможет, в том числе, перекрыть во времени операции загрузки, арифметики и сохранения данных.
    Ответ написан
    2 комментария
  • Как происходит работа с short в asm?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    00000234: xori r16,r16,32768
    00000238: addi r16,r16,-32768

    Это классическое расширение знакового бита, в данном случае для 16-битного числа: если бит 15 был установлен (число отрицательное), то после xor он будет сброшен (т.е. он и все биты старше него станут нулями), а после addi бит 15 и все старше него станут единицами. Если бит 15 был сброшен (число неотрицательное), то после xor он будет установлен, а после addi -- сброшен опять.

    Подскажите пожалуйста смысл таких преобразований?

    Знаковое расширение -- это часть short right = acum & 65535;. Оно нужно для того, чтобы работать с загруженными в регистры значениями не задумываясь об исходной ширине их типа данных. Т.е. (short)-1 в 64-битном регистре будет представлен как 0xffffffffffffffff, а не как 0xffff.
    Ответ написан
    Комментировать
  • Есть ли программы анализа листинга на assembler?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Eсть программа на assembler без комментариев. Надо ее ускорить, изменив некоторые участки. Искать эти участки большая морока.

    Искать эти участки можно с помощью профилирования.
    Ответ написан
  • Как задать регистры стека ss, sp на x86 (загрузчик 16бит)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Обычно удобно пользоваться моделью памяти, в которой все сегментные регистры указывают в одно место. И если пишешь загрузчик, рекомендуют сегментные регистры инициализировать в самом начале. Какое именно значение сегмента выбрать -- 0 или 0x7c0 не имеет большой разницы. sp можно инициализировать так:
    start:
    ....
    mov sp, start + 512 + 1024

    это будет работать правильно для любого выбранного org и соответствующим образом инициализированного ss.
    Например:
    org 0x7c00
    start:
    mov ax, 0
    mov ss, ax
    mov sp, start + 512 + 1024


    mov ax, 0x060 ;(1024+512)/16=96=60h адрес стека после загрузчика в сегментах
    mov ss, ax ;установка адреса сегмента стека
    mov sp, 1024 ;установка указателя стека

    непонятно, почему ты решил записать в ss 0x60 а в sp -- 1024. Если ты хотел чтобы сегмент стека указывал на его дно, то должно было получиться (0x7c00 + 512) / 16 = 0x7e0.

    add ax, 0x060 ;адрес стека после загрузчика в сегментах 0x07C0+0x060

    и опять логика непонятна.
    Ответ написан
    3 комментария
  • Сегменты данных, кода это разделение для ассемблера или так хранится в машинном коде?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    На ассемблере в программе есть раздел .text, .bss, .data

    Обычно эти разделы называют секциями а не сегментами. Потому что в ELF-файлах сегменты тоже есть, но у них нет имён.
    при компиляции в машинный код там тоже так на сегменты разбит

    Разбит, да. А при линковке некоторые секции можно объединить. Обычно неизменные секции (например .text, .rodata, .tls) объединяют в одну кучу, а все изменяемые (например .bss, .data) объединяют в другую кучу. На "больших" ОС (типа linux) эти кучи эти выравнивают по границе страницы и делают неизменные секции доступными только для чтения. Это помогает сэкономить память и использовать одни и те же страницы для представления неизменных данных в разных процессах.

    для выполнения процессором

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

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    mul al,5

    Нет такого опкода. mul вообще на непосредственное значение умножать не может. imul который может, умножает как минимум 16-битное значение в ax.
    Вместо mul умножить на 5 можно через lea (начиная с i386) либо через сдвиг на 2 и сложение.

    idiv cx,4

    idiv так не умеет. Куда проще было бы сделать sar cx, 2
    Ответ написан
    Комментировать
  • Не могу решить лабу по ассемблеру?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    mov al,x
    cmp al,a
    jg sled1
    mov bl,a
    ...


    как сделать разветвление от условия, если это условие не удовлетворяет.

    Если условие не удовлетворено, инструкция jg sled1 не совершает перехода и ты просто выполняешь следующую за ней инструкцию -- mov bl, a. Ветвления и переходы в твоём коде выглядят правильно.
    Ответ написан
    Комментировать
  • Почему программа ловит SIGSEGV на инструкции push?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Указатель стека (RSP: 0x00007FFFFFFFEA78) указывает примерно в то же место, где находится код программы (0x7fffffffea75: push rbx). Код обычно защищён от записи, соответственно записать в стек может быть нельзя по этой причине. Кроме того, если записать в стек таки можно, push rbx как раз перепишет саму себя и следующую инструкцию. Без отладчика это может работать за счёт конвейера, но под отладчиком это работать не будет.
    Ответ написан
    Комментировать
  • Правильно ли я понимаю?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Правильный ли ход мыслей?

    Да.
    Одни ассемблеры имеют одну мнемонику для нескольких опкодов с разным двоичным представлением (например на i8086 мнемоника mov выполняет множество разных видов перемещений данных между регистрами/памятью, конкретный опкод выводится из операндов), другие имеют для этого разные мнемоники (например на i8080 мнемоники mov, mvi, lda, ldax, sta, stax, lxi выполняют каждая свой вид перемещения данных между регистрами/загрузку/выгрузку из памяти/загрузку непосредственных значений).
    Ответ написан
    3 комментария
  • Отладка небольших ассемблерных кусков кода?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    только проблема в том, что в gcc формат ассемблерных вставок другой

    Разберись, потом будешь использовать его с удовольствием:
    int main() {
      int a = 1;
      int b = 3;
      int c;
    
      asm (
        "mov %[a], %[c]\n\t"
        "add %[b], %[c]\n\t"
        : [c] "=mr" (c)
        : [a] "mr" (a), [b] "mr" (b));
    
      printf("a + b = %x + %x = %x\n", a, b, c);
    }
    Ответ написан
    1 комментарий
  • Ассемблер практикуют написанием драйверов и вирусов?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как его ещё практикуют?

    чтением. Читая ассемблерный вывод компиляторов можно узнать как они реализуют те или иные вещи.
    Ответ написан
    Комментировать
  • Как получить адрес в .rdata?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Сложить смещение (0x28316dc) с адресом следующей команды (0x7ffca9332358).
    Ответ написан
    Комментировать