2013-03-12 2 views
-1

Я хочу понять на низком уровне, как ввод задан функции. Что именно происходит после запуска функции? Например, рассмотрим следующее:Низкоуровневое описание присвоений ввода функции

int foo(int t1, int t2) 
{ 
    Function defintion goes here 
} 

Тогда позже в коде

main() 
{ 
    . 
    . 
    int a= foo(23, 24); 
    . 
    . 
} 

Предположим, что код успешно компилируется и мы получим двоичный файл, т.е. EXE-файл, соответствующий нашему источнику высокого уровня код. Я хочу понять, на каком уровне вводятся внутренние функции, и что именно происходит, когда мы дважды щелкаем по этому .exe-файлу. Какие программные/аппаратные средства вступают в игру после нажатия на .exe? Буду признателен, если кто-то может дать мне краткое описание.

По просьбе

ОС: Windows CPU: Intel Core2Duo

+5

Вы спрашиваете далеко, слишком много, чтобы на это ответить. Если это в Windows, прочитайте о файлах PE и загрузчиках окон и x86. Если это Linux, прочитайте об файлах Elf и загрузчике Linux. –

+0

@gpuguy Этот вопрос будет замечательным, если вы можете назвать одну точную ОС и какой компилятор используется. В противном случае вопрос может быть слишком широким для того, чтобы кто-либо дал осмысленный ответ. – Lundin

+1

Я согласен с Джонатоном.Вы также хотите посмотреть на что-то, называемое «стек вызовов». – Panzercrisis

ответ

1

Насколько вызовы функций идти, во-первых, литералы 23 и 24 загружаются в специальные регистры в вашем CPU (используется регистры для параметров функции). Затем ваш код переходит к разделу, когда находится функция foo.

foo считывает из регистров, указанных выше, чтобы получить доступ к t1 и t2, вычисляет возвращаемое значение, и запоминает это значение в еще одном регистре. Затем foo возвращается обратно туда, где он был вызван в основном.

Главное затем считывает из регистра, где хранилось возвращаемое значение foo, и помещает это значение в переменную x.

Это описание на высоком уровне того, что происходит при вызове функции. Более подробное объяснение, вероятно, слишком много, чтобы ожидать из переполнения стека (но, возможно, нет).

+4

Или литералы сохраняются непосредственно по определенным адресам в стеке или внутри выравниваемого фрейма стека. Или, возможно, только один из них сохраняется в стеке. Или, может быть, вызывающая конвенция диктует, что сама функция отвечает за параметры стекирования, так что они заканчиваются там, где наиболее удобно для конкретной функции. Или они вообще не сохраняются, возможно, компилятор оптимизировал или вложил всю функцию. И так далее. – Lundin

+0

@ Lundin Sure; Я просто пытался предоставить базовое/краткое описание того, как обычно может выглядеть вызов функции. – Alec

+0

Кто выполняет эту работу по загрузке 23, 24 в конкретные регистры? ОПЕРАЦИОННЫЕ СИСТЕМЫ? – gpuguy

0

Вы должны быть более конкретным о платформе, для которой вы пишете код. Различные аппаратные и программные платформы используют разные ABI, то есть способ передачи параметров между вызовами.

Кроме того, это может зависеть от версии компилятора и диалекта языка, который вы используете.

http://en.wikipedia.org/wiki/X86_calling_conventions http://en.wikipedia.org/wiki/Application_binary_interface

Чтобы получить ответ вы должны указать: аппаратную платформу, версию ОС, компилятор, который будет использоваться язык и эта вещь написана с (C/C++) или просто звоню условные обозначения, используемые.

Примеры отличий: На ARM некоторые параметры могут передаваться через регистры, а некоторые - через стек. На x86 большинство параметров передаются в стек (за исключением заметных исключений из методов C++), порядок аргументов определяется языком и условным обозначением, а выравнивание является стандартным или в случае M-soft, коммерческой спецификации ,