Fasm выдаёт ошибку: flat assembler version 1.67.14 (1014684 kilobytes memory) code.asm [85]: invoke FF, [dta], [dtb], [dtc], [dtd], dword [edi+00*4] , 07, 0d76aa478h D:\coding\fasm v1.67.14\INCLUDE\win32ax.inc [42] invoke [1]: \common call [proc] \} error: operand size not specified. Ф-ция объявлена так: proc FF dta,dtb,dtc,dtd,x,s:byte,t Что я только туда не вставлял! Смиренно прошу о помощи
Почитал доки фасма, там так написано: "The invoke macro does the same, however it calls the procedure indirectly, through the pointer labelled by the first argument." invoke MessageBox,0,szText,szCaption,MB_OK stdcall [MessageBox],0,szText,szCaption,MB_OK Вот и вся разница, как я понимаю. И как это относится к моей ошибке?
потому что получается invoke FF, [dta]..... меняется на stdcall [FF], [dta]....... Вот и подумайте как это относится.
Заставил работать через Stdcall так: stdcall dword FF, ... Всё же было бы интересно узнать, как вызвать через invoke? Насколько я понимаю invoke работает со списком указателей, обычно через import, если с импортом работать. А как свой объявить? Или хотя бы в какой доке искать подскажите, те что с фасмом идут я прочитал.
zukalo invoke - для вызова функций stdcall - для вызова процедур invoke a = call [a] stdcall a = call a Вот и вся разница.
dead_body Фу, какое ужасное объяснение. Во-первых, AFAIK разница между функциями и процедурами состоит в том, что первые возвращают значение, а вторые нет. Во-вторых, эта разница есть только в языках высокого уровня. В асме (и, например, си) это одно и то же. В-третьих, это здесь вообще не причём. stdcall - вызов по адресу функции, invoke - вызов по указателю на адрес функции. zukalo А зачем? У вас есть прямой указатель на функцию. Зачем извращаться и класть этот указатель куда-то в память, чтобы по адресу этой памяти вызывать функцию? (собственно в этом вопросе и содержится ответ на Ваш вопрос) Для таблицы импорта ясно, зачем так сделано: на стадии компиляции адреса импортируемых функций не известны. Но взамен известны адреса, куда адреса этих функций будут положены загрузчиком. Поэтому и используется invoke. Для своих функций с конвенцией вызова stdcall используйте stdcall, пока нет необходимости в хранении указателей на фукнции в памяти.
Всем спасибо за отзывы. Насчёт импорта то я понимаю, но дело в том, что через invoke у меня не получается вызвать мою процедуру! invoke FF никак не работает! Так почему же не работает, если разницы в данном случае никакой?
зачем вообще эти инвоке и стдкалл? Почему не писать все через калл? Прога станет интереснее и вопросов таких не будет.
zukalo Вы издеваетесь. У меня два варианта. Вариант первый: повторить уже написанное. Вариант второй: рекомендовать Вам перечитывать посты с первого по седьмой включительно до полного просветления. А что ж Вас не смущает, что Вы Вашу процедуру через add вызвать не можете? 1) Чем быстрее? На один символ короче что ли? 2) Что значит "удобнее"? Положение клавиш на клавиатуре благоприятнее? 3) Кем "принято"?
zukalo Если уж вам очень хочется вызывать вашу процедуру через INVOKE, то сделайте следующее. 1) Объявите DWORD, в который положите адрес вашей FF: Код (Text): ... pFF dd 0 ... mov [pFF], FF 2) Вызываем FF, через pFF: Код (Text): invoke pFF, <параметры> По этим пунктам должно быть понятно, почему ваша FF не вызывается напрямую через INVOKE. Для компилятора ваша FF это просто число-константа. А INVOKE берет первым параметром адрес ячейки памяти, где располагается нужная для вызова функция. С другой стороны STDCALL не берет адрес функции из указанной ячейки, а интерпретирует переданный параметр как адрес самой функции.
dword можно жобавить и в самом макросе, например, вместо кода Код (Text): reverse push param можно написать код Код (Text): reverse push dword param
это чтобы фасм выставлял размер любой переменной в dword, т.к. use32 / x dw 0 / push [x] - будет пихать в стек word
Для этого есть push, pushd и pushw. Push не изменяет размер операнда, а pushd и pushw изменяют. Все это написано в справке:
GoldFinch Что это не баг, а документированная фича понятно, но смешивать без крайней необходимости 16 и 32 битный код не есть хороший стиль программирования, а уж особенно применительно к стеку, сильно чуствительному к выравниванию (попробуй, например, перед мессажебоксом временно сохранить ax через pushw, чтобы затем восстановить его . Поэтому по умолчанию правильно всё таки push/pop делать в соответствии с use16/32, а не в соответствии с размером операнда, а если ооочень нужно word в стеке при use32, то для этого уже pushw использовать.