OSDev http://osdev.su/ |
|
GCC long jump http://osdev.su/viewtopic.php?f=6&t=354 |
Страница 1 из 1 |
Автор: | The Odd Beard [ 27 ноя 2010, 07:17 ] |
Заголовок сообщения: | GCC long jump |
Нужно сделать длинный прыжок на функцию Код: void *func; void someproc(){ //надо сюда ... } void main(){ ... func = (void*)someproc; //получть адрес функции __asm__("lgdt gdtr"); __asm__("lcall $8, $func"); } Насколько мне известно, $func даёт адрес переменной, посему прыжок не выходит. Как вставить значение переменной? (такой код Код: __asm__("lcall $8, func"); не компилируется). Если вместо Код: __asm__("lcall $8, $func"); поставить абсолютный адрес Код: __asm__("lcall $8, $0xC0000000"); , то всё работает как надо.
|
Автор: | SII [ 27 ноя 2010, 11:42 ] |
Заголовок сообщения: | Re: GCC long jump |
Я с GCC не работаю, но могу сказать, что в таком варианте одной командой перехода не обойтись: система команд ИА-32 не обеспечивает возможность перехода к подпрограмме по адресу, хранящемуся в памяти, как это имеет место быть в Вашем случае. По всей вероятности, здесь придётся действовать через задницу: 1) запихнуть вручную в стек адрес возврата; 2) запихнуть в стек адрес перехода; 3) выполнить дальний RET, который и выполнит переход к нужной подпрограмме. |
Автор: | The Odd Beard [ 27 ноя 2010, 21:46 ] |
Заголовок сообщения: | Re: GCC long jump |
Спасибо, помогло. Я только недавно пересел на GCC/AT&T, раньше программил на Pascal/Intel. |
Автор: | SII [ 27 ноя 2010, 22:13 ] |
Заголовок сообщения: | Re: GCC long jump |
Ну, я под Винду пишу исключительно на Дельфях, а не под Винду -- на асме, плюс экспериментирую с Адой (из ГЦЦ) и ФриПаскалем. Си/Си++ ненавижу, не использую и не собираюсь (кроме как в случаях, когда по работе это прямо требуется). |
Автор: | Himik [ 28 ноя 2010, 15:04 ] |
Заголовок сообщения: | Re: GCC long jump |
The Odd Beard, изучи типы адресации в Ассемблере. Такого непосредственно-косвенного вызова не бывает. В твоём примере первый операнд, который номер селектора, это непосредственное значение, а второй операнд, который линейный адрес, это косвенное значение, тоесть ты всё смешал. Правильно, что вторая запись, где ты прописываешь оба непосредственных значения, у тебя сработала, так и должно быть. А если надо сделать косвенный вызов, то оба значения должны находиться в переменной-указателе, а в инструкции call прописан только адрес указателя. Сам указатель надо расширить до двух значений. Примерно так, я не проверял. Но основной принцип такой: Код: int func[2]; //Первое значение - линейный адрес, второе - селектор. func[0] = (int)&some_proc; func[1] = 8; asm("lcall FAR PTR $func"); После команды компиляции вызови ту же компиляцию, только с параметром -S, при этом создастся ассемблерный файл - эквивалент исходной Си программы. Файл появится с расширением .s. По нему проверишь результат. Ещё совет - компилятору можно указать параметр -masm=intel тогда ассемблерные вставки можно будет писать в синтаксисе Intel. asm("call FAR PTR [func]"); |
Автор: | The Odd Beard [ 30 ноя 2010, 03:44 ] |
Заголовок сообщения: | Re: GCC long jump |
chizh, спасибо. Поэкспериментировал с твоим методом. Код: typedef struct jmptr{ void* addr; unsigned short segment; } jmptr; ... jmptr jtag; void main(){ ... func = &somefunc; jtag.segment = 8; jtag.addr = func; __asm__("lcall (jtag)"); } Вот так работает. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |