Я использую QTCreator 3.5.1 и виртуальную ОС Linux Mint 18.3 Cinnamon 32-bit, компилятор GCC.
Мне нужно написать код, который использует прерывания, получая нажатие клавиши на клавиатуре с помощью ассемблерных команд.
Код, который должен был работать в Windows, выглядит следующим образом:
#include <iostream>
unsigned char x;
int main()
{
do {
__asm {
mov ah, 00h
int 16h
mov x, ah
};
std::cout <<"The pressed key code is "<< x << std::endl;
} while (true);
}
Хотя он не работает ни в Windows 98, ни в скомпилированном с помощью Visual Studio 2003 в Windows 7x32, ни в любых других системах Windows, что приводит к ошибке во время выполнения или завершению работы моей системы (в Windows 98).
Поэтому я переключился на Linux, и следующий пример кода сборки из http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html (часть 7) работает очень хорошо:
#include <iostream>
using std::cout;
int main(void)
{
int foo = 10, bar = 15;
__asm__ __volatile__("addl %%ebx,%%eax"
:"=a"(foo)
:"a"(foo), "b"(bar)
);
printf("foo+bar=%d\n", foo);
return 0;
}
(Чтобы он работал правильно, мне также пришлось указать версию компилятора (GCC x86 32bit в usr/bin) в «Desktop Kit» в QT Creator Tool-> Options и рабочую версию QT 4.8.7, последняя версия 5.5 .1 выдает ошибку "установлен неправильно, пожалуйста, запустите make install")
Хотя я изо всех сил пытаюсь понять концепцию прерываний и как прерывание «int 16h» должно работать в Linux со встроенной сборкой GCC, каков синтаксис и как я могу получить код любой нажатой клавиши клавиатуры?
int 16h — это служба BIOS. Он работает только в реальном режиме и обычно используется в загрузчиках или программах DOS. К нему нельзя получить доступ ни из Windows (любая версия, если только не выполняется программа DOS, в этом случае служба эмулируется), ни из Linux (любая версия), ни из любой другой операционной системы защищенного режима в этом отношении.
В упражнении указано, что вы должны использовать int 16h? Какие еще подробности указаны? Вы можете читать входные данные, используя встроенный ассемблер в Linux (хотя я бы не рекомендовал делать это вне учебных занятий). В Windows это тоже возможно, но правильный вызов зависит от версии Windows.
@fuz, да. В этом проблема, в моем академическом упражнении указано, что я должен использовать int 16h
@IvanSilkin Вы уверены, что они не хотят, чтобы вы написали программу для DOS или загрузчик? Вы можете писать программы на C для DOS с помощью встроенного ассемблера, используя некоторые старые наборы инструментов, что позволит вам выполнить это упражнение. Двумя недавними поддерживающими это являются ia16-gcc и Open Watcom, хотя требуется некоторая возня, чтобы заставить их выдавать рабочие двоичные файлы.
По словам людей из #winapi в Freenode, возможно, действительно можно было вызвать int 16h из программы Win32 в Windows 98, но тогда вызов мог привести к зависанию в BIOS. Очень странно.
@fuz, да, система зависает и ничего не распознает, кроме ctrl+alt+del.
@IvanSilkin Попробуйте уговорить Visual Studio создать приложение Win16 или DOS.
Вы уверены, что вам не сказали использовать Turbo-C++ (или Borland C) для написания программы для DOS. У вас есть полная копия задания, которое вы можете опубликовать здесь, чтобы показать нам, в чем именно состоит ваше задание? Единственная другая вещь, о которой я могу думать, это если бы вы использовали что-то вроде MSVC 1.52, у которого была версия C++, которая все еще могла генерировать программы для DOS. Если у вас установлена 32-разрядная версия Windows, эта программа DOS будет работать внутри виртуальной машины WIndows DOS (NTVDM).
@fuz, ваш комментарий от «23 декабря в 1:43» дал мне статус завершения практической работы, не могли бы вы также записать его как ответ?





Для современных систем; во время загрузки ОС берет на себя управление всем оборудованием из прошивки, и после этого прошивка становится непригодной для использования (поскольку нельзя предполагать, что ни одно из аппаратных средств не находится в состоянии, ожидаемом прошивкой). Затем ОС запускает свои собственные драйверы, которые предназначены для ОС, и используют IRQ, и работают с планировщиком операционной системы (и не тратят время на опрос ЦП), и работают для нескольких ЦП, и правильно поддерживают память (и не t ограничен 640 КиБ).
Это означает, что прерывание BIOS «int 0x16» может работать, только если:
а) Вы используете ОС, ставшую неактуальной более 20 лет назад (MS-DOS)
б) Вы используете ОС, которая выполняет много дополнительной работы для эмуляции ОС, которая стала неактуальной более 20 лет назад (например, «устаревшая совместимость с DOS», встроенная в Windows95, а не какой-либо исполняемый файл Windows, предназначенный для Windows).
c) Вы не используете операционную систему, а компьютер настолько старый, что в нем установлена прошивка BIOS (вместо этого новые компьютеры перешли на UEFI).
Мне нужно написать код, который использует прерывания, получая нажатие клавиши на клавиатуре с помощью ассемблерных команд.
Я бы еще раз проверил, что ты должен делать. Например. «использует прерывание» может означать «использование старого 32-битного API-интерфейса ядра Linux (int 0x80), а не устаревших функций BIOS» (и это может означать «использование устаревшего чипа контроллера PS/2 IRQ (как это делает драйвер устройства)» , или что-то другое).
Более конкретно; Я предполагаю, что вы следовали инструкциям, которые включали «установить старую 32-разрядную версию Linux на виртуальную машину», потому что вы должны использовать старый API ядра Linux («int 0x80») для выполнения эквивалента « read(STDIN_FILENO, buffer, 1);" на языке ассемблера (чтобы получить байт из чего бы то ни было stdin, который может или не может быть получен с клавиатуры в зависимости от того, как ваш исполняемый файл запускается/используется).
Сервис int 16h — это сервис BIOS. Он работает только в реальном режиме и обычно используется в загрузчиках или программах DOS. К нему нельзя получить доступ ни из Windows (любая версия, если только не выполняется программа DOS, в этом случае служба эмулируется), ни из Linux (любая версия), ни из любой другой операционной системы защищенного режима в этом отношении.
По словам людей из #winapi в Freenode, возможно, было бы возможно вызвать int 16h из программы Win32 в Windows 98, но тогда вызов может привести к зависанию в BIOS. В любом случае, это не полезно для достижения вашей цели.
Чтобы решить вашу проблему, либо напишите программу для DOS, используя цепочку инструментов DOS, такую как ia16-gcc, Open Watcom или старую версию MSVC, либо используйте службу защищенного режима, поддерживаемую операционной системой, для которой вы программируете.
Поскольку вы работаете с Qt (очевидно), не было бы более уместно использовать что-то вроде this, а не пытаться перехватывать события клавиатуры на уровне биоса (что вряд ли будет настроено на одно и то же прерывание в разных операционных системах). системы).