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