Перевод Паскаль-адреса в C-адрес

  • Автор темы -
  • Дата начала

Гость
#1
Здравствуйте! У меня возникла вот такая проблема. На одном сайте нашёл код на Паскале, где используется прямой доступ к системному таймеру. Так там программа использует адрес absolute $0040:$006C. А этот адрес можно перевести в C-адрес, вроде 0x0040006C? Подскажите, пожалуйста!
 

lazybiz

Well-Known Member
03.11.2010
1 339
0
#2
Читая твой вопрос, я начинаю понимать что тебе это не нужно. Хотя...
Тот что в паскале - дальний указатель 16-битного реального режима (который используется в ОС DOS).
Если ты будешь писать в С под 16-битный режим, то дальний указатель будет состоять из сегмента и смещения, и выглядеть в твоем случае примерно так:
C++:
	unsigned char far *ptr;
ptr = MK_FP( 0x0040, 0x006c );
Если же ты хочешь чтобы твой код работал в ОС семейства Windows, то я тебя готов разогорчить тебя, т.к. работать он не будет.
Но! Если ты в DOS будешь использовать так называемый DOS-Extender, который позволяет запускать 32-битные приложения, то указатель будет выглядеть как значение сегмента умноженное на 16 плюс значение смещения, т.е.: (0x0040 << 4) + 0x006c или просто 0x46c.
 

lazybiz

Well-Known Member
03.11.2010
1 339
0
#3
Мой Visual C++ 6.0 не знает о существовании такого макроса, как MK_FP. Откуда же Вы его взяли?
Visual C++ еще и не знает о существовании прямого доступа к системному таймеру.
MK_FP - это макрос для компиляторов под DOS. Та программа, которую вы переписываете с паскаля работала в DOS-е в 16-битном режиме.
 

Гость
#4
MK_FP - это макрос для компиляторов под DOS.
Borland C++ 3.1 сойдёт?
Visual C++ еще и не знает о существовании прямого доступа к системному таймеру.
Надеюсь, он может об этом узнать через ассемблерную вставку в программе. Как я понимаю, что-то вроде этого:
Код:
mov dword ptr[lptime], dword ptr[46Ch]; 46Ch - или как там на ассемблере это пишется...
 

lazybiz

Well-Known Member
03.11.2010
1 339
0
#5
Ни разу им не пользовался, но думаю что сойдет.

Надеюсь, он может об этом узнать через ассемблерную вставку в программе.
Не может. Ассемблерная - не ассемблерная, в данном случае не имеет значения. Windows не даст прочитать тебе переменную по этому адресу. Скорее всего вылезет сообщение с надписью а-ля "General Protection Fault" или тому подобное, или программа просто закроется.
 

Гость
#8
Можно попробовать заменить чтение таймера какой-нибудь функцией.
Извините, я не совсем понял, что значат эти слова.
Код чего? Если код моей программы, то вот он:
C++:
int main (int argc, char *argv[])
{
DWORD dwOldTime = getTime (); // Получим время прямо из таймера.
SlowFunction ();
cout << "Время выполнения SlowFunction равно " << getTime () - dwOldTime << " мс." << endl;
return 0;
}
Программа замеряет время работы функции.

Добавлено: И ещё - Windows как-то получает доступ к таймеру, не так ли? Значит, это всё-таки возможно.
 

lazybiz

Well-Known Member
03.11.2010
1 339
0
#9
Код чего? Если код моей программы, то вот он:

int main (int argc, char *argv[])
{
DWORD dwOldTime = getTime (); // Получим время прямо из таймера.
SlowFunction ();
cout << "Время выполнения SlowFunction равно " << getTime () - dwOldTime << " мс." << endl;
return 0;
}
Что-то я не вижу, чтобы ты тут к адресу 0x46с обращался...

Если хочешь чтобы тебе помогли - выкладывай хотя бы исходник на Паскале. Твой исходник мне ни о чем не говорит.
 

Гость
#10
Функция DWORD getTime (void) - это по сути прямое обращение к таймеру...
Если на Паскале - вот на Паскале:
Код:
unit timer;

interface
procedure start (var t:longint);
procedure stop (var t:longint);
procedure pause (t:longint; show:boolean);

implementation
systemtimer:longint absolute $0040:$006c;

procedure start (var t:longint);
begin
t := systemtimer;
end;

procedure stop (var t:longint);
begin
t := systemtimer - t;
end;

procedure pause (t:longint; show:boolean);
var xn, xt:longint;
begin
xt := 0;
xn := systemtimer;
while ((xt - xn) / 18.2) * 1000 < t do
begin
xt := systemtimer;
if show then
writeln ((xt - xn) / 18.2 : 6:4)
end;
end;
end.
Вот программа на Паскале:
Код:
program timerprimer;
uses timer;
var
i : integer;
a : real;
time : longint;
begin
randomize;
start (time);
for i := 1 to 30000 do
a := sin (sqrt (i)) * cos (sqrt (random (10000)));
stop (time);
writeln ('Время выполнения: ', time / 18.2 : 6:4);
readln;
pause (10000, true);
end.
Но что даст этот код? Я уже задал другой вопрос:
Добавлено:
Можно попробовать заменить чтение таймера какой-нибудь функцией.
Извините, я не совсем понял, что значат эти слова.
 

lazybiz

Well-Known Member
03.11.2010
1 339
0
#11
> Функция DWORD getTime (void) - это по сути прямое обращение к таймеру...
Ты ее откуда откопал вообще?

Можешь использовать любую из этих функций:
DWORD timeGetTime(VOID);
DWORD WINAPI GetTickCount(void);
ULONGLONG WINAPI GetTickCount64(void);

> И обойти Windows никак нельзя?
Нельзя.

Функция pause я вообще не понял зачем нужна.
 

Гость
#12
Функция pause я вообще не понял зачем нужна.
Функция pause - это аналог Sleep в C.
Ты ее откуда откопал вообще?
Мне как раз нужно создать эту функцию. Всё, что было в программе на Паскале - только прямое обращение к таймеру, и ничего больше!
Если какая-либо функция получения времени в Windows напрямую обращается к таймеру (то есть сразу return *systemtime, где systemtime - это адрес таймера в памяти), то я хочу знать, какая!
> И обойти Windows никак нельзя?
Нельзя.
А сам Windows получает доступ к таймеру, так? Получается, на уровне ядра это вполне возможно.

Добавлено:
Мне как раз нужно создать эту функцию.
Во избежание путаницы - это я сказал про DWORD getTime (void).
 

lazybiz

Well-Known Member
03.11.2010
1 339
0
#13
> Мне как раз нужно создать эту функцию.
Не делай из мухи слона и не изобретай велосипед.
Вот то что тебе нужно:
C++:
DWORD timeGetTime(void); // The default precision of the timeGetTime function can be five milliseconds or more, depending on the machine.
Еще есть функции timeBeginPeriod( UINT ) и timeEndPeriod( UINT ), с помощью которых можно установить точность вышеописанной функции.

Вот здесь все подробно описано: http://msdn.microsoft.com/en-us/library/dd757629(VS.85).aspx
Читай. Пользуйся. Наслаждайся результатом.
 

Гость
#14
Спасибо за подсказку. Остался последний вопрос - timeGetTime () берёт значение таймера прямо из памяти?
 

lazybiz

Well-Known Member
03.11.2010
1 339
0
#15
Я на 90% уверен что в Windows нет функции, которая читает значение таймера из адреса BIOS 0x46c.
А тебе вообще нужно время выполнения функции замерить или из память читать?