FASM x64

Тема в разделе "WASM.X64", создана пользователем Orbit, 18 май 2017 в 12:13.

  1. Orbit

    Orbit Member

    Публикаций:
    0
    Регистрация:
    13 дек 2016
    Сообщения:
    62
    Адрес:
    г. Москва
    Здравствуйте.

    Сто лет не писал на fasm и забыл как входить в процедуру. Помогите пожалуйста.
    Я помню что если сразу входить в процедуру в начале программы то ненужно выравнивать стек "sub rsp,8"

    Спасибо, разобрался с Божей помощью

    Код (Text):
    1.  
    2. format PE64 GUI 5.0
    3. entry start
    4.  
    5. include 'win64a.inc'
    6.  
    7. section '.code' code readable executable
    8.  
    9.   proc start
    10.  
    11.   ret
    12.  
    13.   endp
    14.  
    15.   invoke  ExitProcess,rax
    16.  
    17. section '.idata' import data readable writeable
    18.  
    19.   library kernel,'KERNEL32.DLL'
    20.  
    21.   import kernel,\
    22.   ExitProcess,'ExitProcess'
    23.  
    24.  
     
    Последнее редактирование: 18 май 2017 в 12:22
  2. Atari

    Atari New Member

    Публикаций:
    0
    Регистрация:
    16 мар 2017
    Сообщения:
    25
    Вообще, ни хрена не понял, что Вам надо, но наверное это:
    Код (ASM):
    1.  
    2. include 'win64W.inc'
    3.  
    4. format PE64 GUI 5.0
    5. entry start
    6.  
    7. section '.text' code readable executable
    8.  
    9.   start:
    10.         sub     rsp,8           ; Выравнивание стека на dqword
    11.         call     start2
    12.         invoke  ExitProcess, 0
    13.  
    14. proc start2
    15.         ret
    16. endp
    17.  
    18. ;section '.data' data readable writeable
    19.  
    20. section '.idata' import data readable writeable
    21.  
    22.   library kernel32,'KERNEL32.DLL',\
    23.           user32,'USER32.DLL'
    24.  
    25.   include 'api\kernel32.inc'
    26.   include 'api\user32.inc'          
    27.  
     
  3. Orbit

    Orbit Member

    Публикаций:
    0
    Регистрация:
    13 дек 2016
    Сообщения:
    62
    Адрес:
    г. Москва
    У меня такой вопрос: почему программа ексемпл запускается в безопастном режиме в COMODO FIREWALL, я понимаю что программа редкая но всё же

    [​IMG]хостинг фото
     
    Последнее редактирование: 18 май 2017 в 14:02
  4. Atari

    Atari New Member

    Публикаций:
    0
    Регистрация:
    16 мар 2017
    Сообщения:
    25
    А что Вы ожидаете? Она просто выводит MessageBox только по тому, что entry указывает на proc start
     
  5. Orbit

    Orbit Member

    Публикаций:
    0
    Регистрация:
    13 дек 2016
    Сообщения:
    62
    Адрес:
    г. Москва
    Мне интересно почему фаерволл запускает ее в безопастном режиме, ну ладно...
    Вот еще вопрос почему антивирусы, каторый я и в глаза не видел, определяют ее как заразу :(

    [​IMG]фотохостинг бесплатно
     
  6. Orbit

    Orbit Member

    Публикаций:
    0
    Регистрация:
    13 дек 2016
    Сообщения:
    62
    Адрес:
    г. Москва
    Решил проблему с COMODO - удалил его
     
  7. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    0
    Регистрация:
    11 июн 2004
    Сообщения:
    2.591
    Адрес:
    Russia
    аминь )
     
  8. Atari

    Atari New Member

    Публикаций:
    0
    Регистрация:
    16 мар 2017
    Сообщения:
    25
    Мб, потому что в импорте нет "опасных" функций?

    Ложные срабатывания, это норма. Лечиться подписью сертификатом
     
  9. ol.

    ol. Member

    Публикаций:
    0
    Регистрация:
    21 фев 2017
    Сообщения:
    82
    Это не выравнивание, это просто "rsp-8".

    Выравнивание вот:
    Код (ASM):
    1.  
    2.     and rsp, -8
    3.  
    А вообще правильный вход в процедуру зависит от ОС, ее разрядности и соглашения, принятого в процедуре.
    Посмотрите исходник макроса "invoke".
     
  10. Atari

    Atari New Member

    Публикаций:
    0
    Регистрация:
    16 мар 2017
    Сообщения:
    25
    Категорически не согласен! Если сделать and rsp, -8 то программа упадёт на x64. Т.к применяя and вы убиваете указатель на стек в rsp.

    ТС приложил исходник в первом сообщение, смотрим его и путём не сложных умственных заключений приходим к выводу, что его интересует только ОС Windows, архитектура x64 =)
     
  11. Atari

    Atari New Member

    Публикаций:
    0
    Регистрация:
    16 мар 2017
    Сообщения:
    25
    Вообще, 8 надо отнять из RSP только потому что макросы Fasm (вроде как invoke) не резервируют достаточное количество байт перед вызовом функции. Win64 ABI требует, чтобы стековый кадр был выравнен на 16 байт. Таким образом если не сделать sub rsp,8, то стек не будет иметь 16 байтовую кратность с учётом адреса возврата вызываемой функции.
     
  12. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    3
    Регистрация:
    25 июн 2008
    Сообщения:
    2.310
    Atari,
    Код (ASM):
    1. ; Example of 64-bit PE program
    2. format PE64 GUI
    3. include 'win64ax.inc'
    4. .code
    5.   start:           ; Make stack dqword aligned
    6. frame
    7.         invoke MessageBoxA,0,_message,_caption,MB_OK
    8.         invoke    ExitProcess,0
    9. endf
    10. section '.data' data readable writeable
    11.   _caption db 'Win64 assembly program',0
    12.   _message db 'Hello World!',0
    13. .end start
    14.  
    макрос .code/.end value подставит в текст sub rsp,8
     
  13. ol.

    ol. Member

    Публикаций:
    0
    Регистрация:
    21 фев 2017
    Сообщения:
    82
    wat?

    А сделав sub - не убиваете, да? И кто вам мешает rsp сначала сохранить, а когда надо - восстановить?

    Invoke fasm для win64 отлично резервирует место, ибо это входит в Win64 calling convention.

    Тогда надо делать and rsp, -16; причем в самом начале вашей функции, ибо никто не гарантирует, что стек у вас будет при вызове выровнен. Иначе придется скурпулезно считать каждый push и pop, особенно с учетом любых переходов - чтобы не дай бог не сбиться с границы - что все равно рано или поздно произойдет.

    Я когда-то писал функцию универсального вызова внешних процедур для С, и выглядела она как то так:
    Код (C):
    1.  
    2. asm("call:",
    3.    "pushq %rbp",
    4.    "movq  %rsp, %rbp",
    5.  
    6.    "andl  $-16, %esp", // alignment
    7.  
    8.    "andq  $1, %rdx", // arguments count
    9.    "leaq  -16(%rsp,%rdx,8), %rsp",
    10.  
    11.    "pushq (%r10)", ..., "pushq (%r10)", // all arguments
    12.  
    13.    .......
    14.    "subq $32, %rsp", // extra space
    15.    "call *%rax",
    16.    "leave",
    17.    "ret",
    18.  
    Прошу заметить, что перед вызовом винда требует еще и 32 байтика в резерв.
     
  14. Atari

    Atari New Member

    Публикаций:
    0
    Регистрация:
    16 мар 2017
    Сообщения:
    25
    Пардон, мой косяк. Действительно and rsp, -8, делает выравнивание стека без потери адреса. Вы были таки правы, я поспешил с выводами, когда увидел опкод and, а дальнейшие мои мысли были построены на ложном умозаключение...

    Эм, шутки шутками, но... Опытным путём было выяснено, что перед вызовом функции стек должен быть выравнен на 8 байтовую границу, а после на 16-байтовую. Не надо выравнивать стек перед каждым вызовом функции, достаточно на точке входа сделать sub rsp, 8. Выравнивание на 8 байтовую границу останется, а после вызова call xxxx, будет размещён в стеке адрес возврата и выравнивание стека будет кратно 16, что нам и надо.

    Открываем PROC64.INC и видим:
    Код (ASM):
    1. macro invoke proc,[arg]
    2. { common fastcall [proc],arg }
    3.  
    4. macro fastcall proc,[arg]
    5. { common local stackspace,argscount,counter
    6.  
    7. ; Вот тут самое интересное
    8.     if argscount < 4
    9.      stackspace = 4*8
    10.     else if argscount and 1
    11.      stackspace = (argscount+1)*8
    12.     else
    13.      stackspace = argscount*8
    14.     end if    
    На сколько я понимаю, если аргументов функции меньше чем 4, то резервируем на стеке 32 байта, если хотя бы 4 и аргументов чётное количество, то резервируем КоличествоАргументов * 8, при не чётном количестве аргументов, считаем, как (КоличествоАргументов + 1) * 8.

    Т.е. всё замечательно, аргументы в стеке лежат с выравниванием кратным 16, пока инструкция call не положит в стек адрес возврата... Итого в самом простом случае, получается, что макрос fastcall (invoke) резервирует 32 байта + 8 байт на адрес возврата = 40 байт и чтобы их выровнять, нам надо добавить 8 (отнять от rsp 8).

    Я уже не знаю как проще объяснить =(
     
  15. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    3
    Регистрация:
    25 июн 2008
    Сообщения:
    2.310
    там еще чуднее, для функций с аргументами <= 4 макрос invoke будет обрамлять каждую функцию sub rsp,20h add rsp,20h то есть
    Код (Text):
    1.     sub rsp,20h
    2.         invoke MessageBoxA,0,_message,_caption,MB_OK
    3.        add rsp,20h
    4.        sub rsp,20h
    5.         invoke    ExitProcess,0
    6.        add rsp,20h
    если использовать frame/endf как у меня выше, тогда получим
    Код (Text):
    1.     sub rsp,20h
    2.         invoke MessageBoxA,0,_message,_caption,MB_OK
    3.         invoke    ExitProcess,0
    4.        add rsp,20h
    при обрамлении функций с разным числом параметров frame/endf вычислит функцию с наибольшим количеством параметров
    Код (Text):
    1.    sub rsp,MAX*8
    2. invoke f1
    3. invoke f2
    4. ....
    5. invoke fN
    6. add rsp,MAX*8
     
    Коцит нравится это.
  16. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    3
    Регистрация:
    25 июн 2008
    Сообщения:
    2.310
    Теоретически да, но, например, для MessageBox или RegisterClass резервирование не требуется, достаточно при входе в процедуру поставить push reg64 или enter 0,0 вместо sub rsp,8
    Глава вторая. Как Братец Кролик уменьшал размер программы
     
    Последнее редактирование: 23 май 2017 в 13:25
  17. ol.

    ol. Member

    Публикаций:
    0
    Регистрация:
    21 фев 2017
    Сообщения:
    82
    МС засрет 32 байта, как пить дать. Так что лучше, все же, сделать sub rsp, 40.
     
  18. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    3
    Регистрация:
    25 июн 2008
    Сообщения:
    2.310
    конечно разные, я пишу через invoke и макрос сам всё раскладывает по регистрам, а вы через call и mov и lea пишете самостоятельно.
    это так себе аргумент, а вот без sub rsp,32 MessageBox работает нормально...
     
  19. ol.

    ol. Member

    Публикаций:
    0
    Регистрация:
    21 фев 2017
    Сообщения:
    82
    Да, правда ваша - я невнимательно вас прочитал. Уже удалил.

    Ну я на эти грабли уже наступал. Ничего не имею против, чтобы и вы потоптались )