汇编学习教程:开发第一步

引言

此前我们详细讲述了有关内存访问、CPU相关知识、寄存器相关等等,而这些的目的最终都是为了实战开发而准备的。从本片博文开始,我们将正式进入开发相关的学习,相信大家已经急不可耐了,准备一腔热血写代码。

首先,我们先定个“小目标”。本篇博文的学习目标为:

1、搭建汇编开发环境

2、编写并熟悉第一个程序

好了,那么就让我们尽快开始本篇的学习吧~

环境搭建

和其他语言开发一样,首先要做的工作就是开发环境搭建,汇编语言也不例外。我们学习的x86汇编,由于它是运行在16位CPU上,所以我们开发工作还是离不开DOSBox,由DOSBox为我们提供程序的运行环境。DOSBox的环境搭建,我们此前在学习Debug那篇中已经学习过了,这里就不再进行讲述,有遗忘的小伙伴可以翻看我们此前的博文进行学习。

使用Notepad++

DOSBox只是为我们提供了程序可运行环境,它并不承当程序的编写、编译等环节,那么接下来我们就开始介绍汇编开发工具:Notepad++。

Notepad++它表面上就是一个文档编辑器,但是它实际上却是一个代码编写工具!我们还记得使用记事本写Java代码么?没错,就是这种感觉!不过Notepad++功能可要比电脑自带的记事本强大的多。

网上还有别人推荐使用 VS Code,博主实地使用VS Code体验了一番,指令书写上VS Code要比Notepad++体验要好,而且可安装DOSBox插件实现一键编译运行操作。但是在整体使用习惯上,博主本人本不适应,没有Notepad++来的直接和方便,所以博主便放弃了VS Code。不过这个东西毕竟因人而异,小伙伴们可自行进行选择,自己舒服就好。

Nodepad++下载安装非常的便捷方便,老规矩,这里放出下载地址:Notepad++下载,点击进入:

 点击 Free Download 下载即可。由于下载安装过程非常简单无脑,所以这里博主就不再详细图文说明了。

MASM工具

和Debug工具一样,masm工具也是一个运行在16位操作系统的程序,该工具的作用是将汇编源代码文件(.asm)编译成为一个 .obj 文件。什么是 .obj文件?全称Object,它就是程序编译后的二进制文件,此时系统还无法执行。由于它还需要进一步操作才能生成可执行文件(就是我们熟知的.exe),所以它又被称为“中间文件”。

代码被编译运行的过程如下:

代码源文件(.asm)---->中间文件(.obj)---->可执行文件(.exe)

我们在做高级语言开发的时候,基本上遇不到 .obj文件,那是因为强大的编译器已经帮我们处理好了一切,一气呵成将代码生成了可执行文件,所以我们接触最多的就是代码源文件和最后的可执行文件,中间文件的处理过程由编译器做了,不需要人工参与。

但是汇编开发中,由于没有非常强大的一气呵成的编译器,所以我们会在代码编译后遇到中间文件。

LINK工具

和masm工具一样,link工具也是运行在16位操作系统的程序,该工具的作用就是将中间文件(.obj)生成最终的可执行文件(.exe)。

上面我们明白了代码被编译运行的过程,也就是说,我们想运行我们的程序,首先就需要将程序的源代码通过masm工具编译,然后使用link工具将编译成生的中间文件加工成可执行文件,这样我们的程序得以运行。

那么万事俱备,只欠东风,哪里才能得到msam工具和link工具呢?

别急,老规矩,博主这里贴出一个下载链接:工具下载

下载完成后找到压缩包路径下的/masm/下:

我们使用到的就是图中:MASM.EXE、LINK.EXE 这两个程序。将这两个程序加压出来,放到我们需要的目录下,博主这里为:

 OK,这样就已经完成我们开发所需的环境搭建啦,只不过是下了两个工具而已,是不是非常的简单呢!

程序开发

现在我们已经有了MASM工具和LINK工具,也就意味着我们在代码编译、运行环节已经完成,那么就要进入到编写代码环节了。

首先我们在工具存在的路径下(D:/DOSBoxStudy/)创建一个文件,文件后缀为:.asm:

 然后右键,选择在Nodepad++中打开:

 好了,现在我们就开始正式写代码了!

现在我们将开始写第一个汇编代码,将下面的代码写在s1.asm文件内:

assume cs:code

code segment
    
    mov ax,0123H
    mov bx,0456H
    add ax,bx
    add ax,ax

    mov ax,4c00H
    int 21H

code ends
end

 写完之后,我们按 Ctrl+S 保存一下文件即可。

我们会发现Nodepad++会通过识别文件的后缀,自动的适配相应的格式,比如这里我们的文件是.asm,那么Nodepadd++就会自动把当前展示字符语言调整为Assembly,这样一些关键字和伪指令就能显示不同的颜色,进行醒目提示。

伪指令

在Nodepad++中,显示为蓝色的就是伪指令,上述代码中共有四个伪指令,分别是:assumesegmentendsend

伪指令就是编译器所识别的指令,机器(CPU)并不识别,比如我们C语言中开头第一个伪指令 include,本质就是告诉编译器要做什么样的工作。

Assume

assume翻译成中文的意思就是“假设”,这里它的作用就是定义一个段。段就是指代码段(CS)、栈段(SS)、数据段(DS)、预留段(ES)。

上述代码中

assume cs:code

意思为:定义一个代码段,代码段的标号为:code

也就是说,在程序中,我们可以使用code来表示代码段。这个标号仅仅是一个名字用来代指代码段,它可以是另外任意字符。不一定非要是 cs:code。

不过按照开发规范,建议代码段的标号尽量使用code或者其他意思为"代码"的英文单词,这样在程序中我们比较容易识别。

之前我们说过,一个程序中最重要的就是代码,所以在汇编开发中代码段一定要定义(重要),要不然你告诉我你的代码放在哪里!

通过assume 伪指令,编译器就知道了该程序中定义了几个段,都是什么段,段的名字叫什么等等关键信息。

Segment

segment就是段的意思,这里segment伪指令的作用就是标示一个段的开始。这个段可以是代码段、数据段、栈段、预留段。格式为:xxx segment,xxx为assume中定义的段的标号。

上述代码中

code segment

意思为:标号为code的段从这里开始。code,就是伪指令assume 中定义的代码段CS的标号。

注意,这里标号一定要和assume中定义的标号保持一致,否则编译器将无法准确识别段的开始。

通过segment伪指令,编译器就能知道某个段的开始位置,这样对不同的段进行针对性编译。

Ends

ends实际上是end segment的缩写,这里ends伪指令的作用就是标示一个段的结束。段可以是代码段、数据段、栈段、预留段。格式为:xxx ends,xxx为assume中定义的段的标号。

上述代码中

code ends

意思为:标号为code的段从这里结束。code,就是伪指令assume 中定义的代码段CS的标号。

注意:

1、标号要和assume中定义的标号保持一致

2、segment和ends这两个伪指令是成对出现的,切记在开发中不要漏掉了其中某一个。

 通过ends伪指令,编译器就能知道某个段的结束位置,这样就能停止某段的编译。

 end

end伪指令的作用就是表示整个汇编程序的结束,编译器在编译汇编程序的时候,如果碰到了伪指令end,那么就会结束对源程序的编译。所以,我们在写汇编代码的时候,一定要记得在最后加上end。

源程序中的“程序”

这个标题猛的一看上去有点绕口,源程序中的“程序”,这是怎么个意思呢?

要想搞清楚,首先我们要分开来看。源程序是指我们.asm文件中的代码程序,这个程序实际上是给编译器看的,由编译器去执行,里面包含了一些只有编译器才能看的懂的伪指令和关键字。

而这个“程序”,是指真正机器可执行的部分:那就是将源程序去除伪指令去除关键字后,剩下的汇编指令,才是真正意义上的程序。

在源程序中,我们定义了一个代码段,然后将CPU需要执行的汇编指令写在代码段里,然后交给编译器,编译器会通过segment、ends这两个伪指令识别到汇编指令在源程序中的数据范围,将汇编指令编译为其对应的机器码,这样才能交给CPU去执行。

上述汇编程序示例中,code segment、code ends之间,就是具体CPU需要执行的汇编指令:

    mov ax,0123H
    mov bx,0456H
    add ax,bx
    add ax,ax

    mov ax,4c00H
    int 21H

这里重新总结下:

1、源程序是指源程序文件中的所有内容,包含伪指令、关键字、汇编指令

2、程序是指源程序中,最终由计算机执行、处理的指令或数据。这里可以认为源程序中写在代码段内的数据,就是程序。

3、程序最先以汇编指令的形式存在源程序中,经编译、连接后转变为机器码,存储在可执行文件中(.exe) 

下图展示了源程序与程序之间的关系:

标号

在上面的讲述中,我们有提到标号,例如在示例代码中:code,它是CS代码段的标号。标号的作用就是在源代码中代指某一处地址,例如标号code,它就代指了CS代码段的段地址。

标号存在的目的就是为了增强汇编代码的可读性,同时也降低了汇编开发复杂性。试想一下,如果没有标号,那么你就要手写上一个个地址,这样非常容易代码书写错误。

CPU也是不认识标号的,所以标号最终将会被编译程序(masm.exe)、连接程序(link.exe)处理为对应的内存地址,供CPU进行访问操作。

程序返回

不管什么语言开发的程序,必定存在一个最终程序返回,在高级语言中例如C语言,使用return 0来表示程序执行完毕返回。返回,是指回到调用这个程序的程序处,通常是指返回操作系统。

汇编语言当然也有程序的结束返回处理,那就是示例代码中:

mov ax,4c00H

int 21H

这两条汇编语句就相当于C语言的return 0,执行完这两条语句后,本次程序的运行将会结束,控制权返回操作系统中。

这两条汇编语句是固定形式,必须这样写才能确保本次程序结束运行并返回。为什么就非要是这两两条汇编语句呢?现阶段我们先不进行深入的探讨研究,因为这涉及到比较广阔的知识面。我们先务必牢记,在汇编开发中,程序的最后一定要写上这两条汇编指令才能正确返回。

语法错误

在Nodepad++中编写汇编指令,如果你的语法一不小心写错了,比如MOV指令你写成了MAV,那么Nodepad++将会无法显示出对应正确的字体颜色,这样相当于给我们提示出现了语法错误。

此外,如果你的汇编代码中存在语法错误,那么在使用masm工具进行编译时,masm也会提示错误。

除了语法错误,还有逻辑错误,这个错误说白了就是Bug了,需要你实际运行后发现并逐步进行调试才能发现。

本篇结束语

在本篇博文中,我们圆满完成学习目标!主要学习了汇编开发环境搭建,并且通过第一个代码示例,我们学习了源程序组成,包括伪指令、标号和汇编指令。明确了源程序和程序之间的区分,以及在汇编开发中如何正确返回。

在下篇博文中,我们将学习如何使用MASM工具和LINK工具对源代码进行编译和连接,以及如何运行生成的可执行文件。

感谢围观,转发分享请标明出处,谢谢!

  • 12
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值