2016-11-25 5 views
1

В попытке получить данные в таблицы дескрипторов прерываний, используя следующий код:Использование GCC ассемблерные MinGW, чтобы загрузить структуру IDT не удается

/* SIDT returns IDT in following format */ 
#pragma pack(1) 
typedef struct 
{ 
    unsigned short IDTLimit; 
    unsigned short LowIDTBase; 
    unsigned short HighIDTBase 

} s_idt_info; 
#pragma pack() 

. 
. 
. 

    s_idt_info idt_info;  // returned by sidt 
    s_idt_entry *idt_entries; // obtained from idt_info 
    unsigned long count; 

    // load idt_info 
    __asm ("sidt idt_info"); 

Я получаю следующее сообщение об ошибке:

||=== Build: Release in driver2 (compiler: gnu_64) ===| 
obj\Release\driver.o:driver.c|| undefined reference to `idt_info'| 
||error: ld returned 1 exit status| 
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===| 

Использование MinGW -64bit's g ++ компилятор

+0

gcc не является «встроенным ассемблером», и это не связано с mingw! – Olaf

+0

Возможный дубликат [Что такое неопределенная ссылка/неразрешенная ошибка внешнего символа и как ее исправить?] (Http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external- symbol-error-and-how-do-i-fix) – Olaf

+2

Olaf: Я не думаю, что это дубликат этого вопроса, так как это действительно проблема базовой встроенной сборки GCC, которая имеет только видимость глобальных переменных. В этом случае 'idt_info', скорее всего, является локальным для функции, в которой находился код (это немного предположение, поскольку функция не показана в коде) –

ответ

2

GCC не поддерживает локальные переменные (внутри функции) внутри встроенной сборки, в отличие от MSVC. Если переменная idt_info была сделана глобальной, то она должна быть видна встроенным ассемблер, однако GCC documentation отпугивает это:

Accessing data from C programs without using input/output operands (such as by using global symbols directly from the assembler template) may not work as expected. Similarly, calling functions directly from an assembler template requires a detailed understanding of the target assembler and ABI.

Since GCC does not parse the assembler template, it has no visibility of any symbols it references. This may result in GCC discarding those symbols as unreferenced unless they are also listed as input, output, or goto operands.

То, что вы хотите сделать, это использовать GCC extended assembler template и использовать выходное ограничение, чтобы позволить GCC к введите адрес idt_info, который будет обновлен SIDT. Нечто подобное должно работать:

__asm__ __volatile__ ("sidt %[idtptr]" : [idtptr]"=m"(idt_info)); 

= означает ограничение будет использоваться для вывода, m силы GCC передать операнд в памяти. SIDT требует операнда памяти, а не регистр. %[idtptr] - это имя, присвоенное параметру, и GCC заменит его ссылкой на фактическую память.