Это отчасти правильно. Фактические требования здесь более сложны и частично противоречивы. Для целей x86 соглашение о вызовах, используемое фактическим кодом точки входа, не имеет значения для исполняемых файлов, но должно использовать соглашение о вызовах stdcall для DLL. Однако для целей x86 имя, переданное с параметром /ENTRY
, автоматически оформляется так, как если бы оно было функцией в соответствии с соглашением о вызовах cdecl, независимо от того, создается ли исполняемый файл или DLL.
На x64 и ARM На самом деле не существует соглашения о вызовах stdcall, поэтому нет особых требований и несоответствий. Код точки входа должен соответствовать стандартному соглашению cdecl для этих целей, а имя, переданное с параметром /ENTRY
, не оформлено.
Требования кода сборки точки входа
В случае В исполняемом файле точка входа вызывается без аргументов, поэтому соглашение о вызовах cdecl и stdcall эквивалентно, и поэтому любой из них может использоваться для кода точки входа. В случае DLL точка входа вызывается с тремя аргументами, те же аргументы передаются DllMain , и эти аргументы передаются с использованием соглашения о вызовах stdcall. На целях x86 код точки входа DLL должен выдавать эти аргументы при помощи инструкции ret 12
при возврате.
Как / ENTRY обрабатывает свой аргумент
Для целей x86 (а не для целей x64 и ARM) ) опция компоновщика /ENTRY
автоматически ставит перед символом переданный символ подчеркивания _
, следуя соглашению cdecl для имен символов. Он не добавляет суффикс stdcall @##
, даже если вы создаете DLL. Затем он будет нечётко сопоставлять этот символ с символами в связанном коде. Если вы используете /ENTRY:foo
, то сначала он попытается найти символ с именем _foo
, а если он его не найдет, он будет искать символ с именем foo
или символ, начинающийся с _foo@
или foo@
.
Комментарии к коду вашего примера
Обратите внимание, потому что вы используете .MODEL flat, C
в вашем примере кода MASM автоматически префиксом символа main
, определенного в вашем коде, с подчеркивание _
в соответствии с соглашением о вызовах x86 cdecl. Удобно, что это соответствует поведению /ENTRY
, как описано выше. Тем не менее, это не лучшая идея назвать вашу точку входа main
, поскольку это будет означать, что это должна быть функция C с тем же именем. Поскольку ваша точка входа не получает переданные аргументы, но функция C main
может ввести в заблуждение вызов вашей точки входа main
. Вместо этого я бы предложил назвать его start
.
Наконец, директива .STACK ничего не делает при сборке 32-битных или 64-битных программ PECOFF. Это полезно только при создании 16-битных программ.