1. Си / Говнокод #13470

    +142

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 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

    Комментарии (91) RSS

    • > А еще он знает кучу анекдотов и историй, выпить не дурак и вообще отличный дядька.
      Старые Сишники они походу все такие ;)

      > Он не пользуется makefile, т.к. обычно пишет шелл-скрипт, собирающий весь проект.
      Писать мейкфайл руками - занятие неблагодарное, муторное и довольно бесполезное. Я тоже пишу шелл-скрипт для фигни из одного-двух файликов (а иногда просто вбиваю в консоли gcc -O2 some.c other.c и жму стрелку вверх, когда надо собрать ;). Ну а для более серьезных случаев есть qmake и cmake.
      Ответить
      • >> Ну а для более серьезных случаев есть qmake и cmake.
        В четвертом QNX нет ни того, ни другого, так что магия универсальных makefile рулит :)
        Ответить
        • Хм. А мне казалось, что под самим куниксом никто никогда не компилит... Думал, что только кросскомпиляция, только хардкор. Сколько разрывов шаблона приносит гк.
          Ответить
          • Скорее всего, так оно и есть (особенно в QNX 6, в котором gcc), просто к некоторому оборудованию физически нельзя подключить ничего, кроме монитора и клавиатуры.
            Ответить
            • > к некоторому оборудованию физически нельзя подключить ничего, кроме монитора и клавиатуры
              Странное какое-то оборудование... Ведь, имхо, проще и дешевле запаять rs-232 или 485 чем ставить какой-никакой видеоадаптер и контроллер клавы...

              > кроме монитора и клавиатуры
              Т.е. весь код перебивается руками? :)
              Ответить
              • > Т.е. весь код перебивается руками? :)
                А может там делается особая железка, подключаемая в PS/2 порт и имитирующая клавиатуру, и через нее код набивается автоматически? Так можно и бинарники передавать сразу.
                Ответить
      • А я ассемблерщика знаю. Пишет биосы. Играет с ботами в квейк. С работы уходит последним. В 40 живет с мамой.
        Ответить
        • Какой квейк? Первый?
          Ответить
        • > Пишет биосы.
          Для каких устройств, если не секрет?
          Ответить
          • Для первых пентиумов, вестимо. Какие нахуй в 2020 биосы?
            Ответить
            • Может быть, он не для ПК, а для микроволновок пишет?
              Ответить
              • Ну это уже обычно прошивкой называют, а не биосом.
                Ответить
                • Вообще да, «BIOS» — это же чуть ли не фирменное название для «IBM PC». Для всех остальных устройств это называется просто прошивкой.

                  Однако, есть подозрение, что люди, далёкие от лоулевела, любую прошивку могут назвать «биосом».
                  Ответить
            • показать все, что скрытоvanished
              Ответить
              • Даже для 2013-го это наказание. Это всё равно, что сейчас разрабатывать карбюратор для «ВАЗ-2106» или коробку передач для «Москвича-412».

                Есть гипотеза, что он всё-таки разрабатывал не биосы, а прошивки.

                Ты видел, как в «популярных» журналах называли системный блок процессором?
                Ответить
                • Ну может он UEFI пилил, его тоже часто биосом называют? Хотя в UEFI асма не больше чем в обычных операционках, на самом деле.
                  Ответить
                  • показать все, что скрытоvanished
                    Ответить
                  • показать все, что скрытоvanished
                    Ответить
                    • Option ROM эта штука вроде зовётся. Для UEFI в нём, к слову, лежит полноценный PE файл с драйвером. Так что ничего он там уже не подменяет, просто публикует протоколы с GUID'ами...
                      Ответить
                      • показать все, что скрытоvanished
                        Ответить
                        • показать все, что скрытоvanished
                          Ответить
                        • Да, там 2 образа лежит. На самом деле UEFI умеет и старый 16-битный ром запускать. Ради древних видюх где нормального драйвера нет.
                          Ответить
                          • показать все, что скрытоvanished
                            Ответить
                            • Немножко умеет, если CSM включен.

                              Не знаю как с дисками, но универсальный драйвер древних видюх переключается в 16 бит, запускает там option rom видюхи и дёргает int 10h для перечисления и переключения режимов. Обработчики прерываний во время этих вызовов, в принципе, будут работать. В остальное время - нет.

                              Ну и потом 16-битный загрузчик операционки в этом же окружении будет запущен.
                              Ответить
                              • Проблема с древними биосами не в том, что им требуется 16 бит (16-битные сегменты бывают и в защищённом режиме), а в том, что им требуется реальный режим или V86.

                                Он переключается из «длинного» режима или запускает мумулятор процессора, находящегося в реальном режиме?
                                Ответить
                                • показать все, что скрытоvanished
                                  Ответить
                                  • Там адресация другая. В реальном и в V86 линейный адрес получается тупо как segment*16+offset, а таблица дескрипторов игнорируется.

                                    А в 16-битном сегменте защищённого режима в регистрах CS, DS, SS, ES, FS, GS должен лежать валидный селектор сегмента.
                                    Ответить
                                    • показать все, что скрытоvanished
                                      Ответить
                                      • 1. Этому коду нужно помочь. Нужно в GDT создать дескриптор, у которого база совпадает с его номером.

                                        2. Размер GDT — 8192 дескриптора. Максимальный номер дескриптора 0x1FFF. Положение дескриптора совпадает со значением селектора. Значит, мы не сможем поместить программу в сегмент выше 0x1FFF. А это не вариант: BIOS обычно в сегменте 0xF000, а его option ROM — в предыдущих сегментах (начиная с 0xC000, потому что ниже располагается окно в видеопамять текстового режима).

                                        3. Программа из option ROM может лазить в BDA (см. ниже) и в BIOS, чтобы подглядеть настройки.

                                        4. В программе могут быть хакерские приёмы, основанные на том, что в реальном режиме адрес — это seg*16+ofs, поэтому в сегментном регистре может оказаться невалидная питушня.
                                        Ответить
                                  • Реальный пример. Недавно мы обсуждали BDA — BIOS data area. Мы хотим зажечь индикатор «Num Lock». Для этого в ячейку по линейному адресу 0x417 нужно что-то положить.

                                    Программа реального режима может это сделать, обратившись к ячейке как к 0:0x417 или как к 0x40:0x17 (теоретически может даже как к 0x41:7, вообще возможно несколько вариантов). В защищённом программа сломает зубы. Чтобы ей помочь, нужно создать селектор 0 с базой 0, селектор 0x40 с базой 0x400 и так далее.

                                    В GDT есть место для 8192 дескрипторов. Чтобы любая программа реального режима гарантированно работала, дескрипторов должно быть 65536.
                                    Ответить
                                    • Ты ещё не забывай, что селекторы - это не просто номера сегментов. Там в младших битах выбор между GDT/LDT и уровень привилегий закодирован. Т.е. это вообще в принципе работать не будет. Даже если бы их и хватило.
                                      Ответить
                                      • Спасибо. Мы где-то обсуждали, почему какие-то из селекторов чётные, а какие-то — нечётные.

                                        Два младших бита — номер кольца. Для ring 0 это будет 0, для ring 3 будет 3 (где-то тут пробегал кэп). Бит перед ними — выбор между LDT и GDT.

                                        Т. е. для доступа на уровне нулевого кольца можно использовать только селекторы, оканчивающиеся на 16-ричную цифру 0, 8 (будут взяты из GDT) либо 4, C (будут взяты из LDT).

                                        А упомянутые мной числа 0..1FFF нужно сдвинуть на три бита. Т. е. можно использовать диапазон (0..FFFF), но на младшие биты будут ограничения (иначе доступ будет из другого кольца).

                                        Короче, работать не будет. Дизассемблировать и переписать и то проще, чем создать костыльное окружение.
                                        Ответить
                                        • > дизассемблировать и переписать

                                          Ну собственно виртуалки так и делали пока интел хуи пинал.
                                          Ответить
                                        • показать все, что скрытоvanished
                                          Ответить
                                          • v86 в «длинном» режиме 64-битного процессора нет. Нужно переключаться в «короткий», в котором 64-битные сегменты недоступны.

                                            Итак, есть три режима:
                                            • Реальный.
                                            • «Короткий» защищённый. Доступны сегменты v86, 16-битные, 32-битные.
                                            • «Длинный» защищённый. Доступны сегменты 16-битные, 32-битные, 64-битные.
                                            Ответить
                                • Полностью переключается в реальный режим, насколько я видел. Нету там особого смысла в эмуляторе.
                                  Ответить
                                  • А в 64-битной Винде навернули эмулятор, потому что её не устраивает скорость переключения туда и обратно?
                                    Ответить
                                    • На скорость всем насрать, ты видеорежим не так часто меняешь. А пиксели и буквы через int 10h даже в досе никто не рисовал...

                                      Скорее винда боится, что этот код ей что-нибудь навернёт. А с эмулятором у неё всё под контролем.
                                      Ответить
                                      • BIOS вообще ничего не знает про пиксели. У него API только для текстовых режимов. Поэтому пиксели в DOS'е каждая программа выводит средствами собственной библиотеки.

                                        Буквы через int 10h выводят, но в крайне редких случаях: когда режим графический (в таком режиме выводить текст через видеопамять нельзя), но при этом заморачиваться с рендерингом шрифта лень.

                                        В серьёзных программах такой способ вывода применяют редко, потому что портится фон, BIOS может какой-то из размеров шрифта не поддерживать... В общем, надёжнее самому шрифт отрендерить.

                                        Тем не менее, в «наколеночных» программах этот способ встречается хотя бы ради возможности вводить текст через scanf/std::cin/readln/input.
                                        Ответить
                                        • > не знает про пиксели

                                          А команды 0Ch и 0Dh в int 10h тогда что делают? Просто это медленно и нахуй никому не нужно.
                                          Ответить
                                          • Я лох. Не знал. Спасибо за информацию.

                                            Почему же эти функции никто не использовал?
                                            Ответить
                                            • > никто не использовал

                                              Из-за скорости, я думаю. Вывод пикселя - это же самая "горячая" операция, её инлайнить надо по-хорошему. А тут целый сисколл на каждый пиксель.

                                              Я и вывод текста через int 10h то юзал только для того, чтобы шрифты у прошивки спиздить...
                                              Ответить
                                          • Вообще я догадываюсь, почему они не были популярны.

                                            В режимах plane map (640×480, 640×350) эти функции совершают по четыре переключения плоскости каждый вызов, что приводит к диким тормозам. Программа же может эти переключения делать реже, упорядочивая вывод изображения по цветовым плоскостям.

                                            А в режиме pixel map (320×200) эти функции и даром не нужны, потому что можно срать в видеопамять и течь.
                                            Ответить
                                            • Кстати, давайте оценим масштаб тормозов.

                                              Допустим, нам нужно залить каким-нибудь цветом прямоугольник размером 500×400 пикселей (итого 200 тыс. пикселей) в режиме «plane map».

                                              Если программа будет делать это напрямую, она сначала выберет красную плоскость, выведет красные компоненты пикселей, потом выберет зелёную плоскость, потом синюю, потом плоскость яркости... Итого будет 4 переключения на всю заливку.

                                              Если же мы будем заливать этот прямоугольник через BIOS, то плоскости будут переключаться для каждого пикселя, итого переключение плоскостей отнимет времени в 200 тысяч раз больше, чем если бы мы обращались к железу напрямую.

                                              А в режимах SVGA/VESA (1024×768 и выше) разница уже будет в миллион раз и больше.

                                              Какие тормоза )))
                                              Ответить
                                              • > в 200 тысяч раз

                                                Иди в отдел маркетинга работать с такими расчётами. Само рисование пикселя у нас уже за 0 тактов идёт? Да и в SVGA на плоскости уже забили.
                                                Ответить
                                                • Я написал: «переключение плоскостей отнимет времени в 200 тысяч раз больше». Наш отдел посчитал только переключение плоскостей. А подсчётом скорости рисования пикселей другой отдел занимается.

                                                  >> Да и в SVGA на плоскости уже забили.

                                                  Точно. В SVGA видеопамять уже не отображается на первый мегабайт, поэтому там окно в видеопамять разработано настолько, что может вместить це́лую страницу за раз.
                                                  Ответить
                                                  • > наш отдел посчитал только переключение плоскостей

                                                    Ну в этом и суть. Вроде и не наёб, а звучит как ускорение в 200к раз. На самом деле там разница всего раз в 20-30 скорее всего.
                                                    Ответить
                                    • показать все, что скрытоvanished
                                      Ответить
                    • Ну и да, асма в этих дровах сейчас ровно ноль строк.
                      Ответить
        • показать все, что скрытоvanished
          Ответить
      • >Писать мейкфайл руками - занятие неблагодарное, муторное и довольно бесполезное.
        Остановите борманда, но в шаге от изобретения аутолулз
        Ответить
    • > main.cpp

      Но где?
      Ответить
      • Дык это ж он и есть :)
        Ответить
        • Эх, не умеете читать между строчками... Код правильно помещён в раздел Си, но назвался груздем — полезай в кузов «main.cpp» — показывай «cpp». Но где?
          Ответить
          • > Эх, не умеете читать между строчками...
            Эх не умеете читать внутри строчек... Вот тут:
            > Имелся еще меньший шаблонный проект для таких утилит, написанный на плюсах с простым makefile.
            Ответить
            • Слона-то я и не заметил. ГК приучил искать подводные камни, поэтому того, что на поверхности, я уже не замечаю...

              Любопытно, как выглядит этот самый "cases.h", который якобы на плюсах, но который неплохо смотрится в чисто сишном коде.
              Ответить
              • >>на плюсах <...> в чисто сишном коде
                Обвинения "где main.cpp" вполне справедливы: это сишный код, всунутый в крестовый по самые гланды

                >>как выглядит этот самый "cases.h"
                Как обычно выглядит содержимое свитча? case value: do_shit(); break; и таких кейсов строк на 100.

                У него (сишника) я когда-то увидел аналогичный "трюк", но примененный к enum:
                //values.inc
                VALUE1 = 60,
                VALUE2,
                VALUE3,
                
                //constants.inc
                CONSTANT1 = 90,
                CONSTANT2,
                CONSTANT3
                
                //enm.h
                enum
                {
                #include "values.inc"
                #include "constants.inc"
                };
                В общем, без грамма иронии, я от всей души желаю ему крепкого здоровья и долгих лет.
                Ответить
          • Okay.jpg
            Ответить
    • PCH не нужны. Только Unity builds.
      Ответить
    • показать все, что скрытоvanished
      Ответить

    Добавить комментарий