Возникла необходимость вызывать библиотечные функции linux (если конкретнее, то gtk+). Пишу 64-битную программу на fasm. Может кто-нить знает в какие регистры какие параметры помещать (первый параметр туда то, второй туда то ... а N-ый параметр и следующие в стек). Макросы fasm proc64.inc не работают (в смысле не в те регистры помещают значения), ибо расчитаны они не на Linux, а на Win64. Скачал примеры программирования X Windows в 64-битном режиме с сайта fasm. Первые 4 параметра удалось передавать правильно (вроде как. ну 3 точно правильно, а 4 не уверен). Всё же с таблицей будет удобнее...
у Фога есть неплохая статейка. http://www.agner.org/optimize/calling_conventions.pdf И еще: http://winprogger.com/?p=1436 А вообще самый простой вариант - это скопилить gcc с флагом -S.
Спасибо. У меня получился вот такой макрос: Код (Text): macro fastcall name,[arg] { common local ..arg_index,..arg_count ..arg_index = 0 ..arg_count = 0 if ~ arg eq forward ..arg_count = ..arg_count + 1 common sub rsp, ..arg_count * 8 forward if ..arg_index = 0 mov rdi, arg else if ..arg_index = 1 mov rsi, arg else if ..arg_index = 2 mov rdx, arg else if ..arg_index = 3 mov rcx, arg else if ..arg_index = 4 mov r8, arg else if ..arg_index = 5 mov r9, arg else mov rax, arg mov qword[rsp + (..arg_count - ..arg_index - 1) * 8], rax end if ..arg_index = ..arg_index + 1 common end if call name if ..arg_count add rsp, ..arg_count * 8 end if } Его, конечно, можно улучшить. Добавить addr (как в fasm'ком стандартном макросы для винды). Но заготовка получилась вот такая. Сейчас буду проверять нормально она работает или нет (для процедур с количеством параметров <= 4 работает точно хорошо).
Всё кроме этого кода нормально работает: Код (Text): proc StatusIconPopupMenuEvent c,widget,button,activate_time,data local menu:QWORD,menu_item:QWORD mov [widget], rdi mov [activate_time], rsi mov [button], rdx mov [data], rcx fastcall gtk_menu_new mov [menu], rax fastcall gtk_menu_item_new_with_label,quit_label mov [menu_item], rax fastcall g_signal_connect_data,[menu_item],activate_event,gtk_main_quit,0 fastcall gtk_menu_shell_append,[menu],[menu_item] fastcall gtk_widget_show_all,[menu] fastcall gtk_menu_popup,[menu],0,0,0,0,[button],[activate_time] ret endp Поясню, что это такое. Я создаю значок в области уведомлений. Затем назначаю ему обработчик сигнала "popup-menu". Вот собственно этот обработчик. Обработчик вызывается (пишу g_print хоть в начале, хоть в конце - он отображается на консоли). Все функции вроде как вызываются. Если я где-нибудь напишу обнуление menu (после присваивания ей значение, разумеется), то тут же на консоли вылазит предупреждение, что menu это не меню. Однако контекстное меню упорно отображаться не хочет. Макрос proc - стандартный макрос fasm из proc64.inc, а fastcall - мой собственный, который я приводил в сообщении выше.
Возникла та же необходимость и тоже пришлось много читать и долго разбираться, в итоге родился нижеприведенный макрос. Переделал пример "libcdemo", поставляемый вместе с фасмом и он заработал. Отправлю его на flatassembler.net, может профи доведут его до ума и выложат рядом с остальными примерами, а то прямо беда какая-то с этим делом Код (Text): ; Это упрощенная версия макроса ccall ; Упрощенная потому что например вызов: ; ccall myproc,rax,rcx,rdi ; будет преобразован в: ; mov rdi,rax ; mov rsi,rcx ; mov rdx,rdi ; т.е. возможны перехлесты регистров ; а так же не анализируется размер операндов ; предполагается что они все 64-разрядные ; rdi - 1ый аргумент ; rsi - 2ой аргумент ; rdx - 3ий аргумент ; rcx - 4ый аргумент ; r8 - 5ый аргумент ; r9 - 6ой аргумент ; остальные параметры передаются через стек как обычно ; даже если аргументов меньше 6, необходимо резервировать на стеке 64 байта ; регистр rax используется тоже для каких-то целей поэтому его нужно обнулить ;macro ccall proc,[arg] ; { common fastcall qword[proc],arg } macro ccall proc,[arg] { common local ..arg_index, ..arg_count, ..stk_count ; ..arg_index - для запихивания аргументов в стек и в регистры ; ..arg_count - для начального подсчета количества параметров ; ..stk_count - для подсчета зарезервированного в стеке места, чтобы потом освободить его ..arg_count = 0 ; вычисляем количество аргументов forward ..arg_count = ..arg_count + 1 ; вычисляем сколько резервировать места common ..arg_index = ..arg_count if ..arg_count > 6 ..stk_count = ..arg_count - 6 else ..stk_count = 0 end if ; резервируем место sub rsp, 64 + 8 * (..stk_count and 1) ; закладываем параметры reverse if ..arg_index > 6 push arg else if ..arg_index = 1 if ~ arg eq mov rdi,arg end if else if ..arg_index = 2 mov rsi,arg else if ..arg_index = 3 mov rdx,arg else if ..arg_index = 4 mov rcx,arg else if ..arg_index = 5 mov r8,arg else if ..arg_index = 6 mov r9,arg end if ..arg_index = ..arg_index - 1 ; вызываем процедуру common xor rax,rax call proc ; освобождаем зарезервированное место add rsp, 64 + (8 * ..stk_count) + (8 * (..stk_count and 1)) }