Вызов функции стандартной библиотеки 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
выходные параметры компоновщика:
/из:"C:UsersappleDocumentsSP_Lab7DebugSP_Lab7_Demo.исполняемый" / МАНИФЕСТ: НЕТ / NXCOMPAT / PDB:"C:UsersappleDocumentsSP_Lab7DebugSP_Lab7_Demo - ... распределительная плата" / DYNAMICBASE " kernel32.Либ" "библиотека user32.lib "" gdi32.lib "" winspool.движение за освобождение" "comdlg32.lib "" advapi32.Либ" "заshell32.Либ" "трассировки ole32.lib "" oleaut32.движение за освобождение" "идентификатор UUID.Либ" "библиотекой odbc32.lib "" odbccp32.lib " / машина: X86 / SAFESEH:нет / ИНКРЕМЕНТНЫЙ: НЕТ /ПГД:"C:UsersappleDocumentsSP_Lab7DebugSP_Lab7_Demo.ПГД" /Подсистемы:Windows /MANIFESTUAC:"уровень='значение asinvoker' для uiaccess= "ложь"" / ManifestFile: "DebugSP_Lab7_Demo.исполняемый.промежуточный.декларация" / ERRORREPORT:PROMPT /NOLOGO /TLBID: 1
Если я комментарий call print
, тогда все выполняется нормально (даже функция Windows API). Есть ли способ вызвать функцию C из файла asm без создания файла cpp, который включает <cstdio>
?
Можно ли это сделать?
3 ответов
Microsoft переработала большую часть C среда выполнения и библиотеки в VS 2015. Некоторые функции больше не экспортируются из C библиотеки (некоторые из них определены в C файл заголовка). Microsoft имеет некоторые библиотеки совместимости, такие как legacy_stdio_definitions.Либ!--7--> и legacy_stdio_wide_specifiers.Либ!--7-->, но вы также можете использовать более старый набор инструментов платформы Visual Studio 2013 с более старым C библиотеки.
чтобы изменить набор инструментов платформы: потяните вниз ; выберите Properties...
; перейти в раздел Configuration Properties
/General
, и изменить Platform Toolset
до Visual Studio 2013 (v120)
похоже, что можно использовать набор инструментов Visual Studio 2015 с несколькими изменениями.
- вам нужно будет добавить эти библиотеки в свои зависимости:libcmt.Либ!--13-->, libvcruntime.Либ!--13-->, libucrt.Либ!--13-->, legacy_stdio_definitions.Либ!--13-->. В качестве альтернативы вы можете использовать
includelib
для включения этих библиотек в файл сборки. - указать C о вызове для
main
процедуры с помощьюPROC C
- в конце файла (и это важно) не используйте
end main
используйтеend
только. Не исправление этого может привести к неожиданным сбоям. - хотя мы можем использовать ExitProcess чтобы выйти из нашего приложения, мы также можем поместить код возврата в EAX и
ret
вернуться. The C время выполнения вызывает наш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 вы хотите связать. Я бы предложил найти минимальное время выполнения, например,библиотека WCRT.
библиотека, вероятно, потребует инициализации и может потребовать, чтобы вы определили кучу буферов где-нибудь для ее ведения книги.
вместо того, чтобы идти на все эти проблемы, я бы предложил вам просто придерживаться Windows API, и в вашем случае используйте WriteConsole