Задать вопрос
Ответы пользователя по тегу Assembler
  • Как узнать, откуда прерывание?

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

    Возможно тебе следует выяснить, что это конкретно за "состояние машины" которое ты собираешься сохранить, возможно это поможет тебе его найти.
    Ответ написан
    4 комментария
  • Хочу написать простенький симулятор процессора для уроков, какую выбрать систему команд?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Какую систему команд выбрать? …
    для демонстрации принципов работы ассемблера

    Для этого нужно ответить на вопросы: где вы собираетесь взять ассемблер и как конкретно вы собираетесь демонстрировать его работу?
    Я вижу два возможных ответа на первый вопрос: взять готовый или написать самому. Если цель -- написать самому, то это может быть сравнимо по сложности, если не сложнее, чем написать эмулятор для той же самой системы команд. Если брать готовый, я бы рекомендовал RISC-архитектуру, но все они с теми или иными заморочками, так что это будет выбор наименьшего из зол. На мой взгляд RISC-V, точнее базовый набор RV32I -- достойный кандидат.
    Ответ написан
    Комментировать
  • Одна мнемоника преобразуется в один код, или в разные?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Скажите, машинный код команды будет один и тот же, или различный?

    Первая ссылка по запросу mov x86 в гугле: https://c9x.me/x86/html/file_module_x86_id_176.html
    Ответ написан
    Комментировать
  • Как с помощью консоли сделать lst файл, masm32?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    .lst обычно называют листинги ассемблера, которые показывают, в какие конкретно байты были оттранслированы инструкции ассемблера. Для masm это делается ключом /Fl, а деталями листинга можно управлять ключами /S*, см.

    проблема в том что надо не через линк а через link16 тогда работает,

    тогда, возможно, тебе нужен не листинг ассемблера, а мэп линковщика. Его вывод можно включить опцией линковщика /MAP.
    Ответ написан
    Комментировать
  • Как создать массив хендлов на MASM?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Для полноты картины не хватает определений hBmp, hbtm и hInstance.
    Косяк бросающийся в глаза сразу -- ты создаёшь таймер в обработчике WM_INITDIALOG, но нигде его не удаляешь и он продолжает тикать и после закрытия диалога.
    Ответ написан
    Комментировать
  • Почему вылетает программа?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Написал простую программу, которая висит, ожидая нажатие клавиши, но она не висит, а вылетает

    format PE console
    …
                    push str1
                    call [printf]
    
                    mov ah, 7
                    int 21h

    интересная попытка, но почему печать -- вызовом функции, а ввод символа -- вызовом досовского прерывания,
    если для печати тоже есть досовское прерывание?
    Если серьёзно, нельзя вызывать досовские прерывания из приложения win32. Ищи подходящую функцию win32 API.
    Ответ написан
    Комментировать
  • Моя программа не грузиться на VB и в BIOS не отображается SANDISK?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    У тебя тут три разных вопроса.
    Моя программа запускается в bosh но не реагирует на прерывания клавиш


    А какую реакцию ты ожидаешь? Введённый символ ты не печатаешь, si ты не перезагрузил, так что puts_loop загружает из памяти следующий 0 и тоже ничего не печатает. Можно сделать так чтобы увидеть, что int 16h таки работает:

    keyboard_loop:
            mov ah, 0
            int 16h
            mov ah, 0Eh
            int 10h
            jmp puts_loop


    iso образ созданный dd не запускается в VB

    А почему ты думаешь, что из mbr можно создать iso с помощью dd? Его вообще-то надо в правильное место поместить, не абы куда. Например это можно сделать так: mkisofs --no-emul-boot -o test.iso -b test.bin . где test.bin -- это твой бинарник бут-сектора.

    а загрузочная флешка не отображается в BIOS

    Это видимо следствие из того, как ты сделал iso который закатал на флэшку.
    Ответ написан
    Комментировать
  • Как вычисляется эффективный адрес относительно счетчика команд?

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

    Оттуда, что складываемые числа -- RIP 0x7ff778a06497 и смещение 0x67f9. Смещение записано в поле инструкции mov в формате little endian.

    что это за значение 88 13 00 00 ......... и Val = 5000 ?

    Я так понимаю, что это иллюстрация, что по адресу 0x7ff778a0cc90 оказались байты 0x88, 0x13, 0x00..., которые после загрузки в регистр rax дали значение 0x1388 == 5000
    Ответ написан
    Комментировать
  • Как выучить язык ассемблера?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как выучить язык ассемблера?

    Читать ассемблерный код. Когда научишься с лёгкостью читать, писать тоже сможешь.
    Посоветуйте какие-нибудь ресурсы по изучению

    Исходники на ассемблере, которые любой компилятор тебе нагенерирует, справочник по инструкциям твоего процессора (например 2й том Intel developer manual) и гугл. Просто бери, читай и разбирайся зачем так.
    Ответ написан
    Комментировать
  • Как узнать возраст файла в Ассемблере?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как мне найти возраст файла?

    Сравнить creationTime который возвращает GetFileTime с текущим временем которое возвращает GetSystemTimeAsFileTime. 3 дня -- это 3 * 24 * 60 * 60 * 10000000 100-наносекундных интервала (в таких единицах измеряется FILETIME).
    Чтобы упростить себе задачу можно сравнивать только старшие части (dwHighDateTime) структур FILETIME, вес младшей части -- 429 секунд, меньше 10 минут.
    Типа того:

    invoke GetFileTime, hFile, addr ftCreate, NULL, NULL
      invoke GetSystemTimeAsFileTime, addr ftNow
      mov eax, ftNow.dwHighDateTime
      sub eax, ftCreate.dwHighDateTime
      cmp eax, (3 * 24 * 60 * 60 * 10000000 / 0x100000000)
      jg <файл старше 3 дней>
      /* иначе файл младше 3 дней */

    Если упрощать не хочется и нужно отмерить в точности 3 дня, то хвост можно переписать так:
    mov eax, ftNow.dwHighDateTime
      sub eax, ftCreate.dwHighDateTime
      cmp eax, (3 * 24 * 60 * 60 * 10000000 / 0x100000000)
      jg <файл старше 3 дней>
      jl <файл младще 3 дней>
      mov eax, ftNow.dwLowDateTime
      sub eax, ftCreate.dwLowDateTime
      cmp eax, (3 * 24 * 60 * 60 * 10000000 % 0x100000000)
      jg <файл старше 3 дней>  
      /* иначе файл младше 3 дней */
    Ответ написан
    2 комментария
  • Почему не получается открыть файл?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    invoke CreateFile, addr [edi].lpstrFile, GENERIC_READ,

    addr [edi].lpstrFile выглядит неправильно. Должно быть либо [edi].lpstrFile (значение указателя, а не его адрес), либо offset buf.
    Ответ написан
  • Что значит этот код?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    что значит код

    ubfx r0, r0, #1, #1 -- извлечь битовое поле шириной 1 бит (правая единица) начиная с бита №1 (левая единица) из регистра r0 (правый r0) и поместить результат в r0 (левый r0).
    bx lr -- перейти по адресу в регистре lr, обычно это возврат из подпрограммы.
    Семантика опкодов легко гуглится по названию опкода и названию архитектуры процессора.

    какая между ними разница

    ubfx r0, r0, #1, #1
    ubfx r0, r0, #2, #1
    теперь, когда ты знаешь, что это за опкод, ты можешь понять сам, что они извлекают битовое поле начиная с разных битовых позиций.

    что я делаю не так

    ты не написал, что конкретно ты делаешь: что и где меняешь и как проверяешь результат.
    Ответ написан
    3 комментария
  • Как изменить существующее прерывание биос?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Вот, что я попытался сделать:
    push word 0
      pop es
      mov bx, 0x11*2+0xF000
      mov word [es:bx], int10-$$


    Расскажи немного словами, что ты имел в виду когда писал это?

    Я пытался гуглить, всю ночь потратил, …
    проблема в отсутствии информации


    Вот это нашёл? https://ru.wikipedia.org/wiki/Таблица_векторов_пре...

    Самое важное для тебя и полностью достаточное для реализации твоей задачи предложение из этой статьи:
    В микропроцессорах Intel 8086/80186 таблица векторов прерываний расположена в первом килобайте памяти начиная с адреса 0000:0000 и содержит 256 векторов прерываний в формате сегмент:смещение.


    boot:
      push word 0
      pop es
      mov bx, 0x11*4
      mov word [es:bx + 2], cs
      mov word [es:bx], int10
    Ответ написан
  • Что происходит во время прерывания в многопоточной среде? Или прерывания посреди прерывания?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    откуда прерывания знают адрес, куда им вернуть результат.

    Прерывания не знают. Это работа ОС -- организовать информацию так, чтобы при получении прерывания разобраться, откуда оно, зачем, и что с ним делать.

    Прерывание в коде int 21h и прочие Это какое?

    Любое прерывание инициируемое инструкцией int -- программное. В отличие от прерывания, инициируемого уровнем или фронтом сигнала подключённого к контроллеру прерываний.

    Вообще, кажется, если понять, что программные прерывания на x86 используются просто как удобный способ вызывать функции ядра, т.е. делать системные вызовы, то путаницы должно стать меньше. Не думай о них как о прерываниях, думай о них просто как о вызовах функций ядра. Ядро делает всё для того, чтобы для приложения это именно так и выглядело.

    выполнение прерывания std::cin>>line; Может и сутки длиться.

    Системного вызова. std::cin >>line в конце концов превращается в системный вызов read.

    Вот как по пунктам для этой команды. (С условием что есть еще 1 поток жаждущий ЦП).

    Можно запустить такую программу, узнать её PID, выполнить где-нибудь cat /proc/<PID>/stack и увидеть следующую картину:
    [<0>] wait_woken+0x67/0x80
    [<0>] n_tty_read+0x426/0x5a0
    [<0>] tty_read+0x135/0x240
    [<0>] new_sync_read+0x115/0x1a0
    [<0>] vfs_read+0xf4/0x180
    [<0>] ksys_read+0x5f/0xe0
    [<0>] do_syscall_64+0x33/0x80
    [<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9

    Т.е. поток выполнил системный вызов (ksys_read), зашёл в VFS, добрался до функции чтения в драйвере терминала (tty_read) и перешёл в состояние ожидания в глубине этой функции (wait_woken). Когда драйвер терминала получит данные для программы, он разбудит её поток и системный вызов завершится. До тех пор этот поток будет не готов к выполнению и скедулер ОС просто не будет выделять ему время.

    Мне кажется, что тебе было бы полезно прочитать вторую и третью книжки (Understanding the Linux Kernel и Linux Kernel Developmen) из моего списка.
    Ответ написан
    Комментировать
  • Как происходит доступ к эл. массива на уровне ядра? Malloc выделяет непрерывную физическую память?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как происходит доступ к эл. массива на уровне ядра?

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

    Например массив Int* arr = new int[1024*1024*1024] он как храниться?

    Если мы для определённости возьмём linux, то у ядра есть несколько разных способов выделения памяти, в зависимости от того, для чего эта память выделяется. Есть наиболее простой и стандартный kmalloc который выделяет память непрерывную как виртуально так и физически. Обычно этим механизмом нельзя выделить большой непрерывный кусок. Есть vmalloc, который выделяет непрерывную виртуально, но возможно прерывную физически память. Есть get_free_pages который выделяет непрерывные страницы физической памяти, возможно, не отображаемые ни в какие виртуальные адреса. Есть Contiguous Memory Allocator который при старте системы резервирует кусок непрерывной физической памяти и может аллоцировать оттуда куски по запросу.
    Важный момент состоит в том, что аллокации делаемые ядром linux через упомянутые интерфейсы всегда обеспечиваются физической памятью, у памяти ядра нет пейджинга.

    А физическая, для массива то же? Ведь, так будет доступ намного быстрее?

    Почему быстрее? С точки зрения процессора всё равно будет трансляция виртуального адреса в физический, если повезёт -- попадание в TLB, если не повезёт -- ходить по каталогам и таблицам страниц в памяти.

    получается эмулятор каждый адрес вычислять что ли?

    Простой эмулятор -- да, наверно. Умный эмулятор может кешировать эту информацию, например именно это свойство даёт QEMU большую часть его Q.
    Ответ написан
    Комментировать
  • Какой тип виртуальной памяти Сегментная или Страничная, сейчас используется? Как утроена виртуальная память?

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

    На виндовс, icore 5 процессоре вот сейчас, какой тип памяти работает. И какой тип виртуальной памяти на Risc 5 архитектурах.

    Забудь про сегментную организацию, она есть только в семействе x86, была сильно урезана в x86_64 и в современных ОС почти не используется.

    Вот запускается программа. Что происходит. Типа создается процесс, в MMU в таблице страниц генерируется номер страницы PID>>24 + 0x4000000h адрес примерно. И заноситься в таблицу (https://ru.bmstu.wiki/MMU_(Memory_Management_Unit) ) Создаются типа страницы для данных. Окей

    Это какое-то странное описание, особенно часть PID>>24 + 0x4000000h, это вообще что?
    Если программа получает новое адресное пространство, то оно изначально пустое, программа ни с кем его не делит. Есть вот такая книжка про организацию памяти в linux: https://pdos.csail.mit.edu/~sbw/links/gorman_book.pdf Рекомендую ознакомиться с главой 4.

    как программа вообще может в такой системе вызвать функцию из внешней библиотеки

    первым делом программа загружает внешнюю библиотеку в своё адресное пространство. Дальше уже понятно?

    Что за таблица дескрипторов. Где она находиться.

    Находится где-то в физической памяти. Определяет свойства, размеры сегментов и в какие линейные адреса преобразуются логические адреса внутри этих сегментов. Если ты прочитал про линейные адреса эта часть должна тебе быть понятна. В современных ОС все процессы используют один и тот же селектор для кода и один и тот же селектор для данных, а логические адреса cs:0 ds:0 es:0 и ss:0 транслируется в линейный адрес 0. Это называется "плоская модель памяти".

    Как связана с таблицей страниц?

    Никак. Совершенно ортогональная структура, может работать даже когда страничная адресация выключена.

    Что в конечном итоге храниться TLB буфере????

    Мэппинг "линейный адрес" -> "физический адрес".
    Ответ написан
  • Почему не работает ввод?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Иван Четчасов в твоих вопросах повторяется один и тот же паттерн: у тебя что-то не работает, ты приводишь обрывок кода (обычно не относящийся к проблеме) и ничего не говоришь о том, как ты пытался решить проблему.
    Я предлагаю тебе сделать следующее с этим и всеми последующими вопросами:
    - добавить в вопрос ссылку на репозиторий со всем кодом который можно было бы склонировать и собрать
    - добавить в вопрос описание того, как ты запускаешь код, так, чтобы кто угодно мог воспроизвести твои результаты
    - добавить в вопрос описание того, как ты пытался диагностировать и решить проблему

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

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

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Конкретно эта последовательность помимо тупо сохранения rbp создаёт разметку кадров стека. Если все функции в цепочке вызовов делают так, то из любой функции можно проследить всю цепочку вызовов до неё зная только текущее значение rbp без какой бы то ни было дополнительной отладочной информации, потому что по адресу в rbp хранится rbp предыдущей функции, а по адресу rbp + 8 -- адрес возврата в предыдущую функцию. Но делать это, конечно же, необязательно. Например gcc вызванный с флагом -fomit-frame-pointer генерирует код без этой последовательности и использует rbp как ещё один регистр общего назначения.

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

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

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    почему вычитается 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
    "I'm here to consult you" © Dogbert
    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 комментария