2013-12-02 2 views
3

Я работаю над проектом операционной системы для своей лаборатории, где я должен работать с указателем инструкций и инструкцией по операции. Сейчас все, что мне нужно знать, это тип обучения. Для этого я читаю данные по адресу, указанному указателем инструкции. Первый байт из этих данных дает мне тип инструкции. Например, если первый байт составляет 0xC6, это инструкция MOVB. Теперь есть некоторые случаи, когда первый байт указателя команды равен 0x0F. Согласно документации 0x0F, что означает, что это двухбайтная инструкция. Моя проблема связана с этим типом инструкции. Я не уверен, как узнать тип инструкции для двухбайтовой инструкции.Декодирование команд в архитектуре x86

После этого мой второй приоритет - два, чтобы узнать операнды инструкции. Я не знаю, как это сделать из кода. Любой пример кода будет оценен

В-третьих, необходимо выяснить размер инструкции. Поскольку x86 является переменной длиной, я хочу знать размер каждой инструкции. Сначала я планировал использовать таблицу поиска, в которой я буду поддерживать имя инструкции и ее размер. Но потом я обнаружил, что одна и та же инструкция может иметь переменную длину. Например, когда я использовал свалку объекта в файле .o, я нашел две инструкции C6 00 62, которая для MOVB $0x62,(%EAX) & C6 85 2C FF FF FF 00 которая для MOVB $0x0,-0xD4(%EBP). Посмотрите здесь, оба типа инструкции одинаковы (C6), но они имеют разную длину.

Итак, мне нужны ответы на эти вопросы. Будет очень признателен, если кто-то может дать мне некоторые решения.

+0

То, что вы просите, довольно сложно и нелегко ответить в формате SO. Вы можете проверить, как это делают популярные дизассемблеры с открытым исходным кодом ('gdb',' objdump'). И [читать документы] (http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html)! – rodrigo

+0

Дополнительный контекст, пожалуйста. Почему проект ОС включает эмуляцию процессора x86? –

+0

@SevaAlekseyev. Мой проект включает в себя возможность возврата к предыдущему состоянию. Я должен сделать это, используя mprotect(). Идея состоит в том, чтобы защитить каждую страницу от операции записи. Поэтому, когда есть операция записи, я поймаю ее. Внутри функции обработчика я сохраню старые данные, извлеките новые данные из инструкции, сделайте страницу незащищенной, запустите инструкцию еще раз, а затем снова закройте страницу. Поскольку внутри обработчика я не знаю, какое значение должна была выполнить операция, поэтому я могу только выяснить IP, получить операнды команд и выполнить его снова. – azizulhakim

ответ

7

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

Ваш оператор верхнего уровня будет в значительной степени 256 случаев, по одному для каждого байта кода операции; вы найдете некоторые из кодов операций (особенно так называемые «префиксные» байты) заставляют верхний уровень зацикливаться (сбор нескольких префиксных байтов предшествует основному байту кода операции). Sub-события будут получать структуру согласно структуре кода операции x86; вы почти наверняка закончите работу с модулями декодирования MODRM и SIB с байтовыми декодерами/подпрограммами.

Я сделал это; работа раздражает из-за деталей, но не трудно. Вы можете получить довольно хорошее решение в нескольких сотнях строк кода, если будете осторожны. Если вы настаиваете на выполнении всего набора команд (векторных регистров и кодов операций, esp. Для haswell и т. Д.), Вы, скорее всего, получите нечто большее; Intel вводит инструкции в каждый темный угол, который они могут найти.

Вам действительно нужна карта опкода; Я уверен, что в руководствах Intel есть один. Я нашел эту ссылку, чтобы быть очень полезным: http://www.ref.x86asm.net/coder32.html

EDIT Sept 2015: Здесь на SO я обеспечиваю C код, который реализует этот: https://stackoverflow.com/a/23843450/120163

+0

Гигантские заявления операторов просто злые и редко могут быть извинения. :) – oakad

+5

@ user16653: Иногда зло - это правильная вещь :) –

+0

Да, на самом деле я попытался найти таблицу, но у меня проблемы с инструкциями TWOBYTE. Я не знаю, как они работают. Например, я получаю значение 0x0000000F в указателе инструкции, и я действительно не знаю, что это значит. Он не заполняет какую-либо категорию. – azizulhakim

4

Дополнительный подход на самом деле построить правильный синтаксический анализатор для сборки, используя одну из многих фреймворков генератора парсеров (например, вездесущий yacc). Это может привести к упрощению обслуживания и возможности чтения в режиме, чем использование вложенных операторов switch с большим количеством случаев.

Существует также промежуточный подход, после которого парсер, основанный на таблице, может быть реализован «вручную».Один из примеров здесь: https://github.com/libcpu/libcpu/blob/master/arch/x86/x86_decode.cpp

+0

Вы предлагаете использовать генератор парсера для обработки байтовых потоков команд, с байтами инструкций в качестве токенов? Это интересно. Но я уверен, что настоящие процессоры не используют такую ​​власть; они работают с лучшими FSA. Ближе к значению может быть использован генератор лексера, который создает FSA. –

+1

На самом деле хорошая реализация декодера в моей ссылке, по-видимому, является самым простым способом сделать декодер на FPGA по крайней мере (используя блок LUT и простой FSA). Но когда речь заходит о программном обеспечении, я, вероятно, испорчен методом boost :: spirit, чтобы делать синтаксические анализаторы (которые удваиваются по мере того как FSA и делают только тонкие, сложные мудры, без lexing step, что приводит к очень простой и эффективной структуре программного обеспечения).Однако, судя по тому, что boost :: spirit может показаться несколько пугающим с первого взгляда, я решил упомянуть что-то более мирское, например yacc. – oakad

1

kvm имеет очень сложный эмулятор/декодер x86, который может быть повторно использован вашим проектом.

+0

На самом деле есть много инструментов. Но их источник слишком большой для меня прямо сейчас. Все, что я хочу, это понять три момента, которые я сделал. Оттуда я верю, что смогу сделать простой. – azizulhakim

+1

@azizulfahim. В вашем вопросе состояние процессора сокращено до одного указателя инструкции. Это, во-первых, чрезмерное упрощение проблемы. Декодер команд x86 по своей природе DFA принимает двоичные строки в качестве входных данных. Его таблица перехода определяется грамматикой. Вы не можете упростить грамматику и надеяться, что DFA все еще корректно обрабатывает двоичные строки из полной грамматики. – liuyu

Смежные вопросы