#windows #visual-studio #assembly #masm
Вопрос:
Имея такую простую assembly
Win 32
программу:
.386
.model flat, stdcall
option casemap :none
EXTERN printf :PROC ; declare printf
.data
HelloWorld db "Hello Wolrd!:-)", 0
.code
start:
sub esp, 4
push offset HelloWorld
call printf
add esp, 4
ret
end start
Я могу успешно скомпилировать его, просто:
ml.exe /c HelloWorld.asm
НО у меня есть проблема с его связыванием. Когда я использую:
link HelloWorld.obj libcmt.lib
Я получаю сообщение об ошибке:
unresolved external symbol _main called in _mainCRTStartup
Что я должен изменить/исправить, чтобы успешно связать программу для ее запуска?
P.S.
Пожалуйста, не говорите мне, чтобы я использовал только nasm
. Я хотел бы использовать ml
amp; link
из моего MSVC.
Комментарии:
1. Разве это не должно быть
ml.exe /c /coff HelloWorld.asm
,link /SUBSYSTEM:CONSOLE HelloWorld.obj libcmt.lib
?2. @Michael Я попробовал Ваше предложение, но все еще с той же ошибкой компоновщика.:-(..
3. Никто не скажет вам использовать NASM; он не смог собрать этот файл, в котором используется синтаксис / директивы MASM. И NASM-это просто ассемблер, в любом случае он не поставляется с компоновщиком.
Ответ №1:
С некоторыми незначительными изменениями это теперь строится правильно.
.386
.model flat, c
option casemap :none
includelib libcmt.lib
includelib legacy_stdio_definitions.lib
EXTERN printf :PROC ; declare printf
.data
HelloWorld db "Hello World!:-)", 0
.code
main PROC
push offset HelloWorld
call printf
add esp, 4
ret
main ENDP
END
Основными изменениями являются
- .model flat, c устанавливает соглашения о вызовах для процедур на C.
Если вы решите сохранить .model flat, для этого потребуется внести эти изменения.
Заменять
EXTERN printf :PROC
main PROC
с
printf PROTO NEAR C,:DWORD
main PROC NEAR C
- Включены libcmt.lib и legacy_stdio_definitions.lib, которые статически связывают запуск собственной среды выполнения C с вашим кодом.
- Изменена точка входа с начальной на основную. В библиотеке C-Runtime (CRT) libcmt.lib есть точка входа (_mainCRTStartup), которая выполняет некоторые задачи инициализации, а затем передает управление точке входа для основного приложения. Вы можете изменить точку входа по умолчанию, но обычно вам нужно удобство инициализации, которую точка входа CRT выполняет для вас автоматически.
- Удален первый дополнительный esp,4,поэтому оставшийся один толчок уравновешивается дополнительным esp, 4, поэтому ESP указывает на обратный адрес при запуске ret.
Для сборки откройте командную строку Windows и запустите:
"C:Program Files (x86)Microsoft Visual Studio2019ProfessionalVCAuxiliaryBuildvcvars32.bat"
чтобы установить среду MSVC, инициализированную для: ‘x86’
Затем выполните следующие команды MASM
ml.exe /c /coff HelloWorld.asm
link.exe /SUBSYSTEM:console HelloWorld.obj
Программа отображает
Привет, Мир!:-)
Комментарии:
1. Вы должны упомянуть то, что вы изменили , например
main
, вместоstart
, и удалить первоеsub esp,4
, чтобы оставшийся один толчок был сбалансированadd esp,4
, поэтому ESP указывает на обратный адрес приret
запуске.2. @vengy Thx друг, это наконец-то работает!: -) НО я получаю предупреждение компоновщика об этом . Раздел CRT был объединен с разделом .data с различными атрибутами… Что это значит и как это исправить?
3. Быстрое решение состоит в том, чтобы добавить параметр компоновщика /MERGE в x86 для объединения . Раздел CRT (только для чтения) с разделами .rdata (только для чтения): link.exe /ПОДСИСТЕМА:консоль /ОБЪЕДИНЕНИЕ:.CRT=.rdata HelloWorld.obj
Ответ №2:
В вашем сообщении об ошибке говорится, что он не может найти экспортированный символ (т. е. функцию) «_main». Я ожидаю, что переименование вашей функции запуска в _main приведет к ее компиляции.
Комментарии:
1. Я переименовался
start
в_main
и тоже пытался,_mainCRTStartup
но все равно безуспешно…2. @darek_911: может быть , попробуйте позвонить в него
main
; Я думаю, я читал, что MASM может дополнительно украсить имена для вас ведущим_
, в зависимости от некоторых директив или опций. Но да, конечноstart
(и отсутствие символа _main) — это проблема, вероятно , проблема.