Является ли pop eip юридической инструкцией? - PullRequest
1 голос
/ 20 июня 2019

Я работаю над этим теоретическим тестом, который я получил в университете, и мне задали этот вопрос: после некоторого обучения esp вырос на 4, а eip вырос на 20, что может быть инструкция?Я пометил «pop eip» и «ret».Возможно ли в nasm 32-битной сборке выполнить команду pop eip?

1 Ответ

7 голосов
/ 20 июня 2019

pop eip - не настоящая инструкция x86. Никакой ассемблер не будет ее собирать, AFAIK.

Это псевдокод для , объясняющий , что делает ret.См. Раздел «Эксплуатация» в руководстве .В частности, нормальный "рядом" ret;far jmp / call / ret в основном не используются в "нормальном" 32-битном коде.

ret имеет свой собственный код операции, отличный от любой кодировки для pop, и x86 также решает дать емуОтдельная мнемоника.Это был бы действительный дизайн для pop eip, который также был бы принят в качестве другого имени для кода операции 0xc3.x86 имеет мнемонику mov, перегруженную для многих различных кодов операций, включая mov в / из управляющих регистров , mov в / из регистры отладки , а также стандарт mov между целочисленными регистрами и / или памятью или непосредственно.(Однако в этой «стандартной» форме mov также есть несколько различных кодов операций.)

Но это было бы немного странно, потому что push eip не существует, за исключением call +0, которыйимеет побочный эффект производительности - скачок.

EIP не является одним из 8 целочисленных регистров общего назначения, поэтому обычные кодировки pop не могут кодировать ret.Это одна из причин, по которой ret нужен собственный код операции, и поэтому имеет смысл иметь отдельную мнемонику в источнике asm.Инструкции x86 кодируют регистры как 3-битные числа или, необязательно, 4-битные на x86-64.Или как неявный источник или назначение, например EDX: EAX для mul или div, или pushf неявно читает EFLAGS: это просто подразумевается этим кодом операции без каких-либо битов, которые конкретно означают EFLAGS.


ret не волшебство: все, что он делает, это подбрасывает стек и использует результат в качестве цели прыжка.Программист должен убедиться, что ESP указывает на адрес, на который вы хотите перейти, обычно это обратный адрес.

Некоторые новички не понимают этого и думают, что ret волшебным образом вернется к последнему call, поэтому они не устанавливают связь между ошибками на ret и их кодом, запутывающим стек.

Я определенно написал что-то вроде "ret - это имя, которое мы используемна x86 для pop eip "в SO вопросы и ответы много раз.

Интересный факт: на 32-битном ARM счетчик программы равен одному из 16 целочисленных регистров,r15, так что вы действительно можете pop {r4, pc} восстановить сохраненный R4 и вставить сохраненный lr (регистр связи = обратный адрес) в счетчик программ все в одной инструкции.Таким образом, ARM буквально может сделать эквивалент pop eip с тем же кодом операции, который он использует для получения целочисленных регистров общего назначения.


esp вырос на 4, а eip увеличился на 20

Да, я думаю C3 ret или C2 ret 0 - это только 2 опкода, которые могут сделать это, и оба используют мнемонику ret.

ЕслиEIP вырос на 15 или меньше, его может объяснить длинная кодировка add esp, 4 или pop eax, например, с несколькими избыточными префиксами rep и / или fs и кодировкой imm32 для немедленной 4.

x86 инструкции могут быть длиной не более 15 байтов;если декодирование не достигает конца инструкции до 15 байт, процессор принимает исключение #UD, как и для других недопустимых инструкций.Таким образом, изменение EIP на 20 байтов одной инструкцией возможно только с помощью перехода.И единственный скачок, который увеличивается ESP - ret;jmp / jcc оставляют его без изменений, call выдвигает обратный адрес.

iret почти возможно, но он выдает CS:IP и значение FLAGS: вы не можете получить его для выгрузки только 4 байта.(Особенно в 32-битном режиме.)

sysret не изменяет ESP, и может использоваться только ядром (кольцо 0).sysexit устанавливает RSP из RCX и RIP = RDX, но я уверен, что это не тот ответ, который они искали.: P

...