DAK. Pascal (Delphi) => Fasm

High-level languages programming questions
  • Краткое описание-черновик DAK. Возможности DAKа.
    Точнее говоря, пока еще скудные возможности DAKа.

    Комментарии в DAK.
    В DAK организация комментариев такая же как и у Delphi, - '{…}', '(*…*)' или '//..... (до конца строки)'

    Секция модуля.
    В секции модуля можно определять глобальные, целочисленные константы, разменом не более Cardinal (0..4294967295). Константа должна быть без всяких «+» или «-» и т. д. , т.е. Например, вот так: const dd=923874234; Также константы можно делать в секции процедур, - «procedure CycleProcesEvents;
    const dd=923874234;»

    Процедуры.
    Процедуры возможны без параметров, причём в процедуре должен быть один «Begin», как начало процедуры и один «end;», как конец процедуры. В разделе процедур, может быть раздел разметки меток, например: «Label CycleProcesEventsL, CycleProcesEvents_ret,DrawWindow,key,button,exit,My1;».
    В разделе процедур, в секции кода, могут быть использованы локальные метки «CycleProcesEventsL:», на которые можно переходить с помощью «goto», например «goto CycleProcesEventsL;» Процедура может быть определена как forward, например «procedure BEGINPROGRAM;forward;» и указана как стартовая, - «procedure BEGINPROGRAM;forward; {#START PROJECT DAK}» (см. директивы) или «procedure BEGINPROGRAM; {#START PROJECT DAK}» (см. директивы). Указание процедуры стартовой {#START PROJECT DAK}, должно быть после её имени до «end;» процедуры.

    Процедура. Секция кода.
    Секция кода может быть только в процедуре, но не в модуле.
    procedure CycleProcesEvents;
    Begin
    {Секция кода процедуры}
    end;
    В секции кода:
    RET; — аналог ассемблеровского RET, т. е. возврат из процедуры
    INT0x40; - аналог ассемблеровского INT 0x40,
    HALT; – немедленное завершениие программы
    GOTO; - переход на метку внути процедуры.
    IF … - условый переход.

    Неиспользуемые процедуры не компилируются!

    Условный переход IF.
    Условный переход IF, должен содержать регистр-идентификатор, одно из условий сравнения ( "=" ">=" "=>" "<=" "=<" "<>" "><" "<" ">" ) и числовой идентификатор, а далее «then goto» и МЕТКА. Обработка других вариаций, пока не написана. Например: «If EAX=1 then goto DrawWindow;», «If AX=1 then goto DrawWindow;», «If AL=1 then goto DrawWindow;», «If AH=1 then goto DrawWindow;»

    Присваивание.
    Допустимо присваивание только 32-разрядным регистрам EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI. Им можно присваивать числовые значения, а также регистры {8 битные регистры процессора} AL, BL, CL, DL, AH, BH, CH, DH, {16 битные регистры процессора} AX, CX, DX, BX, SP, BP, SI, DI, {32 битные регистры процессора} EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI.

    Никаких логических или арифметических операций, пока не реализовано.

    При написании и испытаниях DAKа использовалась среда Borland Delphi 7.
    Проверялись и испытывались примеры на диске C:\ (т.е. в папке C:\DAKproject\ )

    Ну вот на этом пока всё.
    Автор будет совершенствовать DAK дальше. Вот только не знаю за что “хваться” в первую очередь. :-) Жду комментариев.
  • Порядок работы с DAK в простом изложении:
    DAK «привязан» к файлу uMain.pas , оба файла должны обязательно находится в одном каталоге.

    При использовании среды Delphi, для написания программы необходимо: Открыть Project.dpr, открыть файл uMain.pas который используется Project.dpr, отредактировать uMain.pas, НЕ ЗАБЫТЬ СОХРАНИТЬ и запустить из среды Delphi (кл. F9), в случае успешной компиляции, будут созданы файлы Project.prt и Main.asm, далее согласно установленных директив '{#START CompileProject.bat}' и '{#START RunProject.bat}' в файле uMain.pas, проект будет скомпилирован FASM.EXE и запущен в KlbrInWin.

    При использовании без среды Delphi, но с проверкой синтаксиса через dcc32, для написания программы необходимо: открыть текстовым редактором uMain.pas отредактировать его, СОХРАНИТЬ и запустить DAK.bat, далее DAKом будет запущена предварительная проверка синтаксиса (dcc32CheckProject.bat), потом обработка самим DAKом , в случае успешной компиляции, будут созданы файлы Project.prt и Main.asm, далее согласно установленных директив '{#START CompileProject.bat}' и '{#START RunProject.bat}' в файле uMain.pas, проект будет скомпилирован FASM.EXE и запущен в KlbrInWin.

    При использовании без среды Delphi и без проверки синтаксиса через dcc32, для написания программы необходимо: открыть текстовым редактором uMain.pas отредактировать его, СОХРАНИТЬ и запустить DAKDelphi.bat (либо 'DAK.exe /delphi' из коммандной строки), далее обработка самим DAKом , в случае успешной компиляции, будут созданы файлы Project.prt и Main.asm, далее согласно установленных директив '{#START CompileProject.bat}' и '{#START RunProject.bat}' в файле uMain.pas, проект будет скомпилирован FASM.EXE и запущен в KlbrInWin.
  • Была такая близкая этому топику тема на местном форуме.
    Ещё раз о HiAsm про Hiasm для Kolibri
    но, быстро вникнуть не получилось и забросилось.
  • компилятор, который сможет компилировать файлы с мнемоникой Pascal
    Компилятор Oberon-07 имеет очень похожий синтаксис и работает в самой Колибри viewtopic.php?f=33&t=2443
    Там на скриншоте под спойлером видно кусочек кода для KolibriOS viewtopic.php?f=33&t=2443#p52763

    Судя по приведённому примеру кода, это больше похоже на высокоуровневый ассемблер, чем на паскаль.
    Если именно это необходимо, то можно этого добиться с помощью ассемблерных макросов.
    Или вот, например, можно использовать HJWasm(форк JWasm(форк Open Watcom Assembler)), который поддерживает многие HighLevel конструкции "из коробки".
    Пример кода для Колибри под спойлером viewtopic.php?f=2&t=2586&p=65582#p55776
    Или вот ещё пример кода из демки Masm2Htm.asm(раньше было на сайте у Japheth). Я пропускаю здесь не очень интересные места, заменяя закомментированными точками:
    Spoiler:

    Code: Select all

        .if ( eax == 0 )
    ;......................
        .endif
        
        .while ( byte ptr [esi] )
    ;......................
        .endw
        
    .while (ecx)
    ;......................
        .if ( incomment == 0 && inquotes == 0 && inangles == 0 )
            .if ( startword == 0 )
    ;......................
                .if ( edi > startline )
    ;......................
                .endif
    
            .if ( al == '<' )
    ;......................
            .elseif ( al == '>' )
    ;......................
            .elseif ( al == '&' )
    ;......................
            .else
                .if ( incomment && ( al == cr || al == lf ))
    ;......................
                    .while ( byte ptr [esi] )
    ;......................
                    .endw
    ;......................
                .endif
    ;......................
            .endif
    
    И, похоже, что теперь также поддерживается ".SWITCH - .CASE - .DEFAULT - .ENDSWITCH" http://masm32.com/board/index.php?topic=5280.0
    Оно, кстати, и под Колибри должно работать(я выкладывал давно уже в чате скриншот работы Masm2Htm.kex).
    Конкретно в этом чате chatlogs/chatlog2014-04-23.html
    0CodErr « Wed Apr 23, 2014 11:36 am » собрал вон ту штуку http://japheth.de/JWasm/masm2htm.html под KolibriOS можно полученный из исходника html открыть в WebView:
    Spoiler:Image
    Также тут кто-то уже предлагал Язык ассемблера с упрощенным синтаксисом viewtopic.php?f=4&t=2645

    Что касается именно самого Delphi, то это можно сделать, например, с помощью Delphi2.0(это всё равно лучше самопального транслятора).
    Я как-то уже спрашивал, нужен ли кому-то пример. Сказали, что не нужен.
    Вот в этом чате сказали chatlogs/chatlog2013-04-05.html
    Spoiler:
    0CodErr « Fri Apr 05, 2013 5:06 pm » я могу сделать для Delphi 2.0 пример, похожий на примеры для FreeBasic и XDS
    ; ...............................................................
    Mario_r4 « Fri Apr 05, 2013 9:10 pm » Дельфи не нужен же! ;-)
    Mario_r4 « Fri Apr 05, 2013 9:10 pm » Совсем не нужен.
    А вообще исходник такой:
    Spoiler:

    Code: Select all

    unit test;
    (* -------------------------------------------------------- *)
    interface
    (* -------------------------------------------------------- *)
    Type
      SIZE = Record height, width : Word end;
    (* -------------------------------------------------------- *)
    Const
     (* WinDow styles *)
      WS_SKINNED_FIXED    =  $4000000;
      WS_SKINNED_SIZABLE  =  $3000000;
      WS_FIXED            =  $0000000;
      WS_SIZABLE          =  $2000000;
      WS_FILL_TRANSPARENT = $40000000;
      WS_FILL_GRADIENT    = $80000000;
      WS_COORD_CLIENT     = $20000000;
      WS_CAPTION          = $10000000;
    
     (* Caption styles *)
      CAPTION_MOVABLE     = $00000000;
      CAPTION_NONMOVABLE  = $01000000;
    
     (* Events *)
      REDRAW_EVENT        = 1;
      KEY_EVENT           = 2;
      BUTTON_EVENT        = 3;
    
     (* Colors *)
      COLOR_BLUE          = $000000FF;
      COLOR_RED           = $00FF0000;
      COLOR_GREEN         = $0000FF00;
      COLOR_WHITE         = $00FFFFFF;
      COLOR_BLACK         = $00000000;
    
      sz_hello  = AnsiString('Hello, Delphi 2.0!');
    (* -------------------------------------------------------- *)
    Var
      Left, Top, Width, Height : cardinal;
      Scr : SIZE;
    (* -------------------------------------------------------- *)
    procedure Main; forward;
    procedure RedrawStart; assembler; forward;
    procedure RedrawFinish; assembler; forward;
    procedure DrawWinDow(Left, Top, Width, Height: cardinal; Caption: PChar; BackColor, Style, CapStyle: cardinal); StdCall; assembler; forward;
    procedure ThreadTerminate; assembler; forward;
    procedure On_Redraw;  StdCall; forward;
    procedure On_Key;  StdCall; forward;
    procedure On_Button;  StdCall; forward;
    function  WaitEvent : cardinal; assembler; forward;
    function  GetKey : cardinal; assembler; forward;
    function  GetButton : cardinal; assembler; forward;
    function  GetScreenSize : SIZE; assembler; forward;
    (* -------------------------------------------------------- *)
    implementation
    (* -------------------------------------------------------- *)
    procedure Main();
    begin
      Scr := GetScreenSize();
    
      Width  := Scr.width  Shr 2;
      Height := Scr.height Shr 2;
      Left   := (Scr.width  - Width)  Shr 1;
      Top    := (Scr.height - Height) Shr 1;
    
      While TRUE Do begin
        Case WaitEvent() Of
        REDRAW_EVENT : On_Redraw;
        KEY_EVENT    : On_Key;
        BUTTON_EVENT : On_Button;
        end;
      end;
    end;
    (* -------------------------------------------------------- *)
    procedure On_Redraw();
    begin
     RedrawStart;
     DrawWinDow(Left, Top, Width, Height, sz_hello, COLOR_WHITE, WS_SKINNED_FIXED + WS_COORD_CLIENT + WS_CAPTION, CAPTION_MOVABLE);
     RedrawFinish;
    end;
    (* -------------------------------------------------------- *)
    procedure On_Key();
    begin
      GetKey;
    end;
    (* -------------------------------------------------------- *)
    procedure On_Button();
    begin
      Case GetButton() Shr 8 Of
      1 : ThreadTerminate;
      end;
    end;
    (* -------------------------------------------------------- *)
    procedure RedrawStart();
    Asm
            push   ebx
            mov    eax, 12
            mov    ebx, 1
            int    64
            pop    ebx
    end;
    (* -------------------------------------------------------- *)
    procedure RedrawFinish();
    Asm
            push   ebx
            mov    eax, 12
            mov    ebx, 2
            int    64
            pop    ebx
    end;
    (* -------------------------------------------------------- *)
    procedure DrawWinDow(Left, Top, Width, Height : cardinal; Caption : PChar; BackColor, Style, CapStyle: cardinal);
    Asm
            push   ebx
            push   edi
            push   esi
            xor    eax, eax
            mov    ebx, [Left]
            shl    ebx, 16
            add    ebx, [Width]
            mov    ecx, [Top]
            shl    ecx, 16
            add    ecx, [Height]
            mov    edx, [Style]
            or     edx, [BackColor]
            mov    edi, [Caption]
            mov    esi, [CapStyle]
            int    64
            pop    esi
            pop    edi
            pop    ebx
    end;
    (* -------------------------------------------------------- *)
    function WaitEvent(): cardinal;
    Asm
            mov    eax, 10
            int    64
    end;
    (* -------------------------------------------------------- *)
    function GetKey(): cardinal;
    Asm
            mov    eax, 2
            int    64
    end;
    (* -------------------------------------------------------- *)
    function GetButton(): cardinal;
    Asm
            mov    eax, 17
            int    64
    end;
    (* -------------------------------------------------------- *)
    procedure ThreadTerminate();
    Asm
            mov    eax, $FFFFFFFF;
            int    64
    end;
    (* -------------------------------------------------------- *)
    function GetScreenSize(): SIZE;
    Asm
            push   ebx
            mov    eax, 61
            mov    ebx, 1
            int    64
            pop    ebx
    end;
    (* -------------------------------------------------------- *)
    end.
    
    LScript.x:
    Spoiler:

    Code: Select all

    PATH_SIZE    =  1024;
    PARAMS_SIZE  =   256;
    STACK_SIZE   =   256;
    
    SECTIONS
    {
    
      .text  : AT(0) {
        code = .;
    
            LONG(0x554e454D);
            LONG(0x31305445);
            LONG(1);
            LONG(start);
            LONG(end);
            LONG(end + PATH_SIZE + PARAMS_SIZE + STACK_SIZE);
            LONG(end + PATH_SIZE + PARAMS_SIZE + STACK_SIZE);
            LONG(end + PATH_SIZE);
            LONG(end);
    
    		start = .;
    		
        *(.text)
    
      }
    	
      .data : AT(data - code) {data = .; *(.data)}
    	
      .bss  : AT(bss - code)  {bss = .;  *(.bss)}
    	
      end = .;
    }
    Так я его собирал:
    Spoiler:

    Code: Select all

    Set Name=test
    dcc32 -J %Name%.pas
    editbin %Name%.obj
    ld -T LScript.x %Name%.obj -o %Name%.kex
    objcopy -O binary -j .text -j .data -j .bss %Name%.kex
    А вот скриншот запущенного приложения из Колибри:
    Spoiler:Image
    Скомпилированный бинарник:
    test.kex (385 Bytes)
    Downloaded 353 times
    В целом, конечно, твоя идея интересная. Но тут вопрос лишь в том, хочешь ли ты сам сделать транслятор, или ты всё-таки хочешь уже программировать на Pascal под KolibriOS? Так-то есть ещё FreePascal viewtopic.php?f=33&t=1020, Pascal Pro viewtopic.php?f=9&t=2353.
  • 0CodErr
    Стеки и секции .data и .bss лучше явно выравнивать. Желательно на 16 байт, стек минимум 4.
  • 0CodErr, ты так много понаписывал в одном сообщении, у меня прям голова кругом!... :-)
    Я конечно это всё позже рассмотрю более внимательно, а пока скажу следующее.
    Компилятор Oberon-07 имеет очень похожий синтаксис и работает в самой Колибри
    Программировать в самой КОС не считаю удобным занятием. А есть ли Oberon-07 под вин с возможностью компилировать для КОС ?
    Судя по приведённому примеру кода, это больше похоже на высокоуровневый ассемблер, чем на паскаль.
    Как я уже писал в первом сообщении, я его пишу всего лишь три недели. Он еще долго будет похож на высокоуровневый ассемблер, но суть не в том. Пускай он похож на что хочешь, основной смыл, в том чтобы, мнемоника написания (синтаксис) была такая как у паскаля, чтобы можно было бы использовать Дельфи (или любую другую паскалеподобную среду програмирования) для написания программ для КОС.
    Если именно это необходимо, то можно этого добиться с помощью ассемблерных макросов.
    Ох, не пойму, ну как людям не в домёк :-) - ну фасм штука хорошая конечно, ну не то это, не то! Ну не сравнить же синтаксис паскаля с фасмом! Ну не удобен он в использовании, хоть я и умудрился написать на нём SAS Emulator ( viewtopic.php?f=43&t=3253 ), как говориться “с угару на шару”. :-) Сейчас расматривая исходники SAS Emulatorа я уже фиг что так сразу пойму! А вот на дельфи бы понял!
    Будь бы тогда DAK, такой как я хочу его сделать, то мне бы проще и веселей было бы написать SAS Emulator.
    Что касается именно самого Delphi, то это можно сделать, например, с помощью Delphi2.0(это всё равно лучше самопального транслятора).
    Это интересно! Надо будет рассмотреть более тщательно!
    В целом, конечно, твоя идея интересная. Но тут вопрос лишь в том, хочешь ли ты сам сделать транслятор, или ты всё-таки хочешь уже программировать на Pascal под KolibriOS?
    Ответ будет не менее интересен : :-) Хочу программировать в среде Delphi используя свой транслятор! :-)
    Рассмотрю как вариант тот, о котором написал ты, ( с помощью Delphi 2.0 ) вот толко не пойму, почему имменно 2.0 ? ну да ладно это позже, после рассмотрения!.... хотя я почему-то думаю, что мне и в том варианте что-то да не понравится! :-( Сколько уже было у меня такого?... и СИ пытался изучить и использовать, - ну его в баню! Оберон чё то там рассматривал, - тоже не понравился, что только под КОС! Короче, пришёл к выводу пока я сам не напишу, врядле мне что понравиться! :-( :-)
    Если ты скачивал и рассматривал DAKproject.7z то наверное прекрасно понял мою задумку во всей красе: Открыл дельфёй, пиши, сохраняй, запускай, получи визуальный результат! Нет дельфи или не хочешь её устанавливать,- используй dcc32 для проверки синтаксиса! Не хочешь и такого,- и без этого можно! Не хочешь, чтобы Фасм компилировал после трансляции DAKом, - отключи! Не хочешь, чтобы запускалось в KlbrInWin, - скомпилированное тоже отключи, или прикрути что-то другое в RunProject.bat ! Да как хочешь! На любой вкус! И шаблон готовый есть, открывай да пиши, а не думай, что и как прикрутить, чтобы автоматически компилировало и запускал и т.д.! А далее... это всё будет возможно не только под винХРюша, но и под вин3.11, и под ДОС, если получится так сделать, и конце-концов под КОС!
    У МЕНЯ ВОПРОС: ПОЧЕМУ Я ДО СИХ ПОР НЕ ВИЖУ НИЧЕГО ПОДОБНОГО МОЕЙ ЗАДУМКЕ DAK ?
  • ты так много понаписывал в одном сообщении, у меня прям голова кругом!
    Уж от тебя то я не ожидал такое услышать. :lol:
  • Оберон умеет кросс-компиляцию.

    Проблема не в трансляторе как таковом, а в том, чтобы портировать фреймворк - для Дельфи это либо VCL/LCL Или FireMonkey.

    Ну и ИМХО, визуальные генераторы программ ни до чего хорошего никогда не доводили.
    Лучшие из них разделяют генерируемую часть и позволяют ручками дописывать/править сгенерированный код. Что нетривиально.
  • 0CodErr wrote: Что касается именно самого Delphi, то это можно сделать, например, с помощью Delphi2.0(это всё равно лучше самопального транслятора).
    Я как-то уже спрашивал, нужен ли кому-то пример. .............
    Так я его собирал:

    Code: Select all

    Set Name=test
    dcc32 -J %Name%.pas
    editbin %Name%.obj
    ld -T LScript.x %Name%.obj -o %Name%.kex
    objcopy -O binary -j .text -j .data -j .bss %Name%.kex
    Что такое editbin ? ld ? objcopy ?
    Где это всё брать ?
  • Pathoswithin wrote:
    ты так много понаписывал в одном сообщении, у меня прям голова кругом!
    Уж от тебя то я не ожидал такое услышать. :lol:
    Чего так ? :D
  • ALEXS1983 wrote:Что такое editbin ? ld ? objcopy ?
    ld(GNU linker) и objcopy являются частью binutils(GNU Binary Utilities).
    editbin(The Microsoft COFF Binary File Editor) у меня он был вместе с masm32 "masm32\bin\editbin.exe"
    вот толко не пойму, почему имменно 2.0
    Должно ещё в третьей версии работать. А уже в Delphi 4 Borland стала использовать свой формат OMF, не совместимый с Intel OMF.
    Тут вот ещё товарищ Freeman нечто выкладывал viewtopic.php?f=33&t=735#p49124[quote]"Пифия" -- препроцессор int-файлов, генерируемых dcu32int, в asm-файлы синтаксиса FASM. Полученные ассемблерные исходники штатно собираются FASM-ом как из-под Windows, так и из-под самой "Колибри".[/quote]
  • 0CodErr wrote:ld(GNU linker) и objcopy являются частью binutils(GNU Binary Utilities).
    editbin(The Microsoft COFF Binary File Editor) у меня он был вместе с masm32 "masm32\bin\editbin.exe"....
    "Пифия" -- препроцессор int-файлов, генерируемых dcu32int, в asm-файлы синтаксиса FASM. Полученные ассемблерные исходники штатно собираются FASM-ом как из-под Windows, так и из-под самой "Колибри".
    Ох. мать мою за ногу... :D Ну началось!... как всегда! :-(
    Надо узнавать что это... потом искать... потом еще оно затребует ещё что-то... которое... надо узнавать что это... потом искать... потом, то, что было затребовано, почему-то начнёт возмущаться... мол винда какая-то у меня неправильная... или её обновить надо или какие-то дополнения установить надо.... чтобы это всё заработало... и пошло поехало....

    Никто ничего ненормального не замечает ?! Ах, ну да, попривыкали уже к этому всему! Ребята, ну ведь это не нормально! Ну такого ведь быть не должно! Ну кто захочет, к примеру связываться с таким, чтобы только посмотреть и понять, что это ему не подходит или не подходит ?!

    0CodErr, вот ты, например, создал пример использования Дельфи 2.0, и вот почему бы тебе, было бы всё "жужмом" не заархивировать вместе с файлами ld, objcopy, editbin и еще с чем-то там и не выложить тот архив ?!... для того, чтобы тот, кто его скачает не морочился над такими вопросами "что это ld, objcopy, editbin такое?", "где его брать?", "оно или не оно окажется?!", "подходит эта версия или не подходит?!" и т.д. !... Ну ведь они же у тебя были (ld, objcopy, editbin) когда ты пример создавал?! при примере же были ?!

    Я вот выложил DAKproject, запаковал всё что нужно и всё что можно, - dcc32, KlbrInWin, FASM.EXE и даже FASMW.EXE на всякий случай т.д., т.е. всё то с чем это работать будет нормально! Ну разве что дельфю не запаковал. :-) Всё! Запускай и работай! Вот такой подход должен быть, ребята!

    Если бы с такими мороками, устанавливался турбо паскать или дельфя, - да фиг я начал этим всем заниматься ! Нашёл бы что-то другое без всяких заморочек! Это я всё к тому, что найдутся пользователи, у которых КОС и программирование для КОС, вызовет просто-напросто отвращение, из-за такого! Ребята! Я ко всем обращаюсь! Нужен подход: Скачал, установил, работай! Я такого подхода шото не вижу! Везде, в чём не коснись, связанное в частности с КОС программированием для КОС, - узнай... докачай... подкачай.... версия докаченного не та... инструкция от старой версии.. еще чего-там и т.д.
  • Image
    Ох как мне всё это "нравиться"! Я прям торчу от этого всего, как от дельфи! Ну или почти так!
  • ALEXS1983 wrote:Ох как мне всё это "нравиться"!
    А, ну это не ко мне же, а к автору.
    почему бы тебе, было бы всё "жужмом" не заархивировать вместе с файлами ld, objcopy, editbin и еще с чем-то там и не выложить тот архив
    Ладно, как скажешь, но, надеюсь, что архиватор 7-zip у тебя уж есть :lol:
    Test.7z (1.26 MiB)
    Downloaded 315 times
    В архиве
    • link.exe
      ld.exe
      objcopy.exe
      LScript.x
      test.pas
      make.bat
    editbin — всего лишь вызов MSLinker с ключом -edit, поэтому в архиве link.exe. dcc32 должен быть нужной версии, например, от delphi2.0(от седьмой не пойдёт).
  • Who is online

    Users browsing this forum: No registered users and 1 guest