1. Pascal / Говнокод #19045

    −47

    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
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    ; * WARNING WARNING WARNING WARNING WARNING WARNING WARNING *
    
    ;   Please do not try to use external procedures
    ;   unless you are familiar with assembly language.
    ;
    ;   IMPORTANT: Externals must be written in assembly language.
    ;
    ;   The following example translates a string to upper case.
    
    ;
    ;   Place the following code in a file: "STU.ASM"
    ;
    
    
    CODE    SEGMENT
            ASSUME     CS:CODE
    
    STU     PROC       NEAR
    
            PUSH       BP                    ; SAVE ENVIRONMENT
            MOV        BP,SP                 ; MANUAL PAGE 189
    
            LES        DI,[BP+4]             ; GET PARAMETER
            MOV        CL,ES:[DI]
            INC        CL
    L1:     DEC        CL
            JZ         L2
            INC        DI
            CMP        ES:BYTE PTR[DI],'a'
            JB         L1
            CMP        ES:BYTE PTR[DI],'z'
            JA         L1
            SUB        ES:BYTE PTR[DI],20H
            JMP        SHORT L1
    
    L2:     MOV        SP,BP                 ; RESTORE ENVIRONMENT
            POP        BP                    ; MANUAL PAGE 190
            RET        4
    STU     ENDP
    CODE    ENDS
            END
    
    ; Now exit to PC-DOS and type:
    ;
    ; ASM STU
    ; LINK STU
    ; EXE2BIN STU.EXE STU.COM
    ;
    ; IGNORE MINOR ERRORS FROM ASM AND LINK
    
    
    
    To use, write the following program:
    
    
    type
      AnyString = string[255];
    
    var
      S: AnyString;
      I: integer;
    
    
    procedure STU(var S: AnyString); external 'STU.COM';
    
    begin
      readln(S);
      STU(S);
      writeln(S);
    end.

    Turbo Pascal 3.0. Внешние процедуры/функции линковались не из OBJ-файла, а из COM-файлов. Один файл — одна функция, никакого обмена символами.

    Запостил: inkanus-gray, 18 Ноября 2015

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

    • Ты говоришь, я демон? Так и есть,
      Со мною не видать тебе удачи.
      Навеки моё дело — зло и месть,
      Для демона не может быть иначе!

      https://youtu.be/eqt2xLTatc8
      Ответить
    • а зачем нельзя разве написать скрипт который собирал в один файл исходники библиотек и компилировать все разом.
      Ответить
      • Поясните свою мысль.
        Ответить
        • Ну вместо того, что бы линковать из com собирать исходники в один файл и компилировать его.
          Ответить
          • Процедуры на Паскале даже без модульной системы можно собрать в один файл (например, с помощью директивы {$I}). Но исходники могут быть на разных языках. В один файл их не соберёшь, потому что компилятор не полиглот.

            В более новых Турбо Паскалях поддерживалась линковка OBJ-файлов и директива asm для вставок на Ассемблере. В 3.0 таких вкусностей не было, потому и придумали такой костыль.
            Ответить
          • Дополнение. Оказывается, можно было линковать один COM-файл и использовать из него несколько процедур, но для этого нужно было... указать смещение в байтах от начала COM-файла.

            const
              North = 0;
              East  = 90;
              South = 180;
              West  = 270;
            
            procedure Graphics;                                   external 'GRAPH.BIN';
            procedure GraphMode;                                  external Graphics[0];
            procedure GraphColorMode;                             external Graphics[3];
            procedure HiRes;                                      external Graphics[6];
            procedure HiResColor(Color: Integer);                 external Graphics[9];
            procedure Palette(N: Integer);                        external Graphics[12];
            procedure GraphBackground(Color: Integer);            external Graphics[15];
            procedure GraphWindow(X1,Y1,X2,Y2: Integer);          external Graphics[18];
            ... и так далее ...


            Начало модуля GRAPH.BIN — 28 джампов, каждый из которых занимает по три байта (отсюда и шаг, равный трём, в индексах). Самое смешное, что этот самый GRAPH.BIN дожил до Борман Паскаля 7.0 (декомпиляция GRAPH.TPU от BP 7.0 показывает, что в него целым куском включён тот самый GRAPH.BIN (вероятно, с модификациями), а остальные функции — обёртки над вызовами допотопного кода).
            Ответить
      • Слыш ты ослоеб, нахуй иди!
        Ответить
    • Кстати, все поняли, что в ассемблерном коде нельзя пользоваться смещениями, потому что заранее нельзя угадать, по какому смещению загрузится код? Т. е. стеком и джампами пользоваться можно, а константы и переменные размещать нельзя. Для их использования придётся мутить position-independent code, как в Линуксе.
      Ответить
      • Не поняли. Виртуальный адрес разве не будет постоянным?
        Ответить
        • На первом операторе процедуры STU, прилинкованной к главной программе, значение регистров CS:IP может быть любым.

          Настоящие COM-файлы DOS всегда грузит так, что в точке старта IP=100H (256 в десятичной системе).

          EXE-файлы могут грузиться по любому смещению от начала сегмента, но в них есть таблица перемещаемых символов, с помощью которой ОС патчит исполняемый образ при загрузке.

          А виртуальные адреса уже относятся к программам защищённого режима (в том числе и Windows), к которым данный пример не относится. И да, бывают приложения Windows как с фиксированным виртуальным адресом (без таблицы перемещаемых символов), так и с произвольным виртуальным адресом (с таблицей перемещаемых символов).
          Ответить
          • Тьху, ты про дос.

            >произвольным виртуальным адресом (с таблицей перемещаемых символов).
            Это как?
            Ответить
            • > Тьху, ты про дос.
              > Turbo Pascal 3.0.

              Действительно, трудно догадаться, для какой системы он был.

              Пересмотрел код ещё раз. По коду видно только, что он для 16-битной системы с сегментами, больше никаких особенностей. Теоретически такой же код можно было скомпилировать и для Windows 3.x, и для 16-битной OS/2 (если бы существовал подходящий компилятор).

              Ну тут даже и не важно, что он для ДОС. Важно то, что внешний двоичный образ (STU.COM) вклеивается в произвольное место программы, следовательно, адрес первой команды процедуры STU может быть случайным.

              В OBJ-файлах есть табличка перемещаемых данных, чтобы фиксить адреса при линковке. В COM-файле такой таблички нет.

              **********

              >>произвольным виртуальным адресом (с таблицей перемещаемых символов).
              > Это как?

              Ты не про виртуализацию, а про RVA, который присутствует в виндовых PE-файлах, в линуксовых ELF-файлах и в OBJ-файлах? Ну так если модуль загрузился по адресу, не совпадающему с RVA, то его надо фиксить, а для этого нужна таблица перемещаемых символов (релокейшнов/фиксапов).

              Что же касается виндовых экзешников, то их было два типа. Начиная с Windows 98 стали активно форсить экзешники, у которых при старте VA=RVA и табличка фиксапов отсутствует. Это позволяло сэкономить несколько килобайт (уже смешно) в экзе-файле и несколько наносекунд при старте программы. Для этого каждый экзешник помещался в своё адресное пространство.

              Но такое поведение не было обязательным. Как я уже написал, раньше собирали экзешники, способные запускаться при VA≠RVA. В частности у Win32s (32-битный API для Windows 3.x) не было поддержки виртуальных пространств, поэтому экзешники приходилось раздвигать по разным адресам.

              С появлением ASLR в Висте снова вспомнили про VA≠RVA и экзешники с табличкой фиксапов вернулись.
              Ответить
              • > В OBJ-файлах есть табличка перемещаемых данных, чтобы фиксить адреса при линковке. В COM-файле такой таблички нет.

                64К should be enough for everything.
                Ответить
              • А у линуха .so'шки вообще всегда в PIC режиме должны компилиться. Поэтому там ASLR без проблем прикрутили.
                Ответить
            • >>Тьху, ты про дос.

              Нет, он про OpenSolaris. У него регистры 16ти битные SP и BP. Угадай операционку по разрядности.
              Ответить
              • Виндоуз 3.1!
                Ответить
                • Это не операционка, так как она пользовалась DOS API (21h или как там оно прерыванне это)
                  Ответить
                  • Windows 3.1 уже могла работать с дисками в обход DOS через VXD. А могла и через DOS API.

                    Даже Windows 95/98/Me зачем-то использовали несколько вызовов DOS API, хотя теоретически они не были нужны...
                    Ответить
                    • давно уже общался с одним старым программером. Он говорил самое главное а программирование под дос это не использовать средства дос из за их тормознутости. Вывод на экран чрез прерывания биос, с дисками через контролер. И прочее прочее.
                      Ответить
                      • Вывод на экран через БИОС (а то и через порт видеокарты) использовали не из-за тормознутости ДОСа, а из-за его ограниченности. Консоль в новых Виндовсах и в Линуксе не быстрее досовской. Просто через досовскую консоль нельзя было построить сложный UI.

                        С дисками была проблема из-за отсутствия кэширования, но это решалось костылями типа smartdrive.

                        Кстати, с дисками через контроллер пользовательские программы не общались (за исключением специфических типа undelete/unerase, scandisk, defrag, diskedit, которым прямой доступ к дискам необходим). Кулхацкеры писали для себя драйвера, которые заменяли собой тормозные драйвера ДОСа или БИОСа, но в пользовательские программы это не совали.

                        Только представь себе, что для прямого обращения к диску через контроллер тебе придётся распарсить файловую систему, причём сделать это точно так же, как это делает ДОС, включая все виртуальные и сетевые диски, директории, для которых сделан JOIN или SUBST и прочую питушню.
                        Ответить
                        • а да еще дос не умел в сеть. это тоже по словам "старого программера" нужно было самим реализовывать.
                          Ответить
                          • Net.exe на что? PKTDRV на что? Для красоты?

                            Вот в Интернет не умел... Приходилось библиотеки для TCP/IP линковать с программой.
                            Ответить
                            • IPX/SPX кто умел ?
                              Ответить
                              • DOS умел. Из Винды его удалили то ли в XP, то ли в Висте, и теперь софт для поддержки IPX/SPX нужно качать отдельно.

                                В операционной среде MS-DOS за реализацию протокола IPX отвечает программа IPX.COM или IPXODI.COM.
                                Ответить
                              • >>IPX/SPX кто умел ?
                                и DOS (новел нетварь же!) а в Win95 он чуть ли не сразу ставился потому что ппрактически все сети были на нем.

                                Вот в 98 уже нет.

                                А примерно во времена Win2K МС ризнал главенство Интернета и начал вместо левого говна стараться всезде юзать TCP, IP, DNS, LDAP итд.
                                Ответить
                        • А что с выводом на экран? Использовали что-то более хитрое, чем $A000:$0000?
                          Ответить
                          • Да. Во многих графических режимах на окно $A000:$0000 отображалась не вся видеопамять, а только фрагмент (потому что 64 килобайт не хватало, чтобы покрыть всю видеопамять). Например, в данный момент мог отражаться слой видеопамяти, содержащий только красные субпиксели. Для переключения между слоями нужно было писа́ть в порт.

                            P.S. Если что, окно для текстового режима было в $B800:$0000. Там всё было просто.
                            Ответить
                        • >Просто через досовскую консоль нельзя было построить сложный UI.
                          Эээээ...
                          Ответить
                          • Да, без вызовов функций БИОСа никак.

                            Некоторым, конечно, удавалось через ДОС, но для этого нужно было загрузить драйвер ANSI.SYS, чтобы он обрабатывал эскейп-последовательности, с помощью которых можно было раскрашивать экран и двигать курсор. Но дальше бибиэсок это не пошло́.

                            Все популярные программы типа Нортона рисовали UI через БИОС или срали в видеопамять.
                            Ответить
                            • Смешно что виндовая консоль не умеет экскейп последоватльности, а умеет только специальный Console API.

                              В итоге АБСОЛЮТНО ВСЕ
                              эмуляторы терминала (линуксовые, маковые итд) работают через эскеп последовтальности (из termcap / terminfo), а винда нет.

                              В итоге ncureses например работает везде, а на винде надо всё по другому делать.

                              Ну не сидары-ли?
                              Ответить
                              • Нахуй твой ncurses на винде?

                                Из-за этого кстати все прыщеговно не умеет в юникод на виндовой консоли. Ну не прыщеговно ли?
                                Ответить
                                • Например чтобы написать тулзу которая везде умеет цветной аутпут.
                                  Все идут не в ногу, и только MS в ногу.

                                  Уникод нормальный в консоли есть, но с болью потому что пиндовый "65001" на самом деле не UTF-8.
                                  Ответить
                            • Что такое сложный UI? Там символов каких-то не хватало?
                              Ответить
                              • Домашнее задание: написать клон Нортон Коммандера, используя для вывода на экран только printf. Продемонстрировать базовый функционал: вывод панелей со списком файлов, перемещение курсора, переход по директориями, копирование файлов с прогресс-индикатором.
                                Ответить
                              • Символы можно было загрузить в знакогенератор
                                Ответить
                                • Мало кто знал, но на EGA/VGA/SVGA можно было загрузить одновременно две или четыре таблицы символов и переключаться между ними с помощью старших битов цвета. Таким образом, можно было использовать не 256 символов, а 512 или 1024. Правда, это никто не использовал в целях совместимости со старым говном.

                                  А так да, «графический» режим Нортон Коммандера на самом деле был текстовым, только вместо стандартных символов псевдографики в знакогенератор были загружены красивости.
                                  Ответить
                                  • Я помню такой хак, связанный с тем что ващето на символ там было 2 байта: символ и его атрибуты. Так вот если отказаться от атрибутов, то можно было иметь 2^16 символов.
                                    Ответить
                        • >> Просто через досовскую консоль нельзя было построить сложный UI.

                          ТурбоВижен
                          Ответить
                          • Турбовижен писа́л сразу в видеопамять в обход ДОСа.
                            Ответить
                            • В смысле не пользовался 21h?
                              Ну тогда ты прав. Я просто неверно понял, извини.
                              Ответить
                              • Да, я написал слишком сжато, поэтому можно неправильно понять.

                                Мой комментарий был ответом на комментарий Василия, где он писал, как «старый хакер» рекомендовал выводить на экран через средства БИОС, а не ДОСа.
                                Ответить
                                • Ну вообще старые хакеры считали что быстрее всего писать в видеопамять (а это больно, сложно и bit planes всякие), но если хочешь игрушку то без этого не обойтись.

                                  Через BIOS работать проще и везде работает, но медленнее.

                                  Ну а самый простой (и самый тормознутый) сопосб это DOS.
                                  Ответить
        • Релокацыя внутри вирт адреса. Физичисекий ваще нипричем. Ну и каша у тебя в башке.
          Ответить
      • > в ассемблерном коде нельзя
        Ты так не пугай, а то люди и правда поверят, что никогда нельзя... А ты только про случаи, когда релоков нет.

        Олсо, на x86_64 можно юзать RIP-relative адресацию и наслаждаться жизнью без релоков.
        Ответить
        • > люди и правда поверят, что никогда нельзя

          Виноват. Забыл, что на сайт заходят дети, которые могут неправильно понять...

          > x86_64 можно юзать RIP-relative адресацию

          На x86_64 можно использовать относительную адресацию не только для джампов, но и для обращения к памяти?
          Ответить
          • Типа можно аллоцировать 64 гигабайта и адреса векторам задавать через гигабайт. Реально будет использовано гораздо меньше.
            Ответить
          • Да, rip-относительная адресация памяти - это рекомендуемый способ. Абсолютным адресом можно закодировать только 32 бита. В OS X даже линкер ругается и не линкует, если в где-то в коде есть обращение по абсолютному адресу.
            Ответить

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