Почему вы не можете установить указатель инструкции напрямую?
Статья в Википедии о сборке x86 говорит о том, что «к IP-регистру не может напрямую обращаться программист».
Прямо означает с инструкциями, такими как mov и add.
Почему нет? В чем причина этого? Каковы технические ограничения?
- Может ли x86 переупорядочить узкий магазин с более широкой нагрузкой, которая полностью его содержит?
- Получить количество циклов процессора?
- Действительно ли ADD 1 быстрее INC? x86
- Ассемблер ADC (добавить с переносом) в C ++
- SIMD, подписанный с неподписанным умножением для 64-разрядных * 64-бит до 128 бит
- Самый быстрый способ вычисления абсолютного значения с помощью SSE
- Печать шестнадцатеричных цифр со сборкой
- Ссылка на содержимое ячейки памяти. (режимы адресации x86)
- Почему EDX должен быть 0, прежде чем использовать инструкцию DIV?
- Режимы микросовключения и адресации
- Снижается ли производительность при выполнении циклов, чей счетчик uop не кратен ширине процессора?
- Эффективная функция сравнения целого числа
- Могу ли я использовать синтаксис Intel сборки x86 с GCC?
Вы не можете получить к нему доступ напрямую, потому что нет законного варианта использования. При любом произвольном изменении команды 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