Возвращаемое значение из функции обычно сохраняется в регистре eax процессора, поэтому оператор «return 4;»обычно компилируется в
mov eax, 4;
ret;
, а return x (в зависимости от вашего компилятора) будет выглядеть примерно так:
mov eax, [ebp + 4];
ret;
, если вы не укажете возвращаемое значение, компилятор все равно будетвыплюнуть "ret", но не изменяет значение eax.Таким образом, вызывающий объект будет думать, что то, что когда-либо ранее оставалось в регистре eax, является возвращаемым значением.Для этого примера это обычно будет возвращаемое значение printf, но разные компиляторы будут генерировать разный машинный код и по-разному использовать некоторые регистры.
Это упрощенное объяснение, различные соглашения о вызовах и целевые платформы будут играть важную роль, нов вашем примере должно быть достаточно информации, чтобы объяснить, что происходит «за кулисами».
Если у вас есть базовое понимание ассемблера, стоит сравнить разборку различных компиляторов.Вы можете обнаружить, что некоторые компиляторы очищают регистр eax в качестве меры безопасности.