Проблема преобразования: __asm__ __volatile__

Некоторое время я имел дело с Nasm в среде Linux, и эта функция отлично работала ... но теперь я переключаюсь на среду Windows и хочу использовать Masm (с VS2008). Кажется, я не могу заставить это работать .. .

void outportb (unsigned short _port, unsigned short _data)
{
  __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}

Когда я пишу что-то подобное ...

void outportb (unsigned short _port, unsigned short _data)
{
  asm volatile ("outb %1, %0" : : "dN" (_port), "a" (_data));
}

asm больше не распознается, а volatile выдает ошибку с надписью "строка", я также пытался написать _asm volatile, но получаю сообщение об ошибке "синтаксическая ошибка встроенного ассемблера в 'коде операции'; обнаружен 'тип данных'"


person Fredrick    schedule 06.09.2009    source источник


Ответы (1)


Предполагая, что вы говорите о наборе команд x86, вот несколько вещей, которые следует запомнить:

  1. инструкция «outb» выводит один байт, что было бы эквивалентно типу «char» или «unsigned char» в C / C ++. Для вывода 16-битного (поскольку вы используете "unsigned short") слова нужно использовать "outw"
  2. При этом Intel рекомендует (и требует от VS) использовать мнемонику инструкций «out», и размер порта определяется по размеру операнда. Например, «out dx, ax» будет эквивалентно «outw», а «out dx, al» эквивалентно «outb».
  3. на x86 инструкция «out» требует, чтобы порт и выходное значение были помещены в регистры (e) dx и {eax / ax / al} соответственно. Хотя Nasm может сделать это за вас (у меня нет под рукой компилятора, поэтому я не могу это подтвердить), в VS вы должны делать это так, как это делается на уровне процессора.
  4. нет причин указывать ключевое слово volatile с __asm. Любые встроенные инструкции сборки заставляют компилятор VS отключать кеширование чтения (для чего предназначено ключевое слово volatile)

Вот код (при условии, что вы пишете в 16-битный порт):

void outportw(unsigned short port, unsigned short data)
{
    __asm  mov ax, data; 
    __asm  mov dx, port; 
    __asm  out dx, ax;
}

если вы пишете в 8-битный порт, код должен выглядеть так:

void outportb(unsigned short port, unsigned char data)
{
    __asm  mov al, data; 
    __asm  mov dx, port; 
    __asm  out dx, al;
}
person Rom    schedule 06.09.2009
comment
Также: вы можете использовать __asm ​​{инструкции здесь} для более ясного синтаксиса, и, возможно, стоит упомянуть, что встроенный asm не будет работать на x64, поэтому для этой архитектуры придется писать код asm в автономном коде. - person Marcin Deptuła; 06.09.2009
comment
Хорошо, теперь это имеет смысл, по крайней мере, я не получаю ошибок .. так что эквивалентно inportb? Я знаю, что вы пишете вместо out и, вероятно, меняете ax на al, верно? Или все сложнее? - person Fredrick; 06.09.2009
comment
Попробуйте, не должно быть больно. Помните, что VS использует порядок {операция} {назначение}, {источник}, поэтому для чтения порта это будет: __asm ​​in al, dx; а затем вам нужно сохранить результат в вашей переменной: __asm ​​mov data, al; и вернуть его из функции: return data; - person Rom; 06.09.2009
comment
как насчет unsigned char inportb (unsigned short _port) Я попытал счастья, просто переключившись на in и получил сообщение об ошибке неправильного типа операнда ... - person Fredrick; 06.09.2009
comment
попробуйте: unsigned char tmp; __asm ​​{mov dx, порт \ n в al, dx \ n mov tmp, al} return tmp; - person Marcin Deptuła; 06.09.2009
comment
Спасибо, сработало ... и я предполагаю сделать unsigned int inportw (unsigned short _port), мы меняем al на dx? хмммм это интересно ... - person Fredrick; 06.09.2009