Скомпилировать вывод сборки, сгенерированный VC++?
У меня есть простая программа hello world C и я скомпилирую ее с /FA. Как следствие, компилятор также генерирует соответствующий листинг сборки. Теперь я хочу использовать masm/link для сборки исполняемого файла из сгенерированного списка.asm.
Следующая командная строка выдает 3 ошибки компоновщика:
\masm32\bin\ml /I"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include" /c /coff asm_test.asm
\masm32\bin\link /SUBSYSTEM:CONSOLE /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\lib" asm_test.obj
показывая, что функции времени выполнения C не были связаны с объектными файлами, созданными ранее:
asm_test.obj: ошибка LNK2001: неразрешенный внешний символ @__security_check_cookie@4 asm_test.obj: ошибка LNK2001: неразрешенный внешний символ _printf LINK: ошибка LNK2001: неразрешенный внешний символ _wmainCRTStartup asm_test.exe: фатальная ошибка LNK1120: 3 не разрешено
Вот сгенерированный листинг сборки
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01
TITLE c:\asm_test\asm_test\asm_test.cpp
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB OLDNAMES
PUBLIC ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@ ; `string'
EXTRN @__security_check_cookie@4:PROC
EXTRN _printf:PROC
; COMDAT ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@
CONST SEGMENT
??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@ DB 'hello world!', 0aH, 00H ; `string'
CONST ENDS
PUBLIC _wmain
; Function compile flags: /Ogtpy
; COMDAT _wmain
_TEXT SEGMENT
_argc$ = 8 ; size = 4
_argv$ = 12 ; size = 4
_wmain PROC ; COMDAT
; File c:\users\octon\desktop\asm_test\asm_test\asm_test.cpp
; Line 21
push OFFSET ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@
call _printf
add esp, 4
; Line 22
xor eax, eax
; Line 23
ret 0
_wmain ENDP
_TEXT ENDS
END
Я использую последнюю версию masm32 (6.14.8444).
Обновление:
Как предложил Cogwheel, я включил INCLUDELIB msvcrt.lib
в источнике asm. Программа компилируется и создается исполняемый файл, но компоновщик генерирует предупреждение:
msvcrt.lib (crtmanifestrtm.obj): предупреждение LNK4044: нераспознанная опция "manifestdependency:type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3ebebeb1ba игнорируются
Когда я запускаю исполняемый файл, среда выполнения C генерирует следующую ошибку:
Ошибка времени выполнения: R6034 Приложение попыталось загрузить библиотеку времени выполнения C неправильно
3 ответа
Я сделал это недавно. Оказывается, вы все еще можете делать это в 32-битном режиме в MSVC2012, но я думаю, что 64-битный режим безнадежен.
Для 32-битного режима вот что вы делаете.
Создайте пустой проект и исходный файл Source.cpp
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
- Щелкните правой кнопкой мыши на вашем проекте и выберите "Build Customization" и
выберите masm, как описано здесь http://www.masm32.com/board/index.php?topic=9231.0 - Под C++/OutputFiles выберите Сборка Выход / FA
- Comipile в 32-битном режиме Release mode
- Загрузите файл Source.asm в MSVC, чтобы вы могли просмотреть его. Это пока не сработает. Несколько изменений необходимы.
- В C++ / Оптимизация отключить Оптимизацию всей программы (удаляет
/GL
). Это добавляет строкуINCLUDELIB MSVCRT
- В Linker/Advanced установите для последней опции "Image Has Safe Exception Обработчики" значение No (
/SAFESEH:NO
) - Теперь у вас должен быть файл Source.asm, который будет делать то же самое, что и файл Source.cpp. Скопируйте Source.cpp из каталога Release в тот же каталог, что и Source.cpp (чтобы он не удалялся при сборке / очистке).
- Добавьте Source.asm (как существующий файл) к исходным файлам и удалите Source.cpp из сборки.
- Перестройте, и вы должны увидеть "Hello World" без необходимости менять какие-либо сборочные линии вручную.
Я использовал это для более сложных функций. Я обычно делаю это на отдельном модуле и использую extern "C"
на имя функции, чтобы удалить искажение имени C++.
Вот лучшая ссылка для сборки с CRT 9
Удалите перечисление.inc Удалите ссылку на security_check_cookie, добавьте INCLUDELIB MSVCRT ... и Роберт!
Также вы можете добавить: EXTERN _getchar:PROC и непосредственно перед ret: call _getchar Это будет ждать нажатия клавиши до закрытия программы.
Honkjonk.