ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
29 ноября
963711 Топик полностью
fk0, легенда (10.12.2019 11:10, просмотров: 433) ответил POV_ на Ты чего дурака-то включаешь? Я ж ясно тут отписался уже..
Дурака включаешь ты и реально не догоняешь даже. Смотри, вариант 1:  https://godbolt.org/z/b7fLgY вариант 2: https://godbolt.org/z/ju9yry В варианте 2 временные переменные (bb) далеко от вершины стека (+20, +24, +28), в варианте 1 -- сразу кладутся в [sp] и/или передаются в регистры, без записи в стек. В одном случае (вариант 1) в стеке резервируется 28 байт, в другом (вариант 2) -- 36 байт. В первом варианте вызов функции f() может попортить данные на вершине стека и сломать работу sprintf (испортить её аргумент), вот здесь: bl f ldr r4, .L3+4 str r0, [sp] в варианте 2 такое невозможно, там если даже байт 20 затрёшь с вершины, всё пройдёт гладко: ldr r4, .L3+4 ldr r1, [sp, #28] ldr r3, [sp, #24] str r1, [sp] ldr r2, [sp, #20] ldr r1, .L3+8 movs r0, r4 bl sprintf Даже если компилятор и резервирует место под все переменные в начале функции, то это не значит, что они окажутся именно в этом месте относительно SP, а не в другом или вообще не окажутся в регистрах (временные переменные созданные компилятором, аргументы сразу передаваемые в другую функцию скорей окажутся на вершине стека, а переменные созданные руками -- далеко от вершины). И хуже того, это не так: в ряде случаев место выделяется динамически... (variable length arrays, передача аргументов в variadic функции в частности, всё что не помещяется в регистрах идёт через стек, место выделяется -- вот сразу туда и можно класть, даже если в стеке что-то зарезервировано ещё).
[ZX]