2015-09-25 62 views
4

我正在開發一個C語言的小玩具內核。我現在需要從鍵盤獲得用戶輸入。到目前爲止,我一直在使用下面的代碼來實現inbGCC內嵌組件'Nd'約束

static inline uint8_t inb(uint16_t port) { 
    uint8_t ret; 
    asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); 
    return ret; 
} 

我知道"=a"約束意味着al/ax/eax將被複制到ret作爲輸出,但我仍然困惑的"Nd"約束。任何人都可以提供一些關於爲什麼這個約束是必需的見解或者爲什麼我不能只使用通用寄存器約束如"r""b"?任何幫助,將不勝感激。

+0

你瞄準16位代碼? –

+0

我的目標是32位代碼,因爲我使用GRUB將我的內核加載到保護模式。 –

回答

5

in指令(返回一個字節)可以將立即的8位值作爲端口號,或者在dx寄存器中指定的端口。有關in指令的更多信息,請參閱instruction reference(英特爾語法)。正在使用的機器限制可以在GCC docs中找到。如果您向下滾動到x86 family你會看到:

d

The d register 

ň

Unsigned 8-bit integer constant (for in and out instructions). 
+0

好的,謝謝。這幫了很多。然而,我有一個最後的問題,如果'N'約束只允許0-255端口的立即字節,但'd'約束允許整個'dx'寄存器,爲什麼我不能只使用'd 「約束?我的意思是,使用這兩個約束有什麼好處? –

+0

@MichaelMorrow這是從8086/8088節節省的時候,節省空間通常很重要。如果使用8位立即數(對於0-255之間的端口),則不需要額外的指令先將其移至「DX」(節省空間)。如果你想訪問256-65535端口,你必須通過'DX'傳遞它。您可以在'DX'中指定一個8位(0-255)端口號,但您必須首先將其移至「DX」,從而招致額外的處罰。 –

+0

明白了!謝謝你爲我清理這個。 –