• B правой части каждого сообщения есть стрелки и . Не стесняйтесь оценивать ответы. Чтобы автору вопроса закрыть свой тикет, надо выбрать лучший ответ. Просто нажмите значок в правой части сообщения.

Структура FASM программы для x64

Majestio

Member
16.09.2020
5
1
BIT
0
Всем привет!

В раздел по Ассемблеру писать не могу, поэтому вопрос здесь. Прошу разъяснить участок кода в простейшем 64-битном Hello World:

C-подобный:
format PE64 console
entry start

include "C:/Tools/Fasm/INCLUDE/win64ax.inc"

section '.data' data readable writeable

  Message         db 'Hello World!',0
  Message.length  = $ - Message
  HandleFile      dq ?

section '.text' code readable executable

start:
  ; 1 вариант
  ; sub rsp, 40
  ; and spl, -16
 
  ; 2 вариант
  ; sub    rsp,8*(4+3)

  invoke GetStdHandle, STD_OUTPUT_HANDLE
  mov [HandleFile],rax
  stdcall PrintFunc, HandleFile
  invoke ExitProcess,0

proc PrintFunc
  invoke WriteConsole, [HandleFile], Message, Message.length, 0, 0 
  ret
endp

section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL'
  include 'api\kernel32.inc'

Сразу после метки start в отдельных примерах используются наборы инструкций (вариант 1 и 2). Как я понял, это что-то связано со стеком и выравниванием. Но не могу найти понятной инфы в сети. Для чего, в каких случаях это нужно? И как правильно? И нужно ли это для PE (а может для ELF)? Если сделаете статью по особенностям программирования на fasm для x64 - вообще вам не будет цены.
 

Marylin

Mod.Assembler
Red Team
05.06.2019
326
1 451
BIT
696
Для чего, в каких случаях это нужно? И как правильно?
1. Как-правило, в самом начале 64-битного кода можно встретить инструкцию sub rsp,8. Так предписывает Microsoft выравнивать стек на 16-байтную границу. Только почему именно на 16, а не на 8 байт - нигде не упоминается. К примеру в х32 при запуске приложения стек уже выровнен на 4-байта, что приравнивается к размеру регистров. Но и в этом случае, такое выравнивание нужно только для программного кода, в котором имеются прямые вызовы функций по типу "FastCall". Если функции зовёшь макросом invoke, то инструкция sub rsp,8 уже прописана в нём, и повторять её не нужно.

2. В режиме х32 все аргументы и параметры при вызове системных функций передаются ей только через стек инструкциями push. А вот в х64 - первые 4 параметра передаются функции исключительно через регистры RCX,RDX,R8,R9, и если этой функции нужно передать ещё параметры, то остальные уже через стек инструкциями push. Для тех-что передаются в регистрах, программист должен сам резервировать место в стеме. В фасмовской папке Example есть демка "PE64DEMO":

C-подобный:
start:
      sub      rsp,8*5         ;// reserve stack for API use and make stack dqword aligned

      mov      r9d,0
      lea      r8,[_caption]
      lea      rdx,[_message]
      mov      rcx,0
      call     [MessageBoxA]

В данном случае sub rsp,8*5 подразумевает, что функции планируется передать 4-параметра в регистрах (как это требует режим х64), плюс один параметр на 16-байтное выравнивание стека в начале кода.


Если сделаете статью по особенностям программирования на fasm для x64 - вообще вам не будет цены.
По большому счёту, отличие только в этом, так-что если освоить х32, то проблем с переходом на х64 не будет.
 

Majestio

Member
16.09.2020
5
1
BIT
0
Благодарю! А как "расшифровать" тот "1-й вариант" из моего примера? И попутно второй вопрос - как задать свой размер стека, допустим 64к?
 

Marylin

Mod.Assembler
Red Team
05.06.2019
326
1 451
BIT
696
А как "расшифровать" тот "1-й вариант" из моего примера?
стек растёт наоборот, поэтому sub rsp,40 - это резерв 40 байт из стековой памяти для каких-либо нужд.

как задать свой размер стека, допустим 64к?
обычно задавать его не нужно, т.к. система уже выделила стек для запускаемого приложения, т.е. он уже у вас есть. На системах х32 стек на старте равен 256 Кб, а на х64 точно не знаю. Можно вычислить его размер по алго как в этой теме: Стек – общая философия
 

Marylin

Mod.Assembler
Red Team
05.06.2019
326
1 451
BIT
696
Регистр SPL появился только в х64 и означает младший байт 8-байтного регистра RSP.
Таким образом and spl,-16 сбрасывает мл. тетраду RSP, выравнивая указатель стека на 16-байт.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!