2016-02-09 2 views
3

У меня возникала какая-то странная ошибка при разработке моей операционной системы. Я делал драйвер ввода-вывода, используя outb и inb. Моя outb функции выглядит следующим образом:Ошибка синтаксиса встроенного ассемблера

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

Я получаю эту ошибку в Visual Studio:

C2400: встроенный ассемблер ошибка синтаксиса в 'опкода'; найден «(»

Кто-нибудь знает, почему я получаю эту ошибку? Как исправить эту ошибку? Есть предложения?

+3

_ "VS" _? Как в Visual Studio? Код, который вы опубликовали, не использует синтаксис Microsoft для встроенной сборки. Это похоже на что-то, предназначенное для GCC. – Michael

+1

Действительно, это встроенный синтаксис GCC, ** не ** Visual Studio. Для Visual Studio я не думаю, что есть хороший способ назначить определенные переменные для конкретных регистров, поэтому вы можете просто написать целую функцию в сборке в исходном файле сборки. – immibis

+1

Когда я помогал вам ранее, вы использовали GNU-ассемблер, а не Microsoft. Как указывает @Michael, синтаксис inline Visual C++ в VS довольно сильно отличается от ассемблера GNU. VC++ не поддерживает ассемблерные шаблоны, которые являются расширением GCC, недоступны в продуктах MS. –

ответ

3

Visual Studio в VC++ не поддерживает GNU шаблоны Ассемблер доступны в GCC Поскольку вы определяете port как 16-разрядное целое число без знака, вам необходимо использовать форму OUT, которая принимает 16-разрядный номер порта. Вам нужно поместить 16-битный номер порта в DX. Вам также нужно лечить имена переменных в встроенной сборке в качестве указателей, поскольку вы используете стандарт CDECL конвенция о созыве для ваших функций. Пример кода:

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

Функция inb можно было бы сделать что-то вроде:

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

Это может быть упрощены путем удаления переменной data и хранения характер чтения в переменную port, а затем делать return (uint8_t)port; , Так что это также будет работать:

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; 
} 

Подробнее об использовании VC++ ассемблерные можно найти в Microsoft Developer Network (MSDN) documentation

+0

Я бы не назвал это упрощением. – immibis

+0

@immibis Упрощение является субъективным, хотя в этом случае мы просто повторно используем уже имеющуюся переменную. Я бы признал, что последний пример страдает плохой читаемостью кода. –