通过Wine实现在mac和linux上实现masm编程

原文链接:Using MASM on Mac or Linux via Wine

抄这个文档是因为它的确有用,mac下也能很好的学习windows api。而且我怕老外的文档无法访问。

Wine是啥

来百度百科一下:

Wine (“Wine Is Not an Emulator” 的缩写)是一个能够在多种 POSIX-compliant 操作系统(诸如 Linux,macOS 及 BSD 等)上运行 Windows 应用的兼容层。

Wine(Windows运行环境)是一个在Linux和UNIX之上的Windows 3.x和 Windows API (以下简称动态接口)的实现。注意,Wine不是模拟Windows的工具,而是运用API转换技术实做出Linux对应到Windows相对应的函数来调用DLL(动态链接库)以运行Windows程序。

Wine可以工作在绝大多数的UNIX版本下,包括Linux, FreeBSD, 和 Solaris。另外,也有适用于Mac OS X的Wine程序。Wine不需要Microsoft Windows系统, 因为这是一个完全由百分之百的免费代码组成的。如果有可利用的副本的话,它也可以随意地使用本地系统的DLLs。Wine的发布是完全公开源代码的,并且是免费发行的。(基于LGPL发布:GNU宽通用公共许可证)
Wine 是一款免费和开源的兼容层,它使得在运行 Linux、FreeBSD 或其他一些操作系统的计算机上运行一些 Windows 应用程序成为可能。它也是 Valve 用来让 Steam Deck 用户在 Linux 驱动的手持设备上玩 Windows 游戏的 Proton 软件的基础。

Wine的安装

在mac下面

brew cask install wine-stable

创建Wine挂载的目录

wine运行在macos环境下的,这里需要一个指定的目录来存放window的相关文件,默认位置是:~/.wine, 但是吧,为了方便的运行各种代码,还是建议将位置放到其他地方: ~/wine-masm
使用下面的命令初始化该配置

WINEARCH=win32 WINEPREFIX=~/wine-masm winecfg

这个命令会在~/win-masm下面创建所有windows需要的文件,文件夹driver_c,代表windows C盘的目录。

masm32的安装

可以从官网下载指定版本的masm32,也可以直接使用下面的版本

wget http://website.assemblercode.com/masm32/masm32v11r.zip
unzip masm32v11r.zip
WINEPREFIX=~/wine-masm wine install.exe

安装过程

不添加masm编辑器的快捷方式

安装过程基本都是点击OK,除了下面的:

因为可以通过命令打开这个编辑器

WINEPREFIX=~/wine-masm wine 'C:\masm32\qeditor.exe'.

测试

使用下面的命令测试是否正确安装了

$ WINEPREFIX=~/wine-masm wine 'C:\masm32\bin\ml.exe'
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

usage: ML [ options ] filelist [ /link linkoptions]
Run "ML /help" or "ML /?" for more info

windows环境变量设置

为方便开发,需要将masm32的工具路径放到系统的环境变量里面,这个操作类似

export GOPATH=/usr/local/go

但是这里是windows,并且没有我的电脑, 只能用命令打开

WINEPREFIX=~/wine-masm wine regedit

配置地址: HKEY_CURRENT_USER/Environment,右击添加新的string值,如下:

PATH= %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\masm32\bin
INCLUDE=C:\masm32\include;C:\Irvine
LIB=C:\masm32\lib;C:\Irvine

测试环境变量

使用下面的命令挨个测试是否新建成功

$ export WINEPREFIX=~/wine-masm
$ wine ml -nologo -c -coff -Zi AddSub.asm
 Assembling: AddSub.asm
$ wine link /NOLOGO /SUBSYSTEM:CONSOLE /ENTRY:main \
    /LIBPATH:'C:\Irvine' irvine32.lib kernel32.lib user32.lib AddSub.obj
$ wine AddSub.exe

  EAX=00030000  EBX=00401000  ECX=0032FF03  EDX=000000D0
  ESI=7B84A20B  EDI=7FFDF000  EBP=0032FEE8  ESP=0032FED4
  EIP=00401014  EFL=00000206  CF=0  SF=0  ZF=0  OF=0  AF=0  PF=1

写入mac的profile

为了方便开发,将下面的命令写入profile,方便以后的开发

export WINE_MASM_DIR=~/wine-masm
function masm() (
    # Stop on errors
    set -e

    # Use the correct wine directory
    export WINEPREFIX=$WINE_MASM_DIR

    # Get the path to the file without a .asm extension
    FILENAME="$(basename "$1")"
    EXTENSION="${FILENAME##*.}"
    shopt -s nocasematch   # String case-insensitive comparison
    if [[ "$EXTENSION" = "asm" ]]; then
        FILENAME="${FILENAME%.*}"   # Remove extension
    fi
    UNIX_PATH="$(dirname "$1")/$FILENAME"

    # Convert forwards slashes into backslashes
    WINDOWS_PATH=$(echo "$UNIX_PATH" | tr '/' '\')

    # Assemble file
    wine ml -nologo -c -coff -Zi "$WINDOWS_PATH.asm"

    # Link files
    # Notes: Irvine's asm32.bat script includes a /DEBUG flag. I found that
    # including this flag causes a link fail:
    #   LINK : fatal error LNK1000: unknown error; consult documentation for
    #   technical support options
    # Therefore, I have omitted it. Additionally, the default entry point
    # for Wine or perhaps later versions of Windows appears to be
    # mainCRTStartup instead of main (see http://stackoverflow.com/a/12391264),
    # so we need to manually specify main as the entry point with /ENTRY.
    wine link /NOLOGO /SUBSYSTEM:CONSOLE /ENTRY:main \
        /LIBPATH:'C:\Irvine' \
        irvine32.lib kernel32.lib user32.lib "$WINDOWS_PATH.obj"

    # Run the linked executable
    wine "$WINDOWS_PATH.exe"
)

后来我为了将生成obj和exe放到一个指定的目录,我就放在C:\Irvine\bin 下面,就改写了这个profile命令

function lib()(
    set -e
    FILENAME="$(basename "$1")"
    EXTENSION="${FILENAME##*.}"
    if [[ "$EXTENSION" = "asm" ]]; then
        FILENAME="${FILENAME%.*}"   # Remove extension
    fi
    UNIX_PATH="$(dirname "$1")/$FILENAME"

    WINDOWS_PATH=$(echo "$UNIX_PATH" | tr '/' '\')

    OBJ_PATH="$(dirname "$1")/bin/$FILENAME"
    WINDOWS_OBJ_PATH=$(echo "$OBJ_PATH" | tr '/' '\')
 
    LIB_PATH="$(dirname "$1")/lib32/$FILENAME"
    WINDOWS_LIB_PATH=$(echo "$LIB_PATH" | tr '/' '\')

    # Assemble file
    wine ml -nologo -Fo "$WINDOWS_OBJ_PATH.obj"  -c -coff -Zi "$WINDOWS_PATH.asm"
    # create as lib
    lib /out:"$WINDOWS_LIB_PATH.lib"  "$WINDOWS_OBJ_PATH.obj"
)
function masm-editor()(
    WINEPREFIX=~/wine-masm wine 'C:\masm32\qeditor.exe'
)
function masm() (
    # Stop on errors
    set -e

    # Use the correct wine directory
    # export WINEPREFIX=$WINE_MASM_DIR

    # Get the path to the file without a .asm extension
    FILENAME="$(basename "$1")"
    EXTENSION="${FILENAME##*.}"
    #shopt -s nocasematch   # String case-insensitive comparison
    if [[ "$EXTENSION" = "asm" ]]; then
        FILENAME="${FILENAME%.*}"   # Remove extension
    fi
    UNIX_PATH="$(dirname "$1")/$FILENAME"

    # Convert forwards slashes into backslashes
    WINDOWS_PATH=$(echo "$UNIX_PATH" | tr '/' '\')

    OBJ_PATH="$(dirname "$1")/bin/$FILENAME"
    WINDOWS_OBJ_PATH=$(echo "$OBJ_PATH" | tr '/' '\')
     

    # Assemble file
    wine ml -nologo -Fo "$WINDOWS_OBJ_PATH.obj"  -c -coff -Zi "$WINDOWS_PATH.asm"

    # Link files
    # Notes: Irvine's asm32.bat script includes a /DEBUG flag. I found that
    # including this flag causes a link fail:
    #   LINK : fatal error LNK1000: unknown error; consult documentation for
    #   technical support options
    # Therefore, I have omitted it. Additionally, the default entry point
    # for Wine or perhaps later versions of Windows appears to be
    # mainCRTStartup instead of main (see http://stackoverflow.com/a/12391264),
    # so we need to manually specify main as the entry point with /ENTRY.
    wine link  /NOLOGO /SUBSYSTEM:CONSOLE /ENTRY:main \
        /LIBPATH:'C:\Irvine\lib32' \
        irvine32.lib kernel32.lib user32.lib "$WINDOWS_OBJ_PATH.obj" /OUT:"$WINDOWS_OBJ_PATH.exe"

    # Run the linked executable
    wine "$WINDOWS_OBJ_PATH.exe"
)

还有没有探索的就是如何debug,该环境下的DEBUG能力还不是很好,目前全靠自己思考

posted @ 2024-03-17 17:34  儿立之年  阅读(180)  评论(0)    收藏  举报