fastcall в длинном режиме.

Тема в разделе "WASM.UNIX", создана пользователем KIV, 7 июл 2010.

  1. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Возникла необходимость вызывать библиотечные функции linux (если конкретнее, то gtk+). Пишу 64-битную программу на fasm. Может кто-нить знает в какие регистры какие параметры помещать (первый параметр туда то, второй туда то ... а N-ый параметр и следующие в стек). Макросы fasm proc64.inc не работают (в смысле не в те регистры помещают значения), ибо расчитаны они не на Linux, а на Win64. Скачал примеры программирования X Windows в 64-битном режиме с сайта fasm. Первые 4 параметра удалось передавать правильно (вроде как. ну 3 точно правильно, а 4 не уверен). Всё же с таблицей будет удобнее...
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    у Фога есть неплохая статейка.
    http://www.agner.org/optimize/calling_conventions.pdf
    И еще:
    http://winprogger.com/?p=1436

    А вообще самый простой вариант - это скопилить gcc с флагом -S.
     
  3. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    В терминале Linux набрал gcc --help. Вот, строка про -S:
    Как это поможет разобраться с fastcall?
     
  4. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    генерится асм листинг, например gcc -S -o some_file.S some_file.c
     
  5. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Спасибо. У меня получился вот такой макрос:
    Код (Text):
    1. macro fastcall name,[arg] {
    2. common
    3.         local ..arg_index,..arg_count
    4.         ..arg_index = 0
    5.         ..arg_count = 0
    6.         if ~ arg eq
    7. forward
    8.         ..arg_count = ..arg_count + 1
    9. common
    10.         sub rsp, ..arg_count * 8
    11. forward
    12.         if ..arg_index = 0
    13.                 mov rdi, arg
    14.         else if ..arg_index = 1
    15.                 mov rsi, arg
    16.         else if ..arg_index = 2
    17.                 mov rdx, arg
    18.         else if ..arg_index = 3
    19.                 mov rcx, arg
    20.         else if ..arg_index = 4
    21.                 mov r8, arg
    22.         else if ..arg_index = 5
    23.                 mov r9, arg
    24.         else
    25.                 mov rax, arg
    26.                 mov qword[rsp + (..arg_count - ..arg_index - 1) * 8], rax
    27.         end if
    28.         ..arg_index = ..arg_index + 1
    29. common
    30.         end if
    31.         call name
    32.         if ..arg_count
    33.                 add rsp, ..arg_count * 8
    34.         end if
    35. }
    Его, конечно, можно улучшить. Добавить addr (как в fasm'ком стандартном макросы для винды). Но заготовка получилась вот такая. Сейчас буду проверять нормально она работает или нет (для процедур с количеством параметров <= 4 работает точно хорошо).
     
  6. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Всё кроме этого кода нормально работает:
    Код (Text):
    1. proc StatusIconPopupMenuEvent c,widget,button,activate_time,data
    2. local menu:QWORD,menu_item:QWORD
    3.         mov [widget], rdi
    4.         mov [activate_time], rsi
    5.         mov [button], rdx
    6.         mov [data], rcx
    7.         fastcall gtk_menu_new
    8.         mov [menu], rax
    9.         fastcall gtk_menu_item_new_with_label,quit_label
    10.         mov [menu_item],  rax
    11.         fastcall g_signal_connect_data,[menu_item],activate_event,gtk_main_quit,0
    12.         fastcall gtk_menu_shell_append,[menu],[menu_item]
    13.         fastcall gtk_widget_show_all,[menu]
    14.         fastcall gtk_menu_popup,[menu],0,0,0,0,[button],[activate_time]
    15.         ret
    16. endp
    Поясню, что это такое. Я создаю значок в области уведомлений. Затем назначаю ему обработчик сигнала "popup-menu". Вот собственно этот обработчик. Обработчик вызывается (пишу g_print хоть в начале, хоть в конце - он отображается на консоли). Все функции вроде как вызываются. Если я где-нибудь напишу обнуление menu (после присваивания ей значение, разумеется), то тут же на консоли вылазит предупреждение, что menu это не меню. Однако контекстное меню упорно отображаться не хочет. Макрос proc - стандартный макрос fasm из proc64.inc, а fastcall - мой собственный, который я приводил в сообщении выше.
     
  7. serega386

    serega386 New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2011
    Сообщения:
    1
    Возникла та же необходимость и тоже пришлось много читать и долго разбираться, в итоге родился нижеприведенный макрос.

    Переделал пример "libcdemo", поставляемый вместе с фасмом и он заработал. Отправлю его на flatassembler.net, может профи доведут его до ума и выложат рядом с остальными примерами, а то прямо беда какая-то с этим делом

    Код (Text):
    1. ; Это упрощенная версия макроса ccall
    2. ; Упрощенная потому что например вызов:
    3. ;       ccall myproc,rax,rcx,rdi
    4. ; будет преобразован в:
    5. ;       mov rdi,rax
    6. ;       mov rsi,rcx
    7. ;       mov rdx,rdi
    8. ; т.е. возможны перехлесты регистров
    9. ; а так же не анализируется размер операндов
    10. ; предполагается что они все 64-разрядные
    11.  
    12. ; rdi - 1ый аргумент
    13. ; rsi - 2ой аргумент
    14. ; rdx - 3ий аргумент
    15. ; rcx - 4ый аргумент
    16. ; r8  - 5ый аргумент
    17. ; r9  - 6ой аргумент
    18. ; остальные параметры передаются через стек как обычно
    19. ; даже если аргументов меньше 6, необходимо резервировать на стеке 64 байта
    20. ; регистр rax используется тоже для каких-то целей поэтому его нужно обнулить
    21.  
    22. ;macro ccall proc,[arg]
    23. ; { common fastcall qword[proc],arg }
    24.  
    25. macro ccall proc,[arg] {
    26.   common
    27.     local ..arg_index, ..arg_count, ..stk_count
    28.     ; ..arg_index - для запихивания аргументов в стек и в регистры
    29.     ; ..arg_count - для начального подсчета количества параметров
    30.     ; ..stk_count - для подсчета зарезервированного в стеке места, чтобы потом освободить его
    31.     ..arg_count = 0
    32.  
    33.  ; вычисляем количество аргументов
    34.  
    35.   forward
    36.     ..arg_count = ..arg_count + 1
    37.  
    38.  ; вычисляем сколько резервировать места
    39.  
    40.   common
    41.     ..arg_index = ..arg_count
    42.  
    43.     if ..arg_count > 6
    44.       ..stk_count = ..arg_count - 6
    45.     else
    46.       ..stk_count = 0
    47.     end if
    48.  
    49.  ; резервируем место
    50.  
    51.     sub rsp, 64 + 8 * (..stk_count and 1)
    52.  
    53.  ; закладываем параметры
    54.  
    55.   reverse
    56.  
    57.     if ..arg_index > 6
    58.       push arg
    59.     else if ..arg_index = 1
    60.         if ~ arg eq
    61.           mov rdi,arg
    62.         end if
    63.     else if ..arg_index = 2
    64.         mov rsi,arg
    65.     else if ..arg_index = 3
    66.         mov rdx,arg
    67.     else if ..arg_index = 4
    68.         mov rcx,arg
    69.     else if ..arg_index = 5
    70.         mov r8,arg
    71.     else if ..arg_index = 6
    72.         mov r9,arg
    73.     end if
    74.  
    75.     ..arg_index = ..arg_index - 1
    76.  
    77.  ; вызываем процедуру
    78.  
    79.    common
    80.     xor rax,rax
    81.     call proc
    82.  
    83.  ; освобождаем зарезервированное место
    84.  
    85.     add rsp, 64 + (8 * ..stk_count) + (8 * (..stk_count and 1))
    86.  }