Size: a a a

Ассемблер

2020 August 10

RS

Rusty Shackleford in Ассемблер
Помогите ПОЖАЛУЙСТА )
источник

RS

Rusty Shackleford in Ассемблер
Помогите пожалуйста разобраться с выравниванием стека win x64
Везде написано, что по правилам fastcall стек должен быть выровнен на 16 байт при вызове ф-ий, перед вызовом ф-ии резервируем место для теневой копии регистров sub rsp, 32 и еще sub rsp, 8 для выравнивания.
тоесть sub rsp, 8*5 должен идти перед вызовом каждой ф-ии в x64
Проверяю все в отладчике, во первых сразу же встает вопрос, почему стек при запуске программы не выровнен на 16 ? В моем случае стек при запуске программы 8FF28 что в десятичной системе 589608 и соответственно /16 = 36850.5
что не кратно 16 ?
источник

RS

Rusty Shackleford in Ассемблер
это первый вопрос )
источник

RS

Rusty Shackleford in Ассемблер
тоесть по правилам fastcall в x64 винде перед вызовом процедуры нужно обязательно делать sub rsp, 8*5, я так понимаю, для резервирования и выравнивания
источник

s

s54816 in Ассемблер
Rusty Shackleford
Помогите пожалуйста разобраться с выравниванием стека win x64
Везде написано, что по правилам fastcall стек должен быть выровнен на 16 байт при вызове ф-ий, перед вызовом ф-ии резервируем место для теневой копии регистров sub rsp, 32 и еще sub rsp, 8 для выравнивания.
тоесть sub rsp, 8*5 должен идти перед вызовом каждой ф-ии в x64
Проверяю все в отладчике, во первых сразу же встает вопрос, почему стек при запуске программы не выровнен на 16 ? В моем случае стек при запуске программы 8FF28 что в десятичной системе 589608 и соответственно /16 = 36850.5
что не кратно 16 ?
Представь, что стек выровнен. Ты выполнил call, произошёл переход по адресу вызываемой функции. Как изменится стек?
источник

RS

Rusty Shackleford in Ассемблер
s54816
Представь, что стек выровнен. Ты выполнил call, произошёл переход по адресу вызываемой функции. Как изменится стек?
-8 байт на ret
источник

RS

Rusty Shackleford in Ассемблер
аа, ну тоесть все норм получается
источник

RS

Rusty Shackleford in Ассемблер
тоесть по этому у нас при старте нашей программы стек не кратен 16 ? потому что ret -8 уже был ?
источник

RS

Rusty Shackleford in Ассемблер
call положил на стек адрес возврата
источник

RS

Rusty Shackleford in Ассемблер
Это ясно вроде, дальше вопрос номер 2 )
источник

RS

Rusty Shackleford in Ассемблер
Перед вызовом СОБСТВЕННОЙ ф-ии делаю sub rsp, 40 как и написано во всех учебниках, стек после сохранения адреса возврата и создание фрейма(push rbp) получается 8FEF0 или 589552 что кратно 16, тут вроде бы все норм, идем дальше.
В своей ф-ии вызываю winapi перед эти сделав sub rsp, 40
Тоесть все по правилам fastcall x64, винапи падает с обращение к недоступной памяти, если же перед вызовом winapi резервирую стек  только для 4х параметров без выравнивания, тоесть делаю sub rsp, 8*4
отрабатывает все штатно. Почему так ? В самой winapi вижу в начале
  mov     [rsp+8], rbx
 mov     [rsp+10h], rbp
 mov     [rsp+18h], rsi
 push    rdi
 sub     rsp, 20h

сохранения регистров и sub rsp, 20h ? это что резервирование места для теневых регистров ? но ведь по правилам fastcall win 64 это должен делать вызывающий ? Отсюда в итоге и получается кривой стек
после
sub rsp, 5*8
call some_winapi
стек получается 8FE98h или 589464 ÷ 16 = 36841.5

как так, объясните пожалуйста где ошибка в моих рассуждениях?
источник

RS

Rusty Shackleford in Ассемблер
или это для локальных переменных место выделяется, но в любом случае для резервирования и выравнивания перед winapi sub rsp, 5*8 ведь надо делать ? 4 регистра и 8+8(адрес возврата после call)
источник

s

s54816 in Ассемблер
Лично я нихрена не понял.
источник

RS

Rusty Shackleford in Ассемблер
ыы)))
источник

RS

Rusty Shackleford in Ассемблер
s54816
Лично я нихрена не понял.
короче проще говоря в двух словах, есть моя процедура
источник

RS

Rusty Shackleford in Ассемблер
в ней вызываю винапи
источник

RS

Rusty Shackleford in Ассемблер
перед всеми вызовами делаю sub rsp, 8*5
источник

RS

Rusty Shackleford in Ассемблер
винапи так падает
источник

s

s54816 in Ассемблер
Rusty Shackleford
или это для локальных переменных место выделяется, но в любом случае для резервирования и выравнивания перед winapi sub rsp, 5*8 ведь надо делать ? 4 регистра и 8+8(адрес возврата после call)
Стек должен быть выровнен перед вызовом функции. Адрес возврата — не твоя забота. call его положит, вызываемая процедура сделает push rbp, будет опять ок.
источник

ST

Saenro T in Ассемблер
Если "методом тыка": засунь туда побольше пустышек, с запасом, потом пробегись отладчиком и глянь сколько лишнего осталось в стеке на выхлопе)
источник