前言

之前在读汇编语言_第四版 .pdf (wenjie.store),看到第二章的时候就有实操的部分了,但遗憾的是作者第4版(20年发版)的书还是用着8086的CPU,这就导致我手上的电脑无法跟着作者愉快的玩耍 (无法用公司电脑愉快摸鱼) ,于是整合了网上的一些方法,记录下如何装这个环境。

其实这篇教程在很早之前就写了,只是中间博客备案出了点问题,就丢到别的平台上了,现在才想起来有这么回事😂


使用DosBox

安装DosBox

首先先下载DosBox,选择对应的系统版本下载即可,如下图所示👇:

image.png

下载后双击打开.dmg文件,界面如下所示👇:

image.png

之后新打开一个仿达,把上面的DosBox拖进应用程序(Application)即可👇:

image.png

之后你就可以在启动台看见DosBox了👇:

image.png

这里先不启动,因为启动了之后没东西挂载,下面我们先把masm的文件都下载下来了。


下载masm文件、挂载

下载完后,将文件都放到一个目录下,我自己的电脑用的是~/test/DosBox,你也可以选择自己喜欢的目录,如下所示👇:

image.png

接着就是打开我们之前下载的DosBox,打开后如下所示👇:

image.png

接下来就是用mount命令挂载上面的~/test/DosBox目录了,这里我挂为c盘,命令如下所示👇:

image.png

  • 出现上面这个提示就说明安装成功了

然后就是类似win的命令了,我们切到C盘,查看当前目录的文件👇:

image.png

到此安装完成了,接下来试试简单的命令。


输出helloworld

在之前挂载的目录里面增加一个hello.asm,内容如下👇:

data segment
    mes db 'Hello,World!' ,0DH ,0AH ,24H
    ; 0DH : 回车
    ; 0AH : 换行
    ; 24H : '$' ,即结束符号
data ends

code segment
    ; 伪指令,告诉汇编程序段地址要放到哪个段寄存器中
    assume cs:code, ds:data

main:
    ; ds是段寄存器,无法直接赋值,需要一个寄存器过渡,这里取bx
    mov bx,data
    mov ds,bx
    ; 将mes的首地址传给dx
    mov dx,offset mes
    ; 调用9号DOS功能,即打印
    mov ah,9
    int 21h
    ; 返回DOS,退出
    mov ah,4ch
    int 21h
code ends
end main

之后执行命令:

  • MASM.EXE hello;
  • LINK.EXE hello;
  • hello

最终效果如下👇:
image.png

警告无视就好,因为我们不需要用到栈段

DosBox虽然能最大程度的还原书上的场景(有些还原不到),但如果执行过程中出现错误就比较麻烦了,因为窗口里的内容无法复制,这意味着写错什么东西需要你手动把关键信息打一遍贴到搜索引擎。


使用nasm

安装nasm

mac下执行如下命令即可:

  • brew install nasm

image.png


输出helloworld

首先是写一个hello.asm,不同于DosBox的虚拟环境,nasm是直接用mac的本地环境,所以对应代码也有比较大的变化,不过整体逻辑是相似的,这个倒可以放心。

hello.asm代码如下👇:

; 数据段
section .data
    msg db "Hello, world!", 0x0A
    len equ $ - msg
section .text

; 指定函数入口
global _main

; 系统调用封装
kernel:
    syscall
    ret

; 自定义函数(不一定要叫main,这只是个人习惯,函数名只要ld时对应就行)
_main:
        ; 4 即调用write
        ; rdi则是句柄
        ; rsi则是要输出内容的buffer
        ; rdx则是内容的长度
        mov rax, 0x2000004    ; syscall 4: write(
        mov rdi, 1            ;     fd,
        mov rsi, msg          ;     buffer,
        mov rdx, len          ;     size
        call kernel           ; )

        ; 1 即调用exit
        ; rdi可以看做返回码
        mov rax, 0x2000001    ; syscall 1: exit(
        mov rdi,0             ;     retcode
        call kernel           ; )

之后执行nasm -f macho64 -o hello.o hello.asm,编译后的.o文件在当前目录👇

image.png

下一步就是link了,这里我选择用gcc间接使用ld,执行命令gcc hello.o -e _main(警告无视就好),之后发现当前目录多了个a.out,这个最终的可执行文件👇

image.png

不直接用ld的原因是ld命令的参数在不同版本的mac可能是不一样的,见StackOverFlow的第二个回答

最后我们只需要在当前目录执行./a.out即可👇
image.png

Q.E.D.