+142
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
// main.cpp
#include <stdio.h>
#include <stdlib.h>
//...
#include "tcp.h"
//...
#include "tcp.c"
//...
int main(int argc, char ** argv)
{
//...
receive_tcp_message(sock, &tcp_msg);
switch(tcp_msg.type)
{
#include "cases.h"
default:
break;
}
//...
}
Имелась небольшая утилита, написанная матёрым сишником. Имелся еще меньший шаблонный проект для таких утилит, написанный на плюсах с простым makefile. Таким вот нехитрым способом этот сишник влил первое во второе. Он не пользуется makefile, т.к. обычно пишет шелл-скрипт, собирающий весь проект. А еще он знает кучу анекдотов и историй, выпить не дурак и вообще отличный дядька.
Запостил:
Xom94ok,
24 Июля 2013
Старые Сишники они походу все такие ;)
> Он не пользуется makefile, т.к. обычно пишет шелл-скрипт, собирающий весь проект.
Писать мейкфайл руками - занятие неблагодарное, муторное и довольно бесполезное. Я тоже пишу шелл-скрипт для фигни из одного-двух файликов (а иногда просто вбиваю в консоли gcc -O2 some.c other.c и жму стрелку вверх, когда надо собрать ;). Ну а для более серьезных случаев есть qmake и cmake.
В четвертом QNX нет ни того, ни другого, так что магия универсальных makefile рулит :)
Странное какое-то оборудование... Ведь, имхо, проще и дешевле запаять rs-232 или 485 чем ставить какой-никакой видеоадаптер и контроллер клавы...
> кроме монитора и клавиатуры
Т.е. весь код перебивается руками? :)
А может там делается особая железка, подключаемая в PS/2 порт и имитирующая клавиатуру, и через нее код набивается автоматически? Так можно и бинарники передавать сразу.
↓↓↓↓↓↓↓↓↓↓↓↓↓
Для каких устройств, если не секрет?
Однако, есть подозрение, что люди, далёкие от лоулевела, любую прошивку могут назвать «биосом».
Есть гипотеза, что он всё-таки разрабатывал не биосы, а прошивки.
Ты видел, как в «популярных» журналах называли системный блок процессором?
Не знаю как с дисками, но универсальный драйвер древних видюх переключается в 16 бит, запускает там option rom видюхи и дёргает int 10h для перечисления и переключения режимов. Обработчики прерываний во время этих вызовов, в принципе, будут работать. В остальное время - нет.
Ну и потом 16-битный загрузчик операционки в этом же окружении будет запущен.
Он переключается из «длинного» режима или запускает мумулятор процессора, находящегося в реальном режиме?
А в 16-битном сегменте защищённого режима в регистрах CS, DS, SS, ES, FS, GS должен лежать валидный селектор сегмента.
2. Размер GDT — 8192 дескриптора. Максимальный номер дескриптора 0x1FFF. Положение дескриптора совпадает со значением селектора. Значит, мы не сможем поместить программу в сегмент выше 0x1FFF. А это не вариант: BIOS обычно в сегменте 0xF000, а его option ROM — в предыдущих сегментах (начиная с 0xC000, потому что ниже располагается окно в видеопамять текстового режима).
3. Программа из option ROM может лазить в BDA (см. ниже) и в BIOS, чтобы подглядеть настройки.
4. В программе могут быть хакерские приёмы, основанные на том, что в реальном режиме адрес — это seg*16+ofs, поэтому в сегментном регистре может оказаться невалидная питушня.
Программа реального режима может это сделать, обратившись к ячейке как к 0:0x417 или как к 0x40:0x17 (теоретически может даже как к 0x41:7, вообще возможно несколько вариантов). В защищённом программа сломает зубы. Чтобы ей помочь, нужно создать селектор 0 с базой 0, селектор 0x40 с базой 0x400 и так далее.
В GDT есть место для 8192 дескрипторов. Чтобы любая программа реального режима гарантированно работала, дескрипторов должно быть 65536.
Два младших бита — номер кольца. Для ring 0 это будет 0, для ring 3 будет 3 (где-то тут пробегал кэп). Бит перед ними — выбор между LDT и GDT.
Т. е. для доступа на уровне нулевого кольца можно использовать только селекторы, оканчивающиеся на 16-ричную цифру 0, 8 (будут взяты из GDT) либо 4, C (будут взяты из LDT).
А упомянутые мной числа 0..1FFF нужно сдвинуть на три бита. Т. е. можно использовать диапазон (0..FFFF), но на младшие биты будут ограничения (иначе доступ будет из другого кольца).
Короче, работать не будет. Дизассемблировать и переписать и то проще, чем создать костыльное окружение.
Ну собственно виртуалки так и делали пока интел хуи пинал.
Итак, есть три режима:
• Реальный.
• «Короткий» защищённый. Доступны сегменты v86, 16-битные, 32-битные.
• «Длинный» защищённый. Доступны сегменты 16-битные, 32-битные, 64-битные.
Скорее винда боится, что этот код ей что-нибудь навернёт. А с эмулятором у неё всё под контролем.
Буквы через int 10h выводят, но в крайне редких случаях: когда режим графический (в таком режиме выводить текст через видеопамять нельзя), но при этом заморачиваться с рендерингом шрифта лень.
В серьёзных программах такой способ вывода применяют редко, потому что портится фон, BIOS может какой-то из размеров шрифта не поддерживать... В общем, надёжнее самому шрифт отрендерить.
Тем не менее, в «наколеночных» программах этот способ встречается хотя бы ради возможности вводить текст через scanf/std::cin/readln/input.
А команды 0Ch и 0Dh в int 10h тогда что делают? Просто это медленно и нахуй никому не нужно.
Почему же эти функции никто не использовал?
Из-за скорости, я думаю. Вывод пикселя - это же самая "горячая" операция, её инлайнить надо по-хорошему. А тут целый сисколл на каждый пиксель.
Я и вывод текста через int 10h то юзал только для того, чтобы шрифты у прошивки спиздить...
А чем INT 10h, INT 13h хуже?
P.S. А в Линуксе сисколлы были через INT 80h.
А в Windows 3.x, 95, 98, Me сисколлы из нулевого кольца (из vxd-драйверов) были через INT 20h.
В режимах plane map (640×480, 640×350) эти функции совершают по четыре переключения плоскости каждый вызов, что приводит к диким тормозам. Программа же может эти переключения делать реже, упорядочивая вывод изображения по цветовым плоскостям.
А в режиме pixel map (320×200) эти функции и даром не нужны, потому что можно срать в видеопамять и течь.
Допустим, нам нужно залить каким-нибудь цветом прямоугольник размером 500×400 пикселей (итого 200 тыс. пикселей) в режиме «plane map».
Если программа будет делать это напрямую, она сначала выберет красную плоскость, выведет красные компоненты пикселей, потом выберет зелёную плоскость, потом синюю, потом плоскость яркости... Итого будет 4 переключения на всю заливку.
Если же мы будем заливать этот прямоугольник через BIOS, то плоскости будут переключаться для каждого пикселя, итого переключение плоскостей отнимет времени в 200 тысяч раз больше, чем если бы мы обращались к железу напрямую.
А в режимах SVGA/VESA (1024×768 и выше) разница уже будет в миллион раз и больше.
Какие тормоза )))
Иди в отдел маркетинга работать с такими расчётами. Само рисование пикселя у нас уже за 0 тактов идёт? Да и в SVGA на плоскости уже забили.
>> Да и в SVGA на плоскости уже забили.
Точно. В SVGA видеопамять уже не отображается на первый мегабайт, поэтому там окно в видеопамять разработано настолько, что может вместить це́лую страницу за раз.
Ну в этом и суть. Вроде и не наёб, а звучит как ускорение в 200к раз. На самом деле там разница всего раз в 20-30 скорее всего.
В отличие от х86, где немножко асма всё-таки требуется.
А всякие мелочи типа запрета прерываний - интринсики.
А на x86 выдумали какие-то иопорты и кот вперемешку с даннымы который запускался в анальном режиме в какой-то жопе.
Остановите борманда, но в шаге от изобретения аутолулз
Но где?
Эх не умеете читать внутри строчек... Вот тут:
> Имелся еще меньший шаблонный проект для таких утилит, написанный на плюсах с простым makefile.
Любопытно, как выглядит этот самый "cases.h", который якобы на плюсах, но который неплохо смотрится в чисто сишном коде.
Обвинения "где main.cpp" вполне справедливы: это сишный код, всунутый в крестовый по самые гланды
>>как выглядит этот самый "cases.h"
Как обычно выглядит содержимое свитча? case value: do_shit(); break; и таких кейсов строк на 100.
У него (сишника) я когда-то увидел аналогичный "трюк", но примененный к enum: В общем, без грамма иронии, я от всей души желаю ему крепкого здоровья и долгих лет.
Вроде в элитных американских униках принято студенческие клубы называть тремя греческими буквами