Вызов функции стандартной библиотеки C из asm в Visual Studio
У меня возникла проблема с вызовом функции C из проекта asm, созданного в visual studio (Win10 x64, Visual Studio 2015). Проект состоит из одного файла asm:
.586 .model flat, stdcall option casemap:none includelib msvcrt.lib ExitProcess PROTO return:DWORD extern printf:near .data text BYTE "Text", 0 .code main PROC push offset text call printf add esp,4 invoke ExitProcess,0 main ENDP end main
Когда я создаю проект, компоновщик выводит ошибку:
Ошибка LNK2019 неразрешенный внешний символ _printf, на который ссылается функция _main @ 0
- Сделать муравей тихий без флага -q?
- Как загрузить сборку в AppDomain со всеми ссылками рекурсивно?
- Не удалось загрузить файл или сборку HRESULT: 0x80131515 (При добавлении controllerа в проект MVC с ссылками на сборку на сетевом диске)
- Что регистрирует сохранение в соглашении вызова ARM C?
- Как сохранить сборки ASP.NET в AppDomain в живых?
Выходные параметры компоновщика:
/OUT:”C:\Users\apple\Documents\SP_Lab7\Debug\SP_Lab7_Demo.exe “/ MANIFEST: NO / NXCOMPAT /PDB:”C:\Users\apple\Documents\SP_Lab7\Debug\SP_Lab7_Demo.pdb” / DYNAMICBASE “kernel32.lib” “user32.lib” “gdi32.lib” “winspool.lib” “comdlg32.lib” “advapi32.lib” “shell32.lib” “ole32.lib” “oleaut32.lib” “uuid.lib” “odbc32.lib” “odbccp32.lib” / MACHINE: X86 / SAFESEH: NO / INCREMENTAL: NO /PGD:”C:\Users\apple\Documents\SP_Lab7\Debug\SP_Lab7_Demo.pgd “/ SUBSYSTEM: WINDOWS / MANIFESTUAC: “level = ‘asInvoker’ uiAccess = ‘false'” /ManifestFile:”Debug\SP_Lab7_Demo.exe.intermediate.manifest “/ ERRORREPORT: PROMPT / NOLOGO / TLBID: 1
Если я комментирую call print
, то все выполняется нормально (даже функция Windows API). Есть ли способ вызвать функцию C из asm-файла без создания файла cpp, который включает ? Можно ли это сделать?
- Ошибка в построении gradleа после обновления Android Studio с log4j
- Как ссылаться на сборки .NET с помощью PowerShell
- Как определить, была ли assembly .NET построена для x86 или x64?
- Как объединить несколько сборок в один?
- .Net: Запуск кода при загрузке сборки
- Как я могу перечислить все загруженные сборки?
- Maven: добавьте зависимость к банке относительным путем
- Как получить вывод ассемблера из источника C / C ++ в gcc?
Microsoft реорганизовала большую часть C- среды исполнения и библиотек в VS 2015. Некоторые функции больше не экспортируются из библиотеки C (некоторые из них определены в файле заголовка C ). У Microsoft есть некоторые библиотеки совместимости, такие как legacy_stdio_definitions.lib и legacy_stdio_wide_specifiers.lib , но вы также можете использовать старый набор инструментов платформы Visual Studio 2013 со старыми библиотеками C.
Чтобы изменить набор инструментов платформы: вытащите меню « Project
; выберите Properties...
; перейдите в « Configuration Properties
/ General
и смените « Platform Toolset
на Visual Studio 2013 (v120)
Похоже, что можно использовать набор инструментов Visual Studio 2015 с несколькими изменениями.
- Вам нужно будет добавить эти библиотеки в свои зависимости: libcmt.lib , libvcruntime.lib , libucrt.lib , legacy_stdio_definitions.lib . В качестве альтернативы вы можете использовать
includelib
для включения этих библиотек в файл сборки. - Укажите соглашение о вызове C для
main
процедуры с помощьюPROC C
- В конце вашего файла (и это важно) не используйте
end main
, используйте толькоend
. Не устранение этого может привести к непредвиденным сбоям. - Хотя мы можем использовать ExitProcess для выхода из нашего приложения, мы также можем поместить код возврата в EAX и выполнить возврат
ret
. C runtime вызывает нашуmain
функцию, и мы будем вызывать код останова для нас по возвращении.
Код может выглядеть так:
.586 .model flat, stdcall option casemap:none includelib libcmt.lib includelib libvcruntime.lib includelib libucrt.lib includelib legacy_stdio_definitions.lib ExitProcess PROTO return:DWORD extern printf:NEAR .data text BYTE "Text", 0 .code main PROC C ; Specify "C" calling convention push offset text call printf add esp, 4 ; invoke ExitProcess,0 ; Since the C library called main (this function) ; we can set eax to 0 and use ret`to have ; the C runtime close down and return our error ; code instead of invoking ExitProcess mov eax, 0 ret main ENDP end ; Use `end` on a line by itself ; We don't want to use `end main` as that would ; make this function our program entry point ; effectively skipping by the C runtime initialization
Вы можете вызывать функции C, но тогда вам нужно будет установить связь с библиотекой C. Точно, как это будет сделано, будет зависеть от того, с какой библиотекой C вы хотите установить связь. Я бы предложил найти минимальное время выполнения C, например библиотеку WCRT .
Библиотека, вероятно, потребует инициализации, и может потребовать, чтобы вы определили кучу буферов где-то для ее хранения.
Вместо того, чтобы идти на все эти проблемы, я предлагаю вам просто придерживаться Windows API, и в вашем случае используйте функцию WriteConsole .