2017-01-13 22 views
0

Я создаю небольшую процедуру для загрузки регистра idtr с помощью инструкции lidt. Я создал этот код -Ошибка: Недопустимая комбинация опкода и операндов - nasm

global load_idt 

load_idt: 
    mov eax, esp 
    add eax, 4 
    lidt eax ;<-----------------LINE 9 
    ret 

Но когда я компилирую это с помощью NASM, я получаю ошибку -

kernel/kernel_start.asm:9: error: invalid combination of opcode and operands 

Моя команда компиляции

IS-
nasm kernel/kernel_start.asm -f elf32 -o kernel/kernel_start.o 

Можно ли указать ошибка в этой программе?

+1

mnemonic is 'LIDT m16 & 32' ... Вы имели в виду' lidt [eax] '? – Tommylee2k

+0

Я хочу вызвать функцию в C, используя 'load_idt ()'. Допустим, я должен использовать '[eax]'? Разве это не указывает на значение idtr, а не на его адрес? @ Tommylee2k –

ответ

1

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

Так что, как Tommylee2k pointed out, единственная действительная формой является LGDT m16&32, где m16&32 представляет собой указатель на ячейку памяти, которая содержит размер 16-битный указатель базы и 32-битной.

Цитирование Intel

The source operand specifies a 6-byte memory location that contains the base address and the limit of the interrupt descriptor table.

Учтите, что размер приходит до базового адреса.

Если бы я тебя, я бы держать сборку минимален с соответствующим использованием C.
Например использовать структуру для представления базы IDT и предел, а затем передать его по значению к функции, написанной на ассемблере ,
Это также один из редчайших случаев, когда inline assembly is fine, чтобы вы могли подумать.

/* IDT descriptor */ 
struct desc_t; 

/* IDT */ 
struct __attribute__ ((__packed__)) IDT 
{ 
    uint16_t size; 
    struct desc_t* table; 
}; 

/* Declaration of assembly function */ 
void set_idt(struct IDT idt); 


;Parameters in order of push 
; 
; struct IDT idt 
; 
_set_idt: 
lidt [esp+4] 
ret 

Общая

Технически lidt eax является кодируемый, достаточно использовать ModR M байт/со значением 0d8h (011b для рег поле в качестве расширенного кода операции, 11b и 000b для mod и r/m поля для использования eax), но lidt генерирует #UD, если используется источник регистра (и infact lidt eax используется повторно для vmrun AMD-v).

+0

Я планирую вызвать процедуру сборки из C. Хотя я использую массив для таблицы дескриптора, а не указатель. Будет ли это иметь какое-либо значение или какая-то более эффективная функциональность? –

+0

Разве вы не должны передавать IDT по значению, а не через один дескриптор через set_idt? Возможно, мне что-то не хватает в переводе или как это предполагается использовать. –

+0

Да @MichaelPetch, я написал неправильную структуру, спасибо, что указали это. –