void func1()
{
//bla-bla
}
void func2()
{
asm("..."); // какие-то инструкции
asm("call _func1");
}
Inline assambler
У меня такой вопрос: почему нельзя сделать так (компилятор MinGW-3.1.0-1)?:
void func1()
{
//bla-bla
}
void func2()
{
asm("..."); // какие-то инструкции
asm("call func1");
}
Подскажите что-нибудь по этому поводу, пожалуйста.
если код на C то будет правильно так:
Код:
Если C++ юзаем extern "C"
Вот пример из вижуала (микрософт, как обычно, выпендрился):
Код:
__asm {
mov al, 2
mov dx, 0xD007
out dx, al
}
mov al, 2
mov dx, 0xD007
out dx, al
}
Код:
asm {
mov ax, 0x0e07
xor bx, bx
int 0x10 // makes the system beep
}
mov ax, 0x0e07
xor bx, bx
int 0x10 // makes the system beep
}
Думаю, MinGW в этом отношении от них недалеко ушёл. К тому же, информация о asm есть в половине книжек по С.
.nornad, вообще-то речь шла об inline assembler'е в MinGW...
Читаем стандарт:
Цитата:
7.4 The asm declaration [dcl.asm]
1 An asm declaration has the form
asm-definition:
asm ( string-literal ) ;
The meaning of an asm declaration is implementation-defined.
А asm-инструкция разве не инлайновая? Тоже ведь тупо в код вставляет ассемблер.
Цитата:
Читаем стандарт:
Спасибо за цитату, в стандарт заглядываю редко. Думал, раз у микрософта и борланда различия минимальные, то они по стандарту рисуют. Выходит, что они практически одинаково отошли от стандарта...
Спасибо за объяснение, хотя я и сам по-позже разобрался :)
И ещё вопрос: я написал что-то на подобе мини-ядра, организовал простейшую обработку прерываний (с IRQ0 по IRQ255). Всё хорошо, только комп ВСЁ время через 12 сек. после загрузки перезагружается. 12 сек стабильно. Несколько раз проверял. В чём может быть дело?
IRQ255 - это круто! Думаю, что даже в документации по APIC я такого не найду :) А вообще я хоть и фантом, но все-таки не телепат, и поэтому, как обычно говорят в таких случаях: "Исходники в студию!"
Ramon.
Спасибо за объяснение.
Вот ОНО.
Посмотрел. Если кратко, то не понятно как это все будет запускаться и работать, но самое главное IRQ255 иногда всплывает только в BIOS'ах для обозначения неизвестного или неопределенного номера IRQ. Я использую лишь обработчики для IRQ0-IRQ15. Только без обид, но твои исходники мне ясно дали понять, что ты не ориентируешься в том, что пишешь. У тебя там даже проскакивают моменты несоответствия значений параметров тем типам, которыми они описываются (ну нет смысла передавать значение 0x255 через параметр типа unsigned char), а также ты как-то криво сопоставляешь шестнадцатеричным значениям "векторов" названия соответствующих обработчиков (в записях типа IRQ255 по смыслу понятно, что в них используются десятичные номера; опять-таки исходя исключительно из здравого смысла нелогично с ними сопоставлять шестнадцатеричные числа такого же вида 0x275, хоть и со смещением 0x20; а после 0x79, например, следующим по порядку будет число 0x7A, а не 0x80 - ты вообще в курсе, что такое шестнадцатеричная система счисления)...
Насчет того, что я не ориентируюсь в том, что пишу: да, есть немного. Что поделаешь, все мы когда-то начинали. Так что твое замечание не в обиду, а на пользу :)
Насчет запуска и работы: Там все работает просто (больше половины я сам написал, так что мне там все понятно). Сейчас вроде все работает, но было бы неплохо, если бы ты все же помог мне разобраться, в чем была ошибка. Если не влом. Если влом, то ладно.
Вобщем, все равно спасибо за затраченное время.
И ещё: подскажи, пожалуйста, как считать/записать сектор с дискеты в защищённом режиме? С примером, если можно, или подробным объяснением.
Файл вроде бы так называется: \??\A:
Не, ты не понял. Я ж не из под Винды работаю. Это что-то наподобе очень недаделанного ядра операционки. Хотел именно добавить эти функции. Но в защищенном режиме int 13h не покатит. Там надо через порты осуществлять. Тока как? Какие порты (номера), какие регистры использовать, ...?
Начнем с того, что это не у меня устаревшая версия исходников, а это ты такую версию выложил.
Далее. Я тебе сказал, что нужно оставить только 16 обработчиков аппаратных прерываний. Местоположение в таблице прерываний ты выбрал хорошее (начиная с входа под номером 0x20), так многие делают и я в том числе. Только учти, что этот базовый номер нужно еще установить путем программирования контроллера прерываний. У тебя также неверно написан код обработчиков для прерываний, начиная с номера 8. Для них команда EOI (конец прерывания) реализуется немного сложнее, чем просто выполнение вывода значения 0x20 в порт 0x20.
Когда я писал, что не понимаю, как все это работает, то имел в виду, что совершенно непонятно, как и во что все это компилируется, а также чем загружается и в каком режиме процессора начинает работать. Ты должен мне все подробно об этом рассказать.
Теперь про чтение/запись секторов на дискете. Работа с дискетой на самом низком уровне - это задача, требующая для правильной реализации привлечения еще как минимум двух устройств - таймера и контроллера прямого доступа к памяти (если ты конечно не надумаешь читать данные с дискеты побайтово :) ), а также соблюдения всех этапов взаимодействия с дискетой со стороны твоей программы (инициализация, подача команд, получение результата и, возможно, повторная подача отдельных команд - при работе с дискетой это часто приходится делать, потому что устройство само по себе ненадежное). Если коротко, то я хочу сказать, что тебе еще рано начинать работать с дискетой, т.к. еще не решено много более первостепенных задач. Когда это сделаешь, я тебе объясню, как именно в твоей конкретной ситуации осуществить работу с дискетой.
Компилируется в чистый бинарник (*.com/*.bin). Загружается загрузчиком, (его код я не выкладывал, но там уже устанавливается базовый номер.) в PM. Насчет прерываний: сначала все обработчики (пустые) я делаю как для программных прерываний, потом только нужные как аппаратные. Хотя... можно убрать всю эту бодью в 59 kb. Смысла большого, наверное нет.