2017-01-13 68 views
0

我正在創建一個小例程,用lidt指令加載idtr寄存器。 我創造了這個代碼 -錯誤:操作碼和操作數的組合無效 - 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 

我的編譯命令是 -

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

任何人都可以指出這個程序中的錯誤?

+1

助記符是'LIDT m16&32' ...你的意思是'lidt [eax]'? – Tommylee2k

+0

我想用'load_idt()'調用C中的函數'。我必須使用'[eax]'嗎?它不是指向idtr的價值而不是它的地址? @ Tommylee2k –

回答

1

idtr寄存器必須加載兩條信息:指向描述符表的指針和大小,以字節減去前者的一個字節。

因此,與Tommylee2k pointed out一樣,唯一有效的格式是LGDT m16&32,其中m16&32是指向保存16位大小和32位基址指針的內存位置的指針。

引述英特爾

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是可編碼的,只要使用具有值0d8h一個MODR/M字節(011B爲REG域作爲一個擴展操作碼,11b和000B mod and r/m使用字段eax)但是lidt生成#UD如果使用了註冊源(實際上lidt eax被重新用於AMD-v的vmrun)。

+0

我打算從C調用匯編程序。雖然我使用的是描述符表的數組而不是指針。這會產生什麼區別或更好的功能? –

+0

你不應該通過set_idt按值傳遞一個IDT,而不是一個描述符?可能我錯過了翻譯中的某些內容,或者假設要使用這些內容。 –

+0

是@MichaelPetch,我寫了錯誤的結構,謝謝指出。 –