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

Тема в разделе "Общие вопросы по С и С++", создана пользователем -, 2 дек 2010.

  1. Гость

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

    lazybiz Well-Known Member
    C\C++ Team

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

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Visual C++ еще и не знает о существовании прямого доступа к системному таймеру.
    MK_FP - это макрос для компиляторов под DOS. Та программа, которую вы переписываете с паскаля работала в DOS-е в 16-битном режиме.
     
  4. Гость

    Borland C++ 3.1 сойдёт?
    Надеюсь, он может об этом узнать через ассемблерную вставку в программе. Как я понимаю, что-то вроде этого:
    Код (Text):
    mov dword ptr[lptime], dword ptr[46Ch]; 46Ch - или как там на ассемблере это пишется...
     
  5. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Ни разу им не пользовался, но думаю что сойдет.

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

    Знать бы, для чего это нужно...
    И обойти Windows никак нельзя?
     
  7. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Можно попробовать заменить чтение таймера какой-нибудь функцией. Может ты код выложишь?
     
  8. Гость

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

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

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Что-то я не вижу, чтобы ты тут к адресу 0x46с обращался...

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

    Функция DWORD getTime (void) - это по сути прямое обращение к таймеру...
    Если на Паскале - вот на Паскале:
    Код (Text):
    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.
    Вот программа на Паскале:
    Код (Text):
    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.
    Но что даст этот код? Я уже задал другой вопрос:
    Добавлено:
     
  11. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    > Функция DWORD getTime (void) - это по сути прямое обращение к таймеру...
    Ты ее откуда откопал вообще?

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

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

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

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

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

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    > Мне как раз нужно создать эту функцию.
    Не делай из мухи слона и не изобретай велосипед.
    Вот то что тебе нужно:
    Код (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 () берёт значение таймера прямо из памяти?
     
  15. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Я на 90% уверен что в Windows нет функции, которая читает значение таймера из адреса BIOS 0x46c.
    А тебе вообще нужно время выполнения функции замерить или из память читать?
     
Загрузка...

Поделиться этой страницей