给定:带有入口点prog的PROCE.c
我通常是这样
cl.exe /MD /LD /Fe"prog.dll" /Fo"prog" "prog.c" /link ext.lib或
cl.exe /MD /Fo"prog.obj"
cl.exe /MD /LD /Fe"prog.dll" "prog.obj" /link ext.lib在这两种情况下,生成的prog.dll都可以正常工作。
现在,我执行了以下操作以获得一个asm文件,而不是obj文件:
cl.exe /c /MD /Fa"prog"到目前为止,这种“效果”也很好。但是我不知道如何创建这个文件的dll。
试过:
ml.exe /c /Cx /coff prog.asm
cl.exe /MD /LD /Fe"prog.dll" "prog.obj" /link ext.lib结果: prog.dll没有入口点prog
再试:
ml.exe /c /Cx /coff prog.asm
cl.exe /MD /LD /Fe"prog.dll" "prog.obj" /link /entry:prog ext.lib结果:编译器警告错误的入口点_prog不使用12字节参数进行std调用,以及编译器关于未解析符号_memcpy的错误。
问题:有什么方法可以将cl.exe生成的cl.exe文件编译成动态链接库(最好是通过cl.exe,如果ml.exe不可能)?
发布于 2016-12-07 12:59:22
有没有办法将cl.exe生成的
/Fa文件编译成动态链接库(最好是通过cl.exe,如果ml.exe不可能的话)?
否:
我非常不清楚你为什么一开始就想这么做。如果您的源代码是C或C++,并且可以由MSVC编译和链接,那么引入转换汇编语言的附加中间步骤又有什么意义呢?只需直接使用cl.exe创建DLL即可。
如果您绝对必须这样做,您将不得不接受MSVC生成的ASM列表文件,并在通过MASM运行它之前手动清理它。您可以通过关闭整个程序优化、关闭异常处理、关闭安全检查/cookie以及向链接器指示映像不包含安全的SEH处理程序,从而简化清理任务。请注意,其中一些可能会破坏或更改代码的行为!您还需要为从运行库调用的函数添加EXTERN定义。
发布于 2016-12-08 08:47:45
虽然由Microsoft编译器生成的ASM源代码可能不是MASM的最佳输入,但这并不意味着它无法工作,至少在某些情况下(可能不是复杂的)。如果您查看由C编译器生成的ASM文件,您会发现Microsoft的某个人在插入各种"hacky“包含、指令、手动段定义和其他MASM细节时遇到了很大的麻烦,从而使源文件至少有很小的机会被反馈到MASM中,并获得一个组装的结果。只要你把你的期望调低,我想一个简单的C源文件,转换成ASM,然后反馈到MASM,如果你把命令行选项按顺序排列的话,应该可以工作。
您需要记住的一个警告是,如果您像您正在做的那样使用CRT (即使用memcmp),您将希望从适当的CRT .LIB文件中选择默认的入口点.LIB,而不是指定您自己的。这允许在调用DllMain之前初始化CRT,从而防止在调用依赖于此初始化的某些CRT函数时崩溃。尽管如此,Visual的旧版本,如7.1 (2003),您可以不初始化CRT,这取决于您使用的是哪些函数,而不存在崩溃的风险。如果进程以前没有调用过mainCRTStarttup或DllMainCRTStartup,则function的更新版本将抛出异常,而不管调用哪个CRT函数。
出于教育目的,让我们使用MSVC 7.1 (2003)来解决前面描述的切入点问题,我们不会担心初始化CRT,这样您就可以显式地指定您自己的入口点。我认为你击中了以下链接器警告:
warning LNK4086: entrypoint '_prog@XX' is not __stdcall with 12 bytes of arguments; image may not run在指定自己的DLL入口点时,链接器需要一个DllMain签名(这是12个参数字节和stdcall,因此函数本身清除了参数本身);正式的情况是:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)您可以实现entrypoint函数,如这个版本的pr.c所示:
#include <Windows.h>
#include <stdio.h>
#pragma warning (disable:4100) //Warning Level 4: unreferenced formal parameter
int __stdcall prog(DWORD hInst, DWORD dwReason, DWORD dwReserved)
{
printf("Result of memcmp: %d\n",memcmp("foo","bar",3));
return(1);
}假设正确设置了LIB和INCLUDE环境变量,则可以使用以下命令构建上面的源代码:
cl.exe /nologo /c /MD /Fa./prog.asm prog.c
link.exe /nologo /dll /subsystem:console /entry:prog prog.obj kernel32.lib您已经知道可以使用C编译器构建原始C源。关注从prog.asm选项生成的/Fa输出文件,您可以从生成的/Fa源构建DLL,如下所示:
ml.exe /c /coff /Cx prog.asm
link.exe /nologo /dll /subsystem:console /entry:prog prog.obj kernel32.lib使用简单的控制台加载程序测试DLL,如:
#include <Windows.h>
int __cdecl main(void)
{
HMODULE hLib = LoadLibrary("prog.dll");
printf("LoadLibrary result: 0x%X / code=0x%X\n",hLib,GetLastError());
}在我的机器上,C和MASM生成的DLL都产生了以下输出:
Result of memcmp: 1
LoadLibrary result: 0x10000000 / code=0x0
Result of memcmp: 1下面列出编译器生成的MSVC7.1ASM文件,以供参考。请注意文件如何将自身称为“清单”:)
; Listing generated by Microsoft (R) Optimizing Compiler Version 13.10.6030
TITLE prog.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
$$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
INCLUDELIB MSVCRT
INCLUDELIB OLDNAMES
_DATA SEGMENT
$SG74617 DB 'bar', 00H
$SG74618 DB 'foo', 00H
$SG74619 DB 'Result of memcmp: %d', 0aH, 00H
_DATA ENDS
PUBLIC _prog@12
EXTRN __imp__printf:NEAR
EXTRN _memcmp:NEAR
; Function compile flags: /Odt
_TEXT SEGMENT
_hInst$ = 8 ; size = 4
_dwReason$ = 12 ; size = 4
_dwReserved$ = 16 ; size = 4
_prog@12 PROC NEAR
; File prog.c
; Line 10
push ebp
mov ebp, esp
; Line 11
push 3
push OFFSET FLAT:$SG74617
push OFFSET FLAT:$SG74618
call _memcmp
add esp, 12 ; 0000000cH
push eax
push OFFSET FLAT:$SG74619
call DWORD PTR __imp__printf
add esp, 8
; Line 12
mov eax, 1
; Line 13
pop ebp
ret 12 ; 0000000cH
_prog@12 ENDP
_TEXT ENDS
ENDhttps://stackoverflow.com/questions/41007063
复制相似问题