Инструментарий Разработчика Facebook раньше был довольно плох. Теперь версия 2.0 отсутствует и выглядит большой. Вот рецензия.
, Как Использовать Инструментарий Разработчика Facebook 2.0 - Devtacular
Обычно происходит следующее:
команду вызова
, либо через обычную инструкцию jmp
или br
(переход / переход) Подробности вышеизложенного варьируются от платформы к платформе и даже от компилятора к компилятору (см., например, соглашения о вызовах STDCALL и CDECL). Например, в некоторых случаях регистры ЦП используются вместо хранения данных в стеке. Однако общая идея та же
Подробности вышеизложенного варьируются от платформы к платформе и даже от компилятора к компилятору (см., Например, соглашения о вызовах STDCALL и CDECL). Например, в некоторых случаях регистры ЦП используются вместо хранения данных в стеке. Однако общая идея та же
Подробности вышеизложенного варьируются от платформы к платформе и даже от компилятора к компилятору (см., Например, соглашения о вызовах STDCALL и CDECL). Например, в некоторых случаях регистры ЦП используются вместо хранения данных в стеке. Однако общая идея та же
Вы можете убедиться в этом сами:
Под Linux «скомпилируйте» свою программу с помощью:
gcc -S myprogram.c
И вы получите листинг программы на ассемблере (myprogram.s).
Конечно, вы должны немного знать об ассемблере, чтобы понять его (но его стоит изучить, потому что он помогает понять, как работает ваш компьютер). Вызов функции (на архитектуре x86) в основном:
Что происходит при сборке?
Краткое объяснение: текущее состояние стека сохраняется, создается новый стек, загружается и запускается код функции, которая должна быть выполнена. Это включает неудобства для нескольких регистров вашего микропроцессора, некоторые безумные чтения / записи в память, и после этого состояние стека вызывающей функции восстанавливается.
Аргументы помещаются в стек и выполняется инструкция "call"
Вызов представляет собой простой "jmp" с помещением адреса инструкции в стек ("ret" в конце метода хлопая и прыгая на нем)
Думаю, вы хотите взглянуть на стек вызовов, чтобы лучше понять, что происходит во время вызова функции: http://en.wikipedia.org/wiki/Call_stack
Очень хорошая иллюстрация: http://www.cs.uleth.ca/~holzmann/C/system/memorylayout.pdf
1- контекст вызова устанавливается в стеке
2- параметры помещаются в стек
3- выполняется «вызов» метода
Общая идея заключается в том, что вам необходимо
RET
знала, где продолжить. Особенности варьируются от архитектуры к архитектуре. И даже более конкретная специфика может варьироваться в зависимости от языка. Хотя обычно есть способы контролировать это до некоторой степени, чтобы обеспечить взаимодействие между разными языками.
Довольно полезной отправной точкой является статья Википедии о соглашениях о вызовах . Например, на x86 стек почти всегда используется для передачи аргументов функциям. Однако на многих архитектурах RISC
Что происходит? В x86, первая строка вашей основной функции может выглядеть примерно так:
call foo
Инструкция call
помещает адрес возврата в стек, а затем jmp
в местоположение фу.
Общая идея состоит в том, что регистры, которые используются в вызывающем методе, помещаются в стек (указатель стека находится в регистре ESP
), этот процесс вызывается "толкать регистры". Иногда их тоже обнуляют, но это зависит от обстоятельств. Программисты на ассемблере обычно освобождают больше регистров, чем обычные 4 ( EAX
, EBX
, ECX
и EDX
на x86), чтобы иметь больше возможностей. внутри функции.
Когда функция завершается, то же самое происходит в обратном порядке: стек восстанавливается до состояния до вызова. Это называется «извлечение регистров».
Обновление: этот процесс не обязательно должен происходить. Компиляторы могут оптимизировать его и встраивать ваши функции.
Обновление: обычно параметры функции помещаются в стек в обратном порядке, когда они извлекаются из стека, они отображаются как в обычном порядке. Этот порядок не гарантируется C. (ref: Inner Loops
Рик Бут)
What happens?
C mimics what will occur in assembly...
It is so close to machine that you can realize what will occur
void foo() {
printf("in foo");
/*
db mystring 'in foo'
mov eax, dword ptr mystring
mov edx , dword ptr _printf
push eax
call edx
add esp, 8
ret
//thats it
*/
}
int main() {
foo();
return 0;
}