2016-02-09 1 views
3

Je recevais une erreur étrange lorsque je développais mon système d'exploitation. Je faisais un pilote IO en utilisant outb et inb. Ma fonction est outb comme suit:Erreur de syntaxe de l'assembleur en ligne

static inline void outb(uint16_t port, uint8_t val) 
{ 
    __asm("outb %0, %w1" //<--Error 
     : 
     : "a"(val), "Nd"(port)); 
} 

Je reçois cette erreur dans Visual Studio:

C2400: erreur de syntaxe assembleur en ligne dans 'opcode'; trouvé « (»

Est-ce que quelqu'un sait pourquoi je reçois cette erreur? Comment puis-je corriger cette erreur? Des suggestions?

+3

_ "VS" _? Comme dans Visual Studio? Le code que vous avez publié n'utilise pas la syntaxe de Microsoft pour l'assemblage en ligne. Cela ressemble à quelque chose destiné à GCC. – Michael

+1

En effet, c'est la syntaxe d'assemblage en ligne de GCC, ** pas ** Visual Studio. Pour Visual Studio, je ne pense pas qu'il existe un bon moyen d'assigner des variables spécifiques à des registres spécifiques, donc vous pourriez vouloir écrire toute la fonction dans assembly, dans un fichier source d'assembly. – immibis

+1

Lorsque je vous ai aidé précédemment, vous utilisiez l'assembleur GNU, pas Microsoft. Comme @Michael souligne la syntaxe de Visual C++ en ligne dans VS est assez différent de l'assembleur GNU. VC++ ne prend pas en charge les modèles d'assembleur qui sont une extension GCC qui ne sont pas disponibles dans les produits MS. –

Répondre

3

VC++ de Visual Studio ne prend pas en charge les modèles assembleur GNU disponible en GCC Étant donné que vous définissez port comme un entier non signé de 16 bits, vous devez utiliser le format OUT qui prend un numéro de port de 16 bits Vous devez placer le numéro de port 16 bits dans DX Vous devez également traiter les noms des variables dans l'assembly inline comme pointeurs puisque vous utilisez la convention d'appel standard CDECL pour vos fonctions. Exemple de code:

static inline void outb(uint16_t port, uint8_t val) { 
    __asm 
    { 
     mov dx, port 
     mov al, val 
     out dx, al 
    } 
} 

La fonction inb pourrait se faire avec quelque chose comme:

static inline uint8_t inb(uint16_t port) 
{ 
    uint8_t data; 
    __asm 
    { 
     mov dx, port 
     in al, dx 
     mov data, al 
    } 
    return data; 
} 

Cela pourrait être simplifié en supprimant la variable data et stocker le caractère lu dans la variable port et puis en faisant return (uint8_t)port; . Donc, ce serait aussi travailler:

static inline uint8_t inb(uint16_t port) 
{ 
    __asm 
    { 
     mov dx, port 
     in al, dx 
     mov byte ptr[port], al // Need to cast since port is 16-bit variable 
    } 
    return (uint8_t)port; 
} 

Plus de détails sur l'utilisation de l'assembleur en ligne VC se trouvent dans le (MSDN) Microsoft Developer Network documentation

+0

Je n'appellerais pas cela une simplification. – immibis

+0

@immibis La simplification est subjective, bien que dans ce cas nous ne faisons que réutiliser une variable déjà disponible. Ce que je reconnais, c'est que le dernier exemple souffre d'une plus faible lisibilité du code. –