首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >汇编程序MASM (64位)不识别入口点并抛出错误。

汇编程序MASM (64位)不识别入口点并抛出错误。
EN

Stack Overflow用户
提问于 2022-07-19 08:21:27
回答 1查看 262关注 0票数 0

我正在研究x86系列处理器架构的汇编程序(32位和64位).并不是说我很初学者,但我可能不知道所有的事情,至少是关于MASM汇编程序的语法,就像看上去的那样。我使用位于Visual文件夹中的MASM汇编程序(用于64位程序):

"..\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\ml64.exe

安装了Visual 2019,我从它的文件夹中使用MASM汇编程序。我自己也有Windows 7

我为32位系统编写了程序,它通常由MASM为32位程序组装并工作。然后,我为64位架构翻译了它的代码(在代码中几乎不需要修改)。但是,当将其与64位程序组装时,MASM给出了一个错误消息,即据称存在一些未解决的"StartOfProgram“符号。下面是控制台中的内容:

代码语言:javascript
运行
复制
C:\Assembler>cd "C:\Assembler"

C:\Assembler>"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\ml64.exe" "C:\Assembler\Main.asm" /link /subsystem:windows /entry:StartOfProgram
Microsoft (R) Macro Assembler (x64) Version 14.29.30138.0
Copyright (C) Microsoft Corporation.  All rights reserved.

 Assembling: C:\Assembler\Main.asm
Microsoft (R) Incremental Linker Version 14.29.30138.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/OUT:Main.exe
Main.obj
/subsystem:windows
/entry:StartOfProgram
LINK : error LNK2001: unresolved external symbol StartOfProgram.
Main.exe : fatal error LNK1120: unresolved external symbols: 1

我花了大约两个星期或一个月来寻找这个错误的解决方案,但我没有找到。

一般来说,他经常给出一条错误信息,说据称有一些未解决的符号"WinMainCRTStartup",但最近我有点意识到他是这样做的,因为我没有在控制台中明确指定入口点(通过命令"/entry:",从上面的控制台中),但是关于"unresolved external symbol“的问题仍然存在,尽管我在需要它的地方设置了入口点(即"StartOfProgram")。

下面是我的64位程序的代码,它只需在弹出窗口中输出"Hello“:

代码语言:javascript
运行
复制
option  casemap:none    ; As far as i understand, functions from Windows API without case sensitivity not works

; **** Importing what needs ****

includelib  "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\kernel32.lib"   ; Downloading main static library to use main functions of Windows API
includelib  "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\User32.lib"

extern      LoadLibraryA:near    ; I load from static libraries a functions used in this program
extern      GetProcAddress:near
extern      FreeLibrary:near
extern      ExitProcess:near

; **** Declaring a memory segment ****

.data

        text                    db  'Hello world', 0            ; Text in "Text Box"'s window
        header                  db  'Title of hello world', 0   ; Header of "Text Box"'s window
        nameOfDLL               db  'user32.dll', 0
        nameOfProcedureOfDLL    db  'MessageBoxA', 0

        handlerToModule         dd  0
        addressOfProcedureOfDLL dq  0   ; In 64-bit operating system, addresses are 64-bit, so size of memory area that this label points to - is quad word (dq) (that is 64 bits)

.code

; **** Entry point to program ****

StartOfProgram:    ; For some reason, MASM assembler recommends putting "_" sign before label of entry point to program, if it is 32-bit. Therefore, here, in 64-bit, i finally do not put

        push    qword ptr nameOfDLL
        call    LoadLibraryA                    ; I dynamically connect DLL so that i can then take function from it
        
        mov     handlerToModule, eax
        
        push    qword ptr nameOfProcedureOfDLL
        push    rax                             ; Functions from Windows API use stdcall convention. stdcall is agreement to pass function parameters to stack backwards, so rax is last. Rax still contains Windows' DLL address (Microsoft call it "handler") (after recent call to Loadlibrary function), so it's better to use register, processor works faster with registers
        call    GetProcAddress
        
        mov     addressOfProcedureOfDLL, rax    ; I save address of procedure that i took from GetProcAddress. In 64-bit operating system, addresses are 64-bit, so needs to transfer rax register and not eax
        
        push    0
        push    qword ptr header
        push    qword ptr text
        push    0
        call    qword ptr addressOfProcedureOfDLL   ; It is better to immediately pass address of function through memory address label and not through register containing this address, because computer will still have to go to this address later and there is no point in wasting time reading from  register of same address
        
        push    qword ptr handlerToModule
        call    FreeLibrary

        push    0
        call    ExitProcess

end

下面是这个程序的32位版本的代码(通常是组装和工作的):

代码语言:javascript
运行
复制
.386    ; There indicates processor with minimal set of functions (since new Intel processors (in "x86" family of architectures) are compatible (so far) with instructions of old Intel processors of same family of architectures)

option  casemap:none    ; As far as i understand, functions from Windows API without case sensitivity not works

; **** Importing what needs ****

includelib  "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86\kernel32.lib"   ; Downloading main static library to use main functions of Windows API
;includelib  "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86\User32.lib"

extern      _LoadLibraryA@4:near    ; I load from static libraries a functions used in this program
extern      _GetProcAddress@8:near
extern      _FreeLibrary@4:near
extern      _ExitProcess@4:near

.model flat

; **** Declaring a memory segment ****

.data

        text                    db  'Hello world', 0            ; Text in "Text Box"'s window
        header                  db  'Title of hello world', 0   ; Header of "Text Box"'s windowокна

        nameOfDLL               db  'user32.dll', 0
        nameOfProcedureOfDLL    db  'MessageBoxA', 0

        handlerToModule         dd  0
        addressOfProcedureOfDLL dd  0

.code

; **** Entry point to program ****

_StartOfProgram:    ; For some reason, MASM assembler recommends putting "_" sign before label of entry point to program, if it is 32-bit

        push    offset nameOfDLL
        call    _LoadLibraryA@4                 ; I dynamically connect DLL so that i can then take function from it
        
        mov     handlerToModule, eax
        
        push    offset nameOfProcedureOfDLL
        push    eax                             ; Functions from Windows API use stdcall convention. stdcall is agreement to pass function parameters to stack backwards, so eax is last. Eax still contains Windows' DLL address (Microsoft call it "handler") (after recent call to Loadlibrary function), so it's better to use register, processor works faster with registers
        call    _GetProcAddress@8
        
        mov     addressOfProcedureOfDLL, eax    ; I save address of procedure that i took from GetProcAddress 
        
        push    0
        push    offset header
        push    offset text
        push    0
        call    addressOfProcedureOfDLL
        
        push    handlerToModule
        call    _FreeLibrary@4

        push    0
        call    _ExitProcess@4

end _StartOfProgram

这是32位程序版本的结果:

程序32位版本的结果

EN

回答 1

Stack Overflow用户

发布于 2022-07-19 21:06:04

因此,问题在评论中得到了解决。正如@Peter Cordes和@David Wohlferd所说,我需要通过指令"public“在我的程序中公开我的标签,然后写标签的名称,或者在这个指令的开头用指令"proc”和"endp“重写我的入口点标签。

我更喜欢通过"public“指令解决方案,因为我认为它更接近于低级别编程。在这种情况下,我必须使用"public“指令在我的程序中公开我的标签,然后在它的末尾写标签的名称,以使外部程序可用。显然,MASM汇编程序出现了错误,因为它没有从外部访问它,因此不认为将它指定为入口点是正确的,尽管他可以猜到,如果我指定它为入口点,那么它可以从外部切换到它。显然,MASM的开发人员没有这样做。

下面是在我的程序中使用指令"public“的示例(我使用了指令"public"):

public StartOfProgram

我注意到我可以把它放在代码的任何地方

下面是在我的程序中使用指令"proc“和"endp”的示例:

代码语言:javascript
运行
复制
StartOfProgram proc     ; - Beginning of this directivical procedure

; ... there may be the code itself inside this directivical procedure

StartOfProgram endp     ; - End of this directivical procedure

但是我的代码有其他错误,但它不是这个问题的主题,所以,当我在我的程序中纠正它时,我会在那里更正它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73033509

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档