Design-studio.at.ua
   


1)Q:> А как восстановить исходники на паскале из .exe/.tpu?

1)A: Hикак! Хотя, если есть желание помучиться, то... В пaкете Turbo Analyst 7.0 есть утилиткa, котоpaя может восстaновить интеpфейсную чaсть скомпилиpовaнного модуля, a тaкже изaссемблиpовaть implementation-чaсть.

2)Q:> Как использовать TPU для 6-й версии TP в 7-й версии?
2)A: Если нет исходников, то Hикак!

3)Q:> Хочу паскаль под DOS, но в защищенном режиме! 32-bit protected! Под Win32! Под OS/2!
3)A: В Borland Pascal 7.0 можно использовать только_ 16-битный защищенный режим,он же DPMI. (Turbo Pascal - это всего лишь облегченная версия BP, работающая только в реальном режиме, посему запустите BP.exe и узнаете много нового (хотя бы посмотрите на возможности пункта TARGET при компиляции).Для 32-bit защищенного режима существуют более лругие компиляторы:

4)Q:> А почему задержки, которые задаются процедурой Delay(),на разных машинах разные?
4)A: Юнит CRT криво написан.

5)Q:> А чем тогда делать фиксированную задержку, вместо Delay()?
5)A: Если достаточна точность в 1 тик (1/18 доля секунды), то так:


 Procedure Delay(x:longint);
 {пауза на Х тиков}
 var
 l:longint;
 begin
 l := MemL[Seg0040:$6c];
 while MemL[Seg0040:$6c] < l+x do; {задержка на X 
 тиков}
 end;
 Если нужно точнее, то надо читать регистры таймера...
 Вот вам другая процедура:
 procedure RTCDelay(Wait:LongInt); assembler;
 {Ожидание на Wait микросекунд }
 asm
 mov ah,86h
 mov dx,word ptr Wait
 mov cx,word ptr Wait+2
 int 15h
 end;
 
Wait - в *микро*секундах, но разрешение все равно с точностью до ~976 микросекунд (примерно 1 миллисекунда), т.е. меньше 1024 ставить просто бессмысленно.

6)Q:> А как убрать курсор в текстовом режиме?
6)A: procedure CursorOff; assembler;

 asm
 mov ah,1
 mov cx,2020h {Убрать мерцание за пределы знакоместа}
 int 10h
 end;
 

7)Q:> А как его потом обратно включить?
7)A:


 procedure CursorOn; assembler; 
 asm
 mov ah,1
 mov cx,0607h {Установить мерцание 6й и 7й строк}
 int 10h
 end;
 

8)Q:> А можно сделать так, чтобы курсор был виден, но не мигал?
8)A: Hет. Только самому рисовать '_' (подчеркивание) в нужном месте.

9)Q:> А почему программы, написанные на паскале, вылетают с ошибкой Runtime Error 200 (Division by zero) на быстрых машинах типа PII-300?
9)A: Еще раз: Юнит CRT криво написан. Если в программе используется модуль CRT, то программа виснет при запуске из-за инициализации, которая потом используется процедурой Delay(). Инициализация происходит в любом случае даже если эта процедура не используется в программе. При написании своих программ используйте пропатченный CRT. Чтобы заработала уже скомпилированная программа (чужая), возьмите hex-редактор и: Ищем: B93700F7F1 Меняем на: B96E00F7F1 (увеличение в 2 раза) или на: B937009090 (убрать деление вообще) Программа _не_ должна быть запакована EXE-паковщиками.

10)Q:> Почему глючат процедуры побитового сдвига shl, shr в применении к LongInt?
10)A: Известный баг. Можно поставить фикс BP7.0 -> BP7.01, или же использовать свои процедуры. Вот пример (работают на 386+):


 function LongShl(A: LongInt; B: Byte): LongInt; assembler;
 asm
 mov cl,[B]
 db $66 {код опеpаций с 32-битными pегистpами}
 mov ax,word ptr [A]
 db $66
 shl ax,cl
 db $66
 push ax
 pop ax
 pop dx
 end;
 function LongShr(A: LongInt; B: Byte): LongInt; assembler;
 asm
 mov cl,[B]
 db $66
 mov ax,word ptr [A]
 db $66
 shr ax,cl
 db $66
 push ax
 pop ax
 pop dx
 end;

11)Q:> Почему при умножении 2-х чисел получается неверный результат:


var a,b:Word;
l:LongInt;
a:=1234;
b:=567;
l:=a*b;
В l получается. 44318, а не 699678, как должно быть на самом деле. Это баг?
11)A: Hет, это фича. Тип выражения определяется только типом входящих в него переменных, но не типом переменной, куда записывается результат. Если есть опасность переполнения, надо конвертировать тип явно: l:=LongInt(a)*b;

12)Q:> А как из моей программы запустить другую?
12)A: С помощью процедуры Exec:


 SwapVectors;
 Exec(Путь&ИмяВашейПрограммы, Доп_Параметры);
 SwapVectors;
 

13)Q:> А почему внешняя программа из моей не запускается?
13)A: А память кто будет внешней проге отдавать? По умолчанию все 640Kb отдаются твоей программе. Исправить это можно либо через Options/Memory Sizes../ High heap limit, либо директивой компилятора: {$M 4096,0,10000} Здесь первая цифра - память под стек (в стеке размещаются локальные переменные каждой вызываемой процедуры/функции), вторая - нижняя граница памяти, третья - верхняя. В данном примере твоей программе отдается 10000 байт, а все остальное - внешней программе.

14)Q:> А если мне самому память нужна?
14)A: Используй библиотеку для своппинга (выгрузки из памяти) в XMS/EMS/Disk - перед запуском внешней программы твоя программа вместе со всеми данными переписывается в XMS/EMS или на винт, а после завершения внешней - восстанавливается. Можно воспользоваться, например, юнитом SPAWNO от Ральфа Брауна, или модулем OpExec из ObjectProf by TurboPower.

15)Q:> Как сделать процедуру с нефиксированным числом параметров, типа writeln?
15)A: Встроенными средствами BP - Никак. WriteLn - это не процедура вовсе, это макрос такой, сделанный для удобства.

16)Q:> Как с этим боpоться (сделать одну пpоцедуpу)?
16)A: Пеpедавать yказатель на блок паpаметpов и какой-нибyдь флаг, по котоpомy внyтpи пpоцедypы бyдешь сам pазбиpаться с этим блоком паpаметpов. Hапpимеp так: procedure aaa(var param; flag: byte);

17)Q:> Как узнать ErrorLevel,который выставила программа, запущенная через Exec()?
17)A: С помощью DosExitCode:


{$M 8192,0,0}
 Uses Dos;
 Begin
 SwapVectors;
 Exec(FExpand(FSearch('arj.exe',GetEnv('PATH'))),'x a.arj');
 SwapVectors;
 WriteLn('Код возврата=',lo(DosExitCode));
 End.
 

18)Q:> Предположим, запустили мой ЕХЕ. > Как узнать из программы, в каком каталоге он лежит, > и не переименовали ли его?
18)A: Функция ParamStr(0) возвращает полное имя запущеннонго exe-файла, например 'c:\exe\work.exe'. При запуске программы из-под IDE (Ctrl-F9) вместо имени программы ParamStr(0) вернет путь к файлу turbo.exe, если программа компилируется в память (Compile/Destination = Memory), или имя программы без пути, если компилировать на диск.

19)Q:> Как узнать, какие параметры передаются моему ЕХЕ при вызове из командной строки?
19)A: Функция ParamStr(i) возвращает i-й параметр в виде строки. Отдельным параметром считается комбинация символов, не содержащая пробелов. Функция ParamCount возвращает общее количество параметров, переданных программе. 19)A2: Если вам необходимо совершить некие продвинутые операции с переданной командной строкой - например, вы получаете параметры, содержащие пробелы и заключенные в кавычки, - вам поможет следующий исходник, копирующий всю командную строку в первоначальном виде в строковую переменную:


var
 s: ^string;
 begin
 s:=ptr(prefixseg, $80);
 writeln('Command line: "', s^, '"');
 end.
 

20)Q:> А можно записать в середину текстового файл строку произвольной длины, но чтобы остальные строки остались, как были, или удалить одну строку из середины?
20)A: Просто так - нет. Есть два варианта. Простой: открываете второй файл, читаете строки из первого, пишете строки во второй, пропуская то, что не нужно, или дополняя в нужных местах. Сложный: открываете файл, как бинарный, составляете список длин строк, и копируете куски файла в другой с помощью BlockRead/BlockWrite.


{пример для простого варианта}
 var
 f1,f2: text;
 s: string;
 const
 ourstring = 'ДЬВ'; {искомая стpока}
 begin
 assign(f1,'c:\a.txt');
 assign(f2,'c:\b.txt');
 reset(f1); rewrite(f2);
 while not eof(f1) do
 begin
 readln(f1,s);
 if pos(ourstring,s)<>0 then continue; {пропустить 
 строку, если найдено}
 writeln(f2,s);
 end;
 close(f1); close(f2);
 end.

21)Q:> Как обойти все каталоги на диске?
21)A: Используя процедуры FindFirst, FindNext. Их описание есть в хелпе. Вкратце - в функции обхода перебираем все вхождения в каталог, и проверяем каждое из них - если это каталог, то входим в него и рекурсивно вызываем функцию обхода каталога.


Uses Dos;
 Procedure DirTree(path:string);
 var
 sr:searchrec;
 begin
 If path[length(path)]<>'\' then path:=path+'\';
 findfirst(path+'*.*',AnyFile,sr);
 while (doserror=0) do begin
 if (sr.attr and directory) = directory then begin
 if (sr.name<>'.') and (sr.name<>'..') then
 DirTree(path+sr.name+'\');
 end else begin
 writeln(path+sr.name);
 end;
 findnext(sr);
 end;
 end;
begin
 DirTree(ParamStr(1));
 end.
 

22)Q:> А почему одновременно больше 14 файлов Borland Pascal не открывает?
22)A: Используйте в вашей программе вот такой модуль. Можете до 255 файлов открыть.


{$IFDEF DPMI}
 STOP COMPILE ! Only for real mode !
 {$ENDIF}

Unit Extend; {(C) 1996 by Pavel Nikiforov}
 interface
 implementation

procedure Setup;
 type PJFT=^TJFT;
 TJFT=record
 Num:word;
 Tbl:PChar;
 end;

var MyJFT:PChar;
 P:PJFT;

begin
 getmem(MyJFT,255);
 FillChar(MyJFT[0],255,$FF);
 P:=Ptr(PrefixSeg,$32);
 move(P^.TBL^,MyJFT^,P^.Num);
 P^.TBL:=MyJFT;
 P^.Num:=255;
 end;

begin
 Setup;
 end.
 

23)Q:> 1) А как открыть на запись файл с атрибутом read/only? Ругается. > 2) Как удалить r/o файл?
23)A: Hужно снять атрибут r/o с файла, а затем делать с ним все, что заблагорассудится.


Uses DOS;
 var
 t:text;
 attr:Word;
 Begin
 Assign(t,'file');
 GetFAttr(t,attr); {Прочитать атрибуты файла }
 attr:=attr and $FE;
 SetFAttr(t,attr); {Сбросить атрибут ReadOnly}
 Append(t);
 Writeln(t,'Hello!'); {Дописать что-либо в файл }
 Close(t);
 attr:=attr or $01;
 SetFAttr(t,attr); {Восстановить атрибут ReadOnly}
 End.
 

24)Q:> Ищу я все подкаталоги в данном каталоге процедурой FindFirst('*.*',Directory,Search), а она мне не только подкаталоги, но и все файлы находит. В чем дело?
24)A: Глюк MS-DOS. А именно, функции 4E прерывания 21. Hужно после каждого использования FindFirst/FindNext проверять, каталог ли ты нашел: if Search.Attr and (Directory <> 0) then begin [...] end;

25)Q:> А почему файл не хочет переименовываться/удаляться? Я сделал так: Assign(f,'file'); Reset(f); Erase(f)
25)A: Открытые файлы переименовывать/удалять нельзя. Либо закройте его командой Close(f) перед удалением, либо не открывайте его вообще - после Assign делайте сразу Erase. Assign(f,'file'); Erase(f)

26)Q:> Как получить полное имя файла с путем, если известно его имя, и то, что он лежит в одном из каталогов, определенных в переменной PATH?
26)A: FileName:=FExpand(FSearch('file.ext',GetEnv('PATH'))




Шаблоны Ucoz | Хостинг от uCoz