0

我正在尝试编译某人的程序,该程序部分是用汇编程序编写的,部分是用 C 语言编写的。该程序在编译版本中可用,但是我需要对其进行一些更改。该程序的源代码由一个.c 文件和一个.asm 文件组成。在没有更改任何内容的情况下,我尝试在 Visual Studio 2017 和 Flat Assembler(版本 1.73)中编译该程序。我编译了 .asm 文件,Flat Assembler 给了我 .obj 文件(unlzws4.obj)。然后我在 VS 中创建了一个新的空项目,并从 FASM 导入了 .c 文件和 .obj 文件。

在此处输入图像描述

这里问题出现了。在编译期间,Visual Studio 给了我这个链接错误:

1>------ Rebuild All started: Project: unlibs4, Configuration: Debug Win32 ------
1>unlibs4.c
1>unlzws4.obj : fatal error LNK1107: invalid or corrupt file: cannot read at 0x10EE4
1>Done building project "unlibs4.vcxproj" -- FAILED.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

我试图找出为什么会出现这个错误,但是没有结果。代码应该是正确的。

unlibs4.c 文件:

// (c) CTPAX-X Team 2018 http://www.CTPAX-X.org/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <windows.h>

#ifdef GCC32HACK
#include "win32gcc.h"
#endif

#define S4L_REVISION 0x1000
#define S4F_PACKED   1
#define S4F_CRYPTED  2
#pragma pack(push, 1)
typedef struct
{
    DWORD headsize; /* size of this header with all data */
    DWORD revision; /* MUST be equal to 0x1000 */
    DWORD dnamelen; /* directory names block len */
    DWORD dcounter; /* directory count in block  */
    DWORD fnamelen; /* file names block len */
    DWORD fcounter; /* files counter */
} headinfo;

typedef struct
{
    DWORD floffs; /* looks like first always 1 (.LIB file starts with one zero byte) */
    DWORD pksize; /* packed size */
    DWORD unsize; /* unpacked size (zero if file not packed) */
    DWORD dindex; /* directory name index */
    DWORD xflags; /* flags: 1 - packed; 2 - crypted; */
    DWORD crcsum; /* file CRC (16 bit); can be zero; only for packed files? */
} fileinfo;
#pragma pack(pop)


extern void WINAPI unlzws4(BYTE *undata, DWORD *unsize, BYTE *pkdata, DWORD *pksize);

int main(int argc, char *argv[])
{
    char *dnames, *fnames, *s, *d, name[MAX_PATH];
    fileinfo *list;
    FILE *fl, *f;
    headinfo hi;
    DWORD i, j;
    BYTE *p, *u;
    printf("The Settlers IV .LIB unpacker v1.0\n(c) CTPAX-X Team 2018\nhttp://www.CTPAX-X.org/\n\n");
    if (argc != 2)
    {
        printf("Usage: unlibs4 <filename.lib>\n\n");
        return(1);
    }
    fl = fopen(argv[1], "rb");
    if (!fl)
    {
        printf("Error: can't open input file.\n\n");
        return(2);
    }
    /* read TOC offs */
    fseek(fl, 0, SEEK_END);
    fseek(fl, ftell(fl) - 4, SEEK_SET);
    fread(&i, 4, 1, fl);
    /* read TOC */
    fseek(fl, i, SEEK_SET);
    memset(&hi, 0, sizeof(hi));
    fread(&hi, sizeof(hi), 1, fl);
    if (hi.revision != S4L_REVISION)
    {
        fclose(fl);
        printf("Error: invalid/unknown input file format.\n\n");
        return(3);
    }
    /* allocate memory */
    dnames = (char *)malloc(hi.dnamelen);
    fnames = (char *)malloc(hi.fnamelen);
    list = (fileinfo *)malloc(hi.fcounter * sizeof(list[0]));
    if (dnames && fnames && list)
    {
        /* read strings */
        fread(dnames, hi.dnamelen, 1, fl);
        fread(fnames, hi.fnamelen, 1, fl);
        /* read file infos */
        fread(list, hi.fcounter, sizeof(list[0]), fl);
        /* create all directories before */
        d = dnames;
        for (i = 0; i < hi.dcounter; i++)
        {
            CreateDirectory(d, NULL);
            d += strlen(d) + 1;
        }
        /* unpack */
        s = fnames;
        for (i = 0; i < hi.fcounter; i++)
        {
            /* find directory name */
            d = dnames;
            j = list[i].dindex;
            while (j > 0)
            {
                d += strlen(d) + 1;
                j--;
            }
            /* merge directory with file */
            sprintf(name, "%s\\%s", d, s);
            /* dump to disk */
            printf("%s\n", name);
            f = fopen(name, "wb");
            if (f)
            {
                p = (BYTE *)malloc(list[i].pksize);
                if (p)
                {
                    fseek(fl, list[i].floffs, SEEK_SET);
                    fread(p, list[i].pksize, 1, fl);
                    if (list[i].xflags & S4F_CRYPTED)
                    {
                        printf("Warning: encrypted file, but decryption not supported - saving as is.\n");
                    }
                    /* decryption not supported, that's why '==' instead of just '&' */
                    if ((list[i].xflags & (S4F_CRYPTED | S4F_PACKED)) == S4F_PACKED)
                    {
                        u = (BYTE *)malloc(list[i].unsize);
                        if (u)
                        {
                            j = list[i].unsize;
                            unlzws4(u, &list[i].unsize, p, &list[i].pksize);
                            free(p);
                            p = u;
                            list[i].pksize = j;
                        }
                    }
                    fwrite(p, list[i].pksize, 1, f);
                    free(p);
                }
                fclose(f);
            }
            /* next filename */
            s += strlen(s) + 1;
        }
        printf("\ndone\n\n");
    }
    if (dnames) { free(dnames); }
    if (fnames) { free(fnames); }
    if (list) { free(list); }
    fclose(fl);
    return(0);
}

unlzws4.asm 文件的开头:

; To compile this source code you'll need FASM:
; http://flatassembler.net/
FORMAT COFF

include 'win32ax.inc'

; define section so this can be merged to the code block
section '.text' code

public @startup as '_unlzws4@16'

; some consts
;dword_616478 - start
dword_6167E0 = buf_all + 6167E0h - 616478h
dword_6167E4 = buf_all + 6167E4h - 616478h
dword_616DF8 = buf_all + 616DF8h - 616478h
dword_617060 = buf_all + 617060h - 616478h
dword_617064 = buf_all + 617064h - 616478h

; ###########################################################################

; some startup initialization code
@startup:
  push    esi
  push    edi
  xor     eax, eax
  cld
  ; clear all buffers
  mov     edi, buf_65536
  mov     ecx, 65536 / 4
  rep stosd
  ; ---
  mov     edi, buf_548
  mov     ecx, 548 / 4
  rep     stosd
  ; reinit static buffer since it can be modified due unpacking (sic!)
  mov     esi, dword_616478
  mov     edi, buf_all
  mov     ecx, (3112d + 152d) / 4
  rep     movsd
  ; ---
  pop     edi
  pop     esi
  ; emulate some class structure
  mov     ecx, _buf
  ; jump to the actual unpacking routine
  jmp     @sub_573090

; ###########################################################################

@sub_572450:
var_4           = -4
arg_0           =  4
arg_4           =  8
  push    ecx
  push    ebx
  mov     ebx, [esp+8+arg_0]
  push    ebp
  mov     ebp, [esp+0Ch+arg_4]
  push    esi
  push    edi
  mov     esi, 28h
@loc_572462:

...

我对汇编程序不太了解,我只需要更改程序的C部分并将其编译为.dll库。我想知道是否只是因为 Visual Studio 项目中的某些设置而出现错误。一切都设置为默认选项。

4

1 回答 1

1

要使用 Microsoft 链接器进行链接,您需要拥有 MSCOFF 格式的目标文件。你在哪里

FORMAT COFF

你需要:

FORMAT MS COFF

来自https://flatassembler.net/docs.php?article=manual#2.4.3

2.4.3 通用对象文件格式

要选择通用对象文件格式,请使用格式 COFF 或格式 MS COFF 指令,具体取决于您要创建经典 (DJGPP) 文件还是 Microsoft 的 COFF 文件变体。此格式的默认代码设置为 32 位。要为 x86-64 架构创建 Microsoft 的 COFF 格式的文件,请使用格式 MS64 COFF 设​​置,在这种情况下,默认生成长模式代码。

于 2019-02-24T00:26:20.917 回答