https://pastebin.com/g5UWikav >mov [esp+10h+var_10], eax Зачем в этой строке к 10h прибавляется var_10? Как я понял, var_10 = -10h, то есть в итоге получается ноль.
Я вот кстати никогда до конца не понимал, почему GCC/MinGW делает "mov [esp + *], <reg>" вместо "push <reg>" при вызове функций, это что быстрее?
Это скорей всего дизасм. var_10 это подсказка тебе что это за локальная переменная, а 10 - 10 дают [esp + 0], верхушка стека. Если вглядеться, в стеке ровно 10h байт и выделяются под локальные переменные и аргументы. Это для модели вызова типа ccall или в этом духе, где стек функция не выравнивает, esp каким было таким и остается после выхода из нее. Поэтому аргументы засовываются в заранее выделенное место. Шут знает кто и зачем это придумал, ntdll'ные апи например так себя ведут. Возможно как-то связано с тем, что указатель стека должен быть выравнен на 16.
Это помещение аргумента в стек для последующего вызова printf. В данном случае приводит к тому же результату (расположение аргумента наверху стека) что и push eax. cdecl, но бывает что и stdcall вызовы компиль оптимизирует подобным способом. В x64/fastcall тоже часто встречается. Подозреваю что оптимизация по скорости.
1lith, > Как я понял, var_10 = -10h Не правильно понял, это не переменная, а её смещение в локальном буфере, который в стековом фрейме. Это фича диза такая(IDA), помимо смещения для наглядности показывается условная переменная. Что бы было понятно смотри формат эффективного адреса(MODRM): Intel® 64 and IA-32 Architectures Software Developer’s Manual, 2.1.3 ModR/M and SIB Bytes - поле modrm не кодирует регистр esp, для этого используется дополнительный байт SIB, который определяет базу(esp). В эффективном адресе не может быть два смещения. Оно определено в modrm, sib же это индексация base_reg + scale*index_reg.
Это просто тупой диз ассемблер. Правильная команда выглядит так mov [esp+var_10+10h], eax И тут видно что var_10 - это структура по смещению 10h этой структуры записывается eax.