2013-08-02 2 views
0

Я начал программировать c++ вместе с языком ассемблера. Я хотел бы прояснить некоторые вещи. Из того, что я читал, указатель инструкции получает адрес, где он должен выполняться следующим образом из инструкции retn. Не будет так же, как делать jmp, потому что jmp также устанавливает указатель инструкции.сборка retn, jmp, регистра процесса

Если я прав, какая разница между retn и jmp? Если я ошибаюсь, может кто-нибудь объяснить с помощью псевдокода?

Что такое эквивалент сборки для бесконечного цикла?

Я читал, что EAX,EBX,ECX,EDX взаимозаменяемы, но имеют ли они какую-либо разницу? Если да, то в каком сценарии я должен использовать EAX/EBX/ECX/EDX.

Благодаря

ответ

3

Вы, кажется, говорили о подпрограммах, так вот подноготная на этом.

Когда вы вызов подпрограммой, это выглядит примерно так (адреса будут отличаться друг от друга, но я не хочу, чтобы запутать вас с указанием переменной длины):

1234 call 8888 
1235 <next instruction> 

Что происходит, что call сначала помещает следующий указатель инструкции 1235 в стек (структура данных с последним в первом порядке), а затем устанавливает указатель на то, что вы вызываете, 8888 в этом случае.

Позже, возврат производится в 8889:

8888 mov eax, 0 
8889 ret 

Что возвращение делает это просто поп первое значение из стека (т.е. 1235, который был выдвинут призыв) и загружает его в указатель инструкции. Так что это не возвращение, рассказывающее вам, куда идти, это информация, которая была нажата на стек по вызову .

Если вы имели jmp инструкцию в конце вашей подпрограммы, было бы только смог вернуться в одну точку в коде (дисконтирование все замечательные вещи, которые вы могли бы сделать с другими режимами адресации на данный момент):

8889 jmp 1235 

Используя возврат, вы возвращаетесь туда, куда бы вы ни пришли, независимо от того, где это было.


Ассемблер для бесконечного цикла может быть простым, как:

loopy: 
    jmp loopy 

Что касается регистров, eax, ebx, ecx и edx рассматриваются регистры общего назначения. Это отличает их от регистров особого назначения, таких как указатель стека, указатель базы, указатели источника и адресата и т. Д., Которые имеют специализированные инструкции в зависимости от их использования.

ax, возможно, имел некоторые дополнительные полномочия в очень ранних итерациях архитектуры x86, но я не уверен, что это все еще так. Если вы кодируете свои собственные материалы, вы должны в основном использовать их взаимозаменяемо. Если вы следуете API или ABI, вам необходимо следовать правилам, которые он налагает (например, интерфейс системного вызова Linux, где eax содержит номер системного вызова).

+0

Спасибо за ваш быстрый ответ, я понимаю сейчас. – Imaginarys

0

eax и edx являются неявными операндами в делении и int широкомасштабными версиями умножения. Существуют также специальные инструкции по расширению знака, которые работают только с части rax (код операции 98) или с расширением знака eax в edx:eax (код операции 99). Десятичные математические инструкции работают по частям eax.

ecx (ну cl действительно, но достаточно близко) является единственным регистром, который вы могли бы сдвинуться перед тем Haswell (который вводит sarx, shlx и shrx все из которых могут смещаться любым GPR). ecx также используется в качестве счетчика префиксами rep. pcmp*stri ставит длину в ecx.

Многие инструкции специального назначения не имеют явных операндов, но вместо того, чтобы присвоить специальное значение определенное GPR, например cpuid, rdpmc, rdtsc, wrmsr, xgetbv, xsave. Обычно edx:eax, часто ecx также, и очень редко ebx. Вам, вероятно, не придется иметь дело с этим много.

1

Разница ret и jmp в терминах C/C++ функция похожа на это:

int foo() 
{ 
    int x = 3+4; 

    if(x < 10) 
     goto Quit; <- similar to jmp 

    x += 10; 

Quit: 
    return x;  <- similar to ret 

}

Когда вы return в C, это немного сложнее, что на самом деле происходит на на уровне машины, потому что часто выполняется дополнительный код, например, возвращаемое значение в eax и очистка стека. «В C++ локальные объекты также будут дезактивированы, но в конце и в функции будет команда ret.

Что такое эквивалент сборки для бесконечного цикла?

while(1); 

является как

000000 jmp 000000 

или более продвинутые

00000 inc ecx 
00001 jmp 00000 

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

Одним из примеров является movsw, в котором вам необходимо использовать (E)SI и (E)DI, поэтому в этом случае вы не можете свободно выбирать. Если вы используете rep movsw, то также используется (E)CX. Как правило, ассемблер знает, какие регистры действительны для инкремента, и вы получите сообщение об ошибке, но, конечно, вы должны найти руководство, чтобы убедиться, что вы можете получить неожиданные результаты, если ассемблер не может выполнить ошибку.