Статья в Википедии о сборке x86 гласит, что "к IP-адресу нельзя напрямую обращаться программистом".
Прямо означает с помощью команд, таких как mov и add.
Почему бы и нет? В чем причина этого? Каковы технические ограничения?
Статья в Википедии о сборке x86 гласит, что "к IP-адресу нельзя напрямую обращаться программистом".
Прямо означает с помощью команд, таких как mov и add.
Почему бы и нет? В чем причина этого? Каковы технические ограничения?
Вы не можете получить к нему доступ напрямую, потому что нет законного варианта использования. Любое произвольное изменение команды eip очень затруднит предсказание ветвления и, вероятно, откроет целый ряд проблем безопасности.
Вы можете редактировать eip с помощью jmp, call или ret. Вы просто не можете напрямую читать или писать на eip с помощью обычных операций
Установка eip в регистр так же просто, как jmp eax. Вы также можете сделать 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. Однако это необычно.
Он позволяет очень компактную функцию пролог/эпилог, наряду с возможностью нажатия или всплытия нескольких регистров с помощью одной команды: 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.
На самом деле ничего не может быть сделано, если разрешить использование произвольных инструкций для чтения или записи ПК, так как вы всегда можете сделать то же самое с регистром целого числа и косвенным прыжком. Было бы почти чистым недостатком для x86-64 R15, чтобы быть тем же самым, что и RIP, особенно для архитектуры performace в качестве цели компилятора. (Рукописный материал ASM был уже очень необычной нишей к 2000 году, когда был разработан AMD64.)
Итак, AMD64 - это первый случай, когда x86 мог бы получить полностью открытый программный счетчик, такой как ARM, но было много серьезных причин не делать этого.
jmp установит регистр EIP.
этот код установит eip на 00401000:
mov eax, 00401000
jmp eax ;set Eip to 00401000
и для получения EIP
call GetEIP
.
.
GetEIP:
mov eax, [esp]
ret
Я думаю, что они имели в виду, что доступ к IP-адресу невозможен напрямую так же, как к другим регистрам. Программисты могут определенно писать на IP, например, выдавая инструкцию перехода.