Почему вы не можете установить указатель инструкции напрямую?

Статья в Википедии о сборке x86 говорит о том, что «к IP-регистру не может напрямую обращаться программист».

Прямо означает с инструкциями, такими как mov и add.

Почему нет? В чем причина этого? Каковы технические ограничения?

Вы не можете получить к нему доступ напрямую, потому что нет законного варианта использования. При любом произвольном изменении команды eip очень затруднит предсказание ветвления и, вероятно, откроет целый ряд проблем безопасности.

Вы можете редактировать eip используя jmp , call или ret . Вы просто не можете напрямую читать или писать в eip используя обычные операции

Установка eip в регистр выполняется так же просто, как jmp eax . Вы также можете делать push eax; ret push eax; ret , который выталкивает значение eax в стек и затем возвращает (т.е. всплывает и переходит). Третий вариант – это call eax который вызывает вызов в eax.

Чтение может быть выполнено следующим образом:

 call get_eip get_eip: pop eax ; eax now contains the address of this instruction 

Это был бы возможный дизайн для x86. ARM делает свой счетчик программ для чтения / записи как R15 . Это необычно.

Он позволяет очень компактную функцию prolog / эпилог, а также возможность выталкивать или записывать несколько регистров с помощью одной команды: push {r5, lr} на входе и pop {r5, pc} чтобы вернуться. (Отображение сохраненного значения регистра ссылок в счетчик программ).

Тем не менее, он делает реализацию ARM с высоким приоритетом / невыполнением заказов менее удобным и был сброшен для AArch64.


Так что это возможно, но использует один из регистров . 32-разрядная ARM имеет 16 целых регистров (включая ПК), поэтому номер регистра занимает 4 бита для кодирования в машинном коде ARM. Другой регистр почти всегда связан как указатель стека, поэтому ARM имеет 14 универсальных регистров общего назначения. (LR может быть сохранен в стеке, поэтому он может быть и используется как регистр общего назначения внутри тел функции).

Большинство современных x86 унаследовано от 8086. Оно было спроектировано с довольно компактным кодированием команд переменной длины и только 8 регистров, для которых требуется всего 3 бита для каждого регистра src и dst в машинный код.

В исходном 8086 они не были очень универсальными, а относительная адресация по SP не возможна в 16-битном режиме, поэтому по существу 2 регистра (SP и BP) привязаны для материала стека. Это оставляет только 6 регистров общего назначения, и одним из них является ПК вместо общего назначения, это будет огромным сокращением доступных регистров, что значительно увеличит количество разливов / перезагрузок в типичном коде.


AMD64 добавил r8-r15 и режим относительной адресации RIP. lea rsi, [rip+whatever] и RIP-относительные режимы адресации для прямого доступа к статическим данным и константам – все, что вам нужно для эффективного независимого от позиции кода. Непрямые инструкции JMP полностью достаточны для записи в RIP.

На самом деле нет ничего, что можно было бы сделать, разрешив использование произвольных инструкций для чтения или записи ПК, поскольку вы всегда можете сделать то же самое с регистром целого числа и косвенным прыжком. Это было бы почти чистым недостатком для R86 x86-64, чтобы быть тем же самым, что и RIP, особенно для производительности архитектуры в качестве цели компилятора. (Hand-написанный странный материал был уже очень необычной нишей к 2000 году, когда AMD64 был разработан.)

Итак, AMD64 – это в первый раз, когда x86 вполне мог получить полностью открытый счетчик программ, такой как ARM, но было много серьезных причин не делать этого.

Я думаю, что они имели в виду, что доступ к IP-адресу невозможно получить напрямую, так же, как к другим регистрам. Программисты могут определенно писать на IP, например, выдавая инструкцию перехода.

jmp установит регистр EIP .

этот код установит eip на 00401000:

 mov eax, 00401000 jmp eax ;set Eip to 00401000 

и для получения EIP

 call GetEIP . . GetEIP: mov eax, [esp] ret 
  • x86_64 ASM - максимальные байты для команды?
  • 8086 на DOSBox: ошибка с инструкцией idiv?
  • В чем смысл MOV (% r11,% r12,1),% edx?
  • Почему инструкции x86-64 на 32-разрядных регистрах обнуляют верхнюю часть полного 64-битного регистра?
  • Как сгенерировать код сборки с clang в синтаксисе Intel?
  • System.BadImageFormatException: не удалось загрузить файл или сборку (из installutil.exe)
  • Что означают префиксы E и R в именах 32-битных и 64-битных регистров Intel?
  • Ошибка Weird MSC 8.0: «Значение ESP не было должным образом сохранено в вызове функции ...»
  • Какие целые операции с дополнением 2 можно использовать без обнуления высоких бит в входах, если требуется только низкая часть результата?
  • Почему (или нет?) SFENCE + LFENCE эквивалентно MFENCE?
  • Почему целочисленное переполнение на x86 с GCC вызывает бесконечный цикл?
  • Interesting Posts

    Кнопки раскраски в Android с материальным дизайном и AppCompat

    Что такое «пакет» в приложении для Android

    Как я могу определить, какой из моих USB-накопителей можно сделать загрузочным

    Неверный fragment в ViewPager получает onContextItemВыбранный вызов

    Как использовать JarOutputStream для создания JAR-файла?

    Word 2010: Как ссылаться на пользовательские свойства документа?

    Получение имени текущего исполняемого метода

    Почему double.NaN не равно себе?

    Когда я могу сначала измерить вид?

    Лучшие способы анализа URL с помощью C?

    В чем разница между возвратом пустоты и возвратом задачи?

    Возможные причины Java VM EXCEPTION_ACCESS_VIOLATION?

    Является ли указатель с правильным адресом и типом все еще всегда действительным указателем с C ++ 17?

    Могу ли я получить доступ к архивам Microsoft Outlook PST с помощью любых других инструментов?

    jquery scroll, изменить активный class навигации, поскольку страница прокручивается относительно разделов

    Давайте будем гением компьютера.