Помогите, плз, совладать с Turbo C+ (получить адрес метки)

Статус: Offline
Реєстрація: 02.07.2009
Повідом.: 201
Помогите, плз, совладать с Turbo C++ (получить адрес метки)

Пишу на C++ программу, которая переводит микропроцессор (МП) из реального режима (real mode, R-mode) в защищённый (protected mode, P-mode).

Необходимо сформировать адрес возврата - адрес команды, которая получит управление после сброса МП.

имеется код вроде такого:

Код:
unsigned int ret_offset = 0; // Смещение точки возврата в реальный режим

int main() {
     // нужно получить адрес возврата:
     ret_offset = FP_OFF( &prot_exit ); // не работает. компилятор ругается, что получить адрес метки prot_exit невозможно

     // вторая попытка получить адрес возврата
     asm {
          mov ret_offset, offset prot_exit // компилятор ругается: неизвестный идентификатор prot_exit
          lea ret_offset, prot_exit // то же самое: неизвестный идентификатор prot_exit
     }

     < переход в защищённый режим >

prot_exit: // метка - наша точка возврата

     < Действия, которые выполняются после перехода из защищённого     
          режима обратно в реальный - восстановление сегментных
          регистров и т.д. >

     return 0;
}


Короче говоря, после сброса МП, начинает выполняться та команда, адрес которой записан в памяти по адресу 40:67h. Мне нужно, чтобы по этому адресу находился адрес первой команды, расположенной после метки prot_exit, но я никак не могу получить её адрес.

В Turbo Pascal проблема решалась следующим образом:

Код:
label
     prot_exit; // объявление метки
var
     ret_offset: Word; // Смещение точки возврата
begin

     { получение адреса первой команды, которая идёт за меткой prot_exit }
     { компилятор прекрасно понимает идентификатор prot_exit внутри ассемблерной вставки }
     asm
          mov ret_offset, offset prot_exit
     end;

     < переход в защищённый режим >

prot_exit: // метка - наша точка возврата

     < Действия, которые выполняются после перехода
          из защищённого режима обратно в реальный - восстановление 
          сегментных регистров и т.д. >

end.

Не знаю даже, что и делать, откуда узнать адрес точки возврата.
В GCC неофициально есть оператор - &&ИДЕНТИФИКАТОР_МЕТКИ, который позволяет получить адрес, но Turbo C++, увы, такого не умеет.

Можно, конечно, написать новую функцию, перенести в неё весь код по восстановлению регистров и т.д., а затем указать её адрес в качестве адреса возврата... Но куда вернётся управление после завершения этой функции? Ведь всё равно понадобится получить адрес возврата :рл:.

Думал, что можно при помощи ассемблерной вставки получить содержимое регистра IP и занести его значение в переменную ret_offset, но компилятор ругается - "неизвестный идентификатор - IP" (видимо, таким образом Turbo C++ запрещает программисту привязывать свой код к значению IP).

Подскажите, пожалуйста, как можно узнать адрес какой-либо команды, расположенной в определённой части функции Main.
Буду признателен за любую помощь по данному вопросу.
 
Останнє редагування:
Я не специалист по данному вопросу, но интернеты говорят, что вся беда в том, что Borland'ский компилятор не умеет делать ссылку на метку, которая позже по коду.
 
вся беда в том, что Borland'ский компилятор не умеет делать ссылку на метку, которая позже по коду.
Проверял - Turbo C++ не может получить адрес метки даже объявленой ранее :( .

Ну а как бы можно было бы провернуть этот фокус без меток? В смысле, чтобы управление по выходе из защищённого режима вернулось в функцию Main? А то пока что на ум приходит только один вариант - написать основной модуль на ассемблере, все сложные функции - на С, и скомпилить их вместе. Но хотелось бы по возможности этого избежать.
 
Перше, що спало на думку:
Код:
unsigned int ret_offset = 0; // Смещение точки возврата в реальный режим

int main() {
     goto start;
     goto prot_exit;
start:
     // нужно получить адрес возврата:
     ret_offset = FP_OFF( (unsigned int) main + 2 ); // адрес "goto prot_exit;"

     < переход в защищённый режим >

prot_exit: // метка - наша точка возврата

     < Действия, которые выполняются после перехода из защищённого     
          режима обратно в реальный - восстановление сегментных
          регистров и т.д. >

     return 0;
}
 
Перше, що спало на думку:
Код:
unsigned int ret_offset = 0; // Смещение точки возврата в реальный режим

int main() {
     goto start;
     goto prot_exit;
start:
     // нужно получить адрес возврата:
     ret_offset = FP_OFF( [COLOR="Red"][B](unsigned int) main[/B][/COLOR] + 2 ); // адрес "goto prot_exit;"

     < переход в защищённый режим >

prot_exit: // метка - наша точка возврата

     < Действия, которые выполняются после перехода из защищённого     
          режима обратно в реальный - восстановление сегментных
          регистров и т.д. >

     return 0;
}
Э-э-э... Думаешь выделенное красным - хорошая идея? :)
Вообще у ТС-а неправильная концепция. Он хочешь симитировать возврат из подпрограммы для банального безусловного перехода. Такой финт ушами конечно существует - но нахуа окромя шеллкода и эксплойта на переполнение стека? ;)
Вместо извращений - просто нужна грамотная архитектура программы.
 
1) первый вариант - оформить переход в защищенный режим как функцию, из тела функции прочитать адрес возврата на вершине стека и скорректировать стек так чтобы сымитировать возврат из функции по сути его не делая. В итоге имеем адрес возврата и продолжаем делать свои дела внутри функции...

2) второй вариант - перед адресом возврата делаем ASM вставку в стиле
Код:
  asm {
   dw 0C0FEh
  }
  // тут код адрес которого мы ищем

Берем указатель на main и ищем по байтам нужную сигнатюру, инкрементим указатель на длину сигнатюры и получаем адрес возврата.
 
Останнє редагування:
Останнє редагування:
1 - Подобными вопросами я не занимался. Но есть подозрения что рантайм будет не сильно в удовольствии если вдруг внутри него процессор перейдет в защищенный режим, хотя может в далекие времена доса это было и нормуль.
2 - По поводу проблемы - считай секцию кода, найди в ней мейн, в мейне поищи точку выхода (например можно использовать функцию маркер, которая будет вызываться только раз в точке выхода, нифига не делать (главное шоб аптимизатор ее тока не прихлопнул) дальше в коде мэйна ищещ переход на эту функцию и устанавливаешь по ней код возврата, ну или на инструкцию сразу за ней.
 
1) первый вариант - оформить переход в защищенный режим как функцию, из тела функции прочитать адрес возврата на вершине стека и скорректировать стек так чтобы сымитировать возврат из функции по сути его не делая. В итоге имеем адрес возврата и продолжаем делать свои дела внутри функции...

Первый вариант гениален! А я вот до него не додумался! Действительно, переход в защищённый режим можно оформить в виде функции (назовём её, скажем, init_prot), в самом начале которой можно прочитать из стека адрес возврата в main, занести его в 40:67h, и со спокойной душой переводить МП в защищённый режим. При сбросе МП выполнение программы перейдёт к следующей команде после вызова функции init_prot.

Очень элегантное решение, спасибо огромное :).

Можно, конечно, и маркер оставить в main, а потом отдельной функцией его найти и получить смещение следующей команды, но первый вариант значительно проще и изящнее :)

Перше, що спало на думку:
Это тоже неплохой вариант, попробую и его :)

Спасибо всем огромнейшее за помощь! :) Впереди ещё много работы - организачия перехода в защищённый режим, установка вентилей прерываний и исключений, а застопорился на получении адреса возврата, и никуда не мог сдвинуться с места.
 
Спасибо всем огромнейшее за помощь! :) Впереди ещё много работы
Я так понимаю, ты изобретаешь машину времени, которая наконец позволит перенестись тебе из прошлого в настоящее и забыть о всех этих глупостях, которыми ты занимаешься. Верно? :D
 
Я так понимаю, ты изобретаешь машину времени, которая наконец позволит перенестись тебе из прошлого в настоящее и забыть о всех этих глупостях, которыми ты занимаешься. Верно? :D

а что смешного? человеку интересно, вот это и есть настоящий программер, будет хацкером :)
 
а что смешного? человеку интересно, вот это и есть настоящий программер, будет хацкером :)
Если ему действительно интересно - то пусть для начала пошарится например на васм.ру. Там есть неплохие переводы "для чайников" про реальный/защищенный режимы, в том числе и с примерами как надо делать.
 
Назад
Зверху Знизу