К оглавлению | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Конечной целью программирования является не написание красивого кода, радующего глаз программиста, а передача последовательности команд центральному процессору (далее по тексту — процессор). Поэтому чем оптимален их набор в коде программы, тем выше её производительность.
В процессе выполнения программы, по мере надобности, процессор вычитывает инструкции из памяти или вернее из КЭШа, который в свою очередь может их иметь один, два или три уровня в зависимости от архитектуры процессора и модели его реализации.
Каждая инструкция имеет размерность в байтах, которая не имеет различий с размерностью данных с которыми она оперирует. Поэтому для различая между данными и инструкциями используются специальные указатели (special pointers), чтобы помочь процессору следить за тем, где в оперативной памяти хранятся инструкции и данные.
В свою очередь любые данные и инструкции являются частью адресного пространства. Соответственно, программа должна знать куда и по какому адресу обращаться, чтобы выполнить инструкцию и/или передать ей данные. Поэтому регистры специальных указателей процессора содержат адрес памяти сегмента данных или кода, где хранятся инструкции или, соответственно, данные.
Листинг 1. Использование указателя инструкции
Регистр указателя инструкций EIP (Instruction pointer) используется, чтобы помочь отслеживать процессору какие инструкции уже были обработаны и какие нужно обработать ещё. При этом к регистру EIP нельзя обратиться на прямую, а лишь косвенно через вызов таких инструкций как JMP, Jcc, CALL и RET, а так же прерываний и исключений.
Как видно из листинга 1, адрес памяти в регистре EIP приращивается не в соответствие с префиксом, указанным в мнемоническом объявлении инструкции, а по непонятному на первый взгляд случайному распределению байтов в памяти, который на самом деле следует из формата кодирования инструкции в машинный код.
Листинг 2. Фрагмент дампа результата дизассемблирования объектного файла
Из листинга 2 видно, что счетчик в лице указателя инструкций приращивается ровно на то количество байт сколько фактически инструкции отведено в машинных кодах. Поэтому настала пора рассмотреть ее формат представления к оным.
Формат машинного кода инструкцииНа рис.1 представлен формат машинного кода инструкций архитектуры x86-32.
Мандатный префикс инструкцииДополнительно инструкция может иметь один из четырех групп префиксов, имеющие размерность в один байт и обеспечивающие переназначение её поведения от устанавливаемого по-умолчанию (таблица 1). При этом одновременное использование подряд нескольких префиксов может привести к непредсказуемым результатам.
Таблица 1. Мандатные префиксы инструкции
В листинге 2, префикс инструкции ( выделен жирным) встречается по смещению 8, как показано в листинге 3, при помещения константы 0xffff в 16-ти разрядный регистр аккумулятора AX.
Листинг 3. Пример использования префикса инструкции
. . .
8: 66 b8 ff ff mov $0xffff,%ax
. . .
В таблице 2 приводится использование префиксов переназначения размера данных (операндов) и адресации согласно режиму работы процессора.
Таблица 2. Использование префиксов переназначения размера операндов и адреса
Префикс 0x0FПризнак наличия двух-байтового кода операции, который начинается именно с данного значения в первом байте.
В листинге 2, данный префикс присутствует по смещению 5 и 12. В первом случае он используется в инструкции movzbl, а во втором в movzwl, которые производят операции с 8-ми и 16-ти разрядными данными соответственно.
Листинг 4. Пример использования префикса 0f
. . . 5: 0f b6 d2 movzbl %dl,%edx . . . 12: 0f b7 c0 movzwl %ax,%eax . . . Код операцииКод операции Opcode (Operation code) может состоять из 1 или 2-х байтов. При этом, если операция производится только между регистром и непосредственного значения (способ адресации – непосредственная), код инструкции может состоять из opcode и непосредственного операнда, как показано в таблице 3, а первые три младших разряда её будут содержать идентификатор регистра, соответствующий полю reg байта modR/M.
Таблица 3. Представление в машинных кодах записи непосредственного операнда 0xffffffff, 0xfffff и 0xff в регистры общего назначения.
Таким образом, для регистров общего назначения при использовании непосредственной адресации, можно вывести следующее выражение формально-логического описания, в данном случае для инструкции перемещения данных – MOV.
Мнемон. обознач.Форма записи в формально инструкции GASлогическом описание MOVB imm8, r8 MOVW imm16, r16→[MOV + /r] [imm] MOVL imm32, r32 Где
MOV – мнемоническое обозначение opcode, равного значению BA16;
/r – один из регистров общего назначения:
r8 – размерностью 1 байт (8 разрядов) : AL, CL, DL, BL, AH, CH, DH, BH, BPL, SPL, DIL и SIL;
r16 – размерностью 2 байта (16 разрядов): AX, CX, DX, BX, SP, BP, SI, DI;
r32 – размерностью 4 байта (16 разрядов): EAX, ECX, EDX, EBX,ESP, EBP, ESI, EDI;
imm – непосредственное значение операнда, который обозначается с использованием символьного префикса '$'. Иначе, операнд может быть воспринят как адрес памяти.
imm8 – одно-байтовое знаковое значение в диапазоне значений от –128 до +127 включительно или без знаковое, записанное в форме шестнадцатеричной системы представления чисел в диапазоне допустимых значений от 0 до 255 включительно. Для инструкций, которые комбинирует такое одно-байтовое знаковое значение с операндом размерностью слово или двойного слова, непосредственное значение будет расширено с учетом знака до требуемого размера. При этом старшие байты расширяемого значения будут заполнены согласно старшему разряду непосредственного значения.
imm16 – двух-байтовое знаковое значение в диапазоне значений от –32,768 до +32,767 включительно или без знаковое, определенное в форме шестнадцатеричной системы представления чисел от 0 до 65535 включительно.
imm32 – четырех-байтовое с учетом знака значение в диапазоне значений между +2,147,483,647 и –2,147,483,648 включительно или без знаковое, определенное в форме шестнадцатеричной системы представления чисел от 0 до 4294 967 295 включительно.
Общей формой записи инструкции для непосредственной адресации будет являться формула (1), используемой в формально логическом описании
(1)[OPCODE + /r] [imm]
Где
OPCODE – является мнемоническим наименованием инструкции.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
К оглавлению |