无法编译编译器生成的确切程序集列表

问题描述 投票:0回答:1

我的环境是 x86 Native Tools for VS 2022。 其他地方的情况可能有所不同 x86-64 和 ARM 等平台。

我正在尝试编译生成的程序集列表 由编译器使用如下命令行

cl foo.c /Fa /FAs
。选项
/Fa
表示需要 列表文件,
/FAs
表示需要 列表文件中对应的 C 源代码行。

获得列表文件后,我尝试编译 带有命令行的列表文件,例如

ml foo.asm
。我添加了相应的链接选项 就像
/link /subsystem:windows
/link User32.lib

我在某些文件中成功了,但在以下情况下失败了: 尝试用最小的 Windows API 来做到这一点 消息循环。

该C文件可以编译并运行良好。 然而,当我尝试编译它的列表文件时, 汇编器,

ml
,失败并出现错误:

win.asm(45) : error A2008:syntax error : flat

当我查看第45行时,是:

           voltbl   SEGMENT
           _volmd   DD  0ffffffffH
(LINE 45)           DDSymXIndex:    FLAT:_WinMain@16
                    DD  0dH
                    DD  0ecH
           voltbl   ENDS

我猜是

FLAT
中的
DDSymXIndex: FLAT:_WinMain@16
导致了这个问题。

但是,这个列表文件是由

cl
生成的, 编译器本身。因此,不应该有 成为问题。是否有一些命令行选项 我错过了?

有一个相关问题。然而,这个问题 似乎与库链接有关,即 不是我的情况。 链接如下。

VC++生成的编译汇编输出?

附件1:列表文件编译成功的文件

这个文件非常简单。 它只包含一个空的主函数, 什么都不做。

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
}

附件2:列表文件编译成功的另一个文件

此文件会弹出一个消息框。 它的程序集列表文件也 编译成功。

我使用了以下命令行 生成列表文件并编译:

> cl /Fa /FAs msgbox.c
> del msgbox.exe   (TO MAKE SURE A NEW EXECUTABLE IS CREATED)
> ml msgbox.asm /link User32.lib
               (^^^^^^^^^^^^^^^^ THIS PART IS IMPORTANT)
> msgbox
(IT RUNS AND WORKS)

代码:

#include <windows.h>
#pragma comment(lib, "User32.lib")

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
{
        MessageBox(NULL, "TEST", "TITLE",
                        MB_ICONEXCLAMATION | MB_OK);
}

附件3:列表文件编译失败的最小Windows API消息循环文件的C源代码

这是一个有效的C文件,可以编译 由C编译器和生成 可执行文件运行。然而,大会 此 C 文件生成的列表文件 编译失败。参见上文 编译错误的详细信息。

#include <windows.h>
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "gdi32.lib")

LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        switch (msg) {
        case WM_CLOSE:
                DestroyWindow(hwnd);
                break;
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        return 0;
}

BOOL register_window(const char * szClassName, HINSTANCE hInstance) {
        WNDCLASSEX wc;
        wc.cbSize = sizeof(WNDCLASSEX);
        wc.style = 0;
        wc.lpfnWndProc = wndproc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
        wc.lpszMenuName = NULL;
        wc.lpszClassName = szClassName;
        wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
        if (RegisterClassEx( & wc))
                return TRUE;
        MessageBox(NULL, "Window Registration Failed!", "Error!",
                MB_ICONEXCLAMATION | MB_OK);
        return FALSE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
{
        HWND hwnd;
        MSG Msg;
        const char szClassName[] = "myWindowClass";

        if (!register_window(szClassName, hInstance))
                return 0;

        hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, szClassName, "MY WINDOW",
                WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                640, 480, NULL, NULL,
                hInstance, NULL);

        if (!hwnd) {
                MessageBox(NULL, "Window Creation Failed!", "Error!",
                        MB_ICONEXCLAMATION | MB_OK);
                return 0;
        }

        ShowWindow(hwnd, nCmdShow);
        UpdateWindow(hwnd);

        while (GetMessage( & Msg, NULL, 0, 0) > 0) {
                TranslateMessage( & Msg);
                DispatchMessage( & Msg);
        }
        return Msg.wParam;
}

附件4:编译失败的完整列表文件

汇编器未能生成 目标文件,在到达之前 链接阶段。 因此,目前还没有必要 检查可能出现的问题 链接阶段。

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.38.33130.0 

    TITLE   C:\...\win.obj
    .686P
    .XMM
    include listing.inc
    .model  flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC  _WinMain@16
PUBLIC  _wndproc@16
PUBLIC  _register_window
EXTRN   __imp__CreateSolidBrush@4:PROC
EXTRN   __imp__GetMessageA@16:PROC
EXTRN   __imp__TranslateMessage@4:PROC
EXTRN   __imp__DispatchMessageA@4:PROC
EXTRN   __imp__DefWindowProcA@16:PROC
EXTRN   __imp__PostQuitMessage@4:PROC
EXTRN   __imp__RegisterClassExA@4:PROC
EXTRN   __imp__CreateWindowExA@48:PROC
EXTRN   __imp__DestroyWindow@4:PROC
EXTRN   __imp__ShowWindow@8:PROC
EXTRN   __imp__UpdateWindow@4:PROC
EXTRN   __imp__MessageBoxA@16:PROC
EXTRN   __imp__LoadCursorA@8:PROC
EXTRN   __imp__LoadIconA@8:PROC
EXTRN   @__security_check_cookie@4:PROC
EXTRN   ___security_cookie:DWORD
_DATA   SEGMENT
$SG72129 DB 'Error!', 00H
    ORG $+1
$SG72130 DB 'Window Registration Failed!', 00H
$SG72148 DB 'myWindowClass', 00H
    ORG $+2
$SG72150 DB 'MY WINDOW', 00H
    ORG $+2
$SG72152 DB 'Error!', 00H
    ORG $+1
$SG72153 DB 'Window Creation Failed!', 00H
_DATA   ENDS
voltbl  SEGMENT
_volmd  DD  0ffffffffH
    DDSymXIndex:    FLAT:_WinMain@16
    DD  0dH
    DD  0ecH
voltbl  ENDS

; Function compile flags: /Odtp
; File C:\...\win.c
_TEXT   SEGMENT
_wc$ = -48                      ; size = 48
_szClassName$ = 8                   ; size = 4
_hInstance$ = 12                    ; size = 4
_register_window PROC

; 20   : BOOL register_window(const char * szClassName, HINSTANCE hInstance) {

    push    ebp
    mov ebp, esp
    sub esp, 48                 ; 00000030H

; 21   :         WNDCLASSEX wc;
; 22   :         wc.cbSize = sizeof(WNDCLASSEX);

    mov DWORD PTR _wc$[ebp], 48         ; 00000030H

; 23   :         wc.style = 0;

    mov DWORD PTR _wc$[ebp+4], 0

; 24   :         wc.lpfnWndProc = wndproc;

    mov DWORD PTR _wc$[ebp+8], OFFSET _wndproc@16

; 25   :         wc.cbClsExtra = 0;

    mov DWORD PTR _wc$[ebp+12], 0

; 26   :         wc.cbWndExtra = 0;

    mov DWORD PTR _wc$[ebp+16], 0

; 27   :         wc.hInstance = hInstance;

    mov eax, DWORD PTR _hInstance$[ebp]
    mov DWORD PTR _wc$[ebp+20], eax

; 28   :         wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    push    32512                   ; 00007f00H
    push    0
    call    DWORD PTR __imp__LoadIconA@8
    mov DWORD PTR _wc$[ebp+24], eax

; 29   :         wc.hCursor = LoadCursor(NULL, IDC_ARROW);

    push    32512                   ; 00007f00H
    push    0
    call    DWORD PTR __imp__LoadCursorA@8
    mov DWORD PTR _wc$[ebp+28], eax

; 30   :         wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));

    push    0
    call    DWORD PTR __imp__CreateSolidBrush@4
    mov DWORD PTR _wc$[ebp+32], eax

; 31   :         wc.lpszMenuName = NULL;

    mov DWORD PTR _wc$[ebp+36], 0

; 32   :         wc.lpszClassName = szClassName;

    mov ecx, DWORD PTR _szClassName$[ebp]
    mov DWORD PTR _wc$[ebp+40], ecx

; 33   :         wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    push    32512                   ; 00007f00H
    push    0
    call    DWORD PTR __imp__LoadIconA@8
    mov DWORD PTR _wc$[ebp+44], eax

; 34   :         if (RegisterClassEx( & wc))

    lea edx, DWORD PTR _wc$[ebp]
    push    edx
    call    DWORD PTR __imp__RegisterClassExA@4
    movzx   eax, ax
    test    eax, eax
    je  SHORT $LN2@register_w

; 35   :                 return TRUE;

    mov eax, 1
    jmp SHORT $LN1@register_w
$LN2@register_w:

; 36   :         MessageBox(NULL, "Window Registration Failed!", "Error!",

    push    48                  ; 00000030H
    push    OFFSET $SG72129
    push    OFFSET $SG72130
    push    0
    call    DWORD PTR __imp__MessageBoxA@16

; 37   :                 MB_ICONEXCLAMATION | MB_OK);
; 38   :         return FALSE;

    xor eax, eax
$LN1@register_w:

; 39   : }

    mov esp, ebp
    pop ebp
    ret 0
_register_window ENDP
_TEXT   ENDS
; Function compile flags: /Odtp
; File C:\...\win.c
_TEXT   SEGMENT
tv64 = -4                       ; size = 4
_hwnd$ = 8                      ; size = 4
_msg$ = 12                      ; size = 4
_wParam$ = 16                       ; size = 4
_lParam$ = 20                       ; size = 4
_wndproc@16 PROC

; 6    : LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

    push    ebp
    mov ebp, esp
    push    ecx

; 7    :         switch (msg) {

    mov eax, DWORD PTR _msg$[ebp]
    mov DWORD PTR tv64[ebp], eax
    cmp DWORD PTR tv64[ebp], 2
    je  SHORT $LN5@wndproc
    cmp DWORD PTR tv64[ebp], 16         ; 00000010H
    je  SHORT $LN4@wndproc
    jmp SHORT $LN6@wndproc
$LN4@wndproc:

; 8    :         case WM_CLOSE:
; 9    :                 DestroyWindow(hwnd);

    mov ecx, DWORD PTR _hwnd$[ebp]
    push    ecx
    call    DWORD PTR __imp__DestroyWindow@4

; 10   :                 break;

    jmp SHORT $LN2@wndproc
$LN5@wndproc:

; 11   :         case WM_DESTROY:
; 12   :                 PostQuitMessage(0);

    push    0
    call    DWORD PTR __imp__PostQuitMessage@4

; 13   :                 break;

    jmp SHORT $LN2@wndproc
$LN6@wndproc:

; 14   :         default:
; 15   :                 return DefWindowProc(hwnd, msg, wParam, lParam);

    mov edx, DWORD PTR _lParam$[ebp]
    push    edx
    mov eax, DWORD PTR _wParam$[ebp]
    push    eax
    mov ecx, DWORD PTR _msg$[ebp]
    push    ecx
    mov edx, DWORD PTR _hwnd$[ebp]
    push    edx
    call    DWORD PTR __imp__DefWindowProcA@16
    jmp SHORT $LN1@wndproc
$LN2@wndproc:

; 16   :         }
; 17   :         return 0;

    xor eax, eax
$LN1@wndproc:

; 18   : }

    mov esp, ebp
    pop ebp
    ret 16                  ; 00000010H
_wndproc@16 ENDP
_TEXT   ENDS
; Function compile flags: /Odtp
; File C:\...\win.c
_TEXT   SEGMENT
_Msg$ = -52                     ; size = 28
_hwnd$ = -24                        ; size = 4
_szClassName$ = -20                 ; size = 14
__$ArrayPad$ = -4                   ; size = 4
_hInstance$ = 8                     ; size = 4
_hPrevInstance$ = 12                    ; size = 4
_lpCmdLine$ = 16                    ; size = 4
_nCmdShow$ = 20                     ; size = 4
_WinMain@16 PROC

; 43   : {

    push    ebp
    mov ebp, esp
    sub esp, 52                 ; 00000034H
    mov eax, DWORD PTR ___security_cookie
    xor eax, ebp
    mov DWORD PTR __$ArrayPad$[ebp], eax

; 44   :         HWND hwnd;
; 45   :         MSG Msg;
; 46   :         const char szClassName[] = "myWindowClass";

    mov eax, DWORD PTR $SG72148
    mov DWORD PTR _szClassName$[ebp], eax
    mov ecx, DWORD PTR $SG72148+4
    mov DWORD PTR _szClassName$[ebp+4], ecx
    mov edx, DWORD PTR $SG72148+8
    mov DWORD PTR _szClassName$[ebp+8], edx
    mov ax, WORD PTR $SG72148+12
    mov WORD PTR _szClassName$[ebp+12], ax

; 47   : 
; 48   :         if (!register_window(szClassName, hInstance))

    mov ecx, DWORD PTR _hInstance$[ebp]
    push    ecx
    lea edx, DWORD PTR _szClassName$[ebp]
    push    edx
    call    _register_window
    add esp, 8
    test    eax, eax
    jne SHORT $LN4@WinMain

; 49   :                 return 0;

    xor eax, eax
    jmp $LN1@WinMain
$LN4@WinMain:

; 50   : 
; 51   :         hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, szClassName, "MY WINDOW",

    push    0
    mov eax, DWORD PTR _hInstance$[ebp]
    push    eax
    push    0
    push    0
    push    480                 ; 000001e0H
    push    640                 ; 00000280H
    push    -2147483648             ; 80000000H
    push    -2147483648             ; 80000000H
    push    13565952                ; 00cf0000H
    push    OFFSET $SG72150
    lea ecx, DWORD PTR _szClassName$[ebp]
    push    ecx
    push    512                 ; 00000200H
    call    DWORD PTR __imp__CreateWindowExA@48
    mov DWORD PTR _hwnd$[ebp], eax

; 52   :                 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
; 53   :                 640, 480, NULL, NULL,
; 54   :                 hInstance, NULL);
; 55   : 
; 56   :         if (!hwnd) {

    cmp DWORD PTR _hwnd$[ebp], 0
    jne SHORT $LN5@WinMain

; 57   :                 MessageBox(NULL, "Window Creation Failed!", "Error!",

    push    48                  ; 00000030H
    push    OFFSET $SG72152
    push    OFFSET $SG72153
    push    0
    call    DWORD PTR __imp__MessageBoxA@16

; 58   :                         MB_ICONEXCLAMATION | MB_OK);
; 59   :                 return 0;

    xor eax, eax
    jmp SHORT $LN1@WinMain
$LN5@WinMain:

; 60   :         }
; 61   : 
; 62   :         ShowWindow(hwnd, nCmdShow);

    mov edx, DWORD PTR _nCmdShow$[ebp]
    push    edx
    mov eax, DWORD PTR _hwnd$[ebp]
    push    eax
    call    DWORD PTR __imp__ShowWindow@8

; 63   :         UpdateWindow(hwnd);

    mov ecx, DWORD PTR _hwnd$[ebp]
    push    ecx
    call    DWORD PTR __imp__UpdateWindow@4
$LN2@WinMain:

; 64   : 
; 65   :         while (GetMessage( & Msg, NULL, 0, 0) > 0) {

    push    0
    push    0
    push    0
    lea edx, DWORD PTR _Msg$[ebp]
    push    edx
    call    DWORD PTR __imp__GetMessageA@16
    test    eax, eax
    jle SHORT $LN3@WinMain

; 66   :                 TranslateMessage( & Msg);

    lea eax, DWORD PTR _Msg$[ebp]
    push    eax
    call    DWORD PTR __imp__TranslateMessage@4

; 67   :                 DispatchMessage( & Msg);

    lea ecx, DWORD PTR _Msg$[ebp]
    push    ecx
    call    DWORD PTR __imp__DispatchMessageA@4

; 68   :         }

    jmp SHORT $LN2@WinMain
$LN3@WinMain:

; 69   :         return Msg.wParam;

    mov eax, DWORD PTR _Msg$[ebp+8]
$LN1@WinMain:

; 70   : }

    mov ecx, DWORD PTR __$ArrayPad$[ebp]
    xor ecx, ebp
    call    @__security_check_cookie@4
    mov esp, ebp
    pop ebp
    ret 16                  ; 00000010H
_WinMain@16 ENDP
_TEXT   ENDS
END

总结一下:

  1. 我正在尝试编译程序集列表 由
    cl
    生成。
  2. 我成功地创建了两个小测试文件。
  3. 虽然我用的是同样的方法, 我的另一个测试文件失败了。
windows visual-c++ x86 masm cl
1个回答
0
投票

就是这些行:

           voltbl   SEGMENT
           _volmd   DD  0ffffffffH
(LINE 45)           DDSymXIndex:    FLAT:_WinMain@16
                    DD  0dH
                    DD  0ecH
           voltbl   ENDS

通过删除这些行,程序集列表 只需编译并运行即可。

DDSym
可能类似于“调试符号”? 因此我尝试删除这些行,并且 它只是有效。

但是我还是不明白为什么C编译器 生成这些无法编译的行 汇编器。也许我错过了一些 命令行选项 告诉汇编器如何处理这些调试 符号。无论如何,我目前不会研究它。

© www.soinside.com 2019 - 2024. All rights reserved.