Вызов функции стандартной библиотеки 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

Выходные параметры компоновщика:

/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, который включает ? Можно ли это сделать?

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 .

  • Поиск всех пространств имен в сборке с использованием Reflection (DotNET)
  • C # компиляция для 32/64 бит или для любого процессора?
  • Как загрузить сборку .NET для операций отражения и впоследствии выгрузить ее?
  • Размер сборки .NET влияет на производительность?
  • Безопасно ли читать конец конца буфера на одной странице на x86 и x64?
  • _addcarry_u64 и _addcarryx_u64 с MSVC и ICC
  • Как сделать kernel ​​для моего загрузчика?
  • Ошибки CocoaPods при сборке проекта
  • Как я могу просмотреть MSIL / CIL, сгенерированный компилятором C #? Почему это называется сборкой?
  • использование ILMerge с библиотеками .NET 4
  • Медленная инструкция jmp
  • Давайте будем гением компьютера.