经过前几天的基础知识学习,我们已经对汇编指令有了一个宏观上的了解,我们学习了硬件,又学习了一些常见的指令,可是这些都无法真正的被叫做一个程序。不过不要紧,学习完今天的内容,我们就可以真正的做出我们的第一个程序。
一、一个程序的诞生过程不知道小伙伴们平时有没有想过,我们平时经常使用的一些应用软件到底是如何被制作出来的?如何做到我们只需要点击一个桌面的EXE文件就可以运行?我们是如果做到将一些只有机器认识的指令转化为大家都能够使用的软件呢?如果按照一个程序的诞生过程来讲,首先第一个步骤肯定是软件工程师们将想实现的汇编指令编写成一个指令文件。这个文件的编写只需要借助我们常用的文本编辑器(比如Edit,记事本,notepad++等等),而我们生成的文本文件的作用主要就是记录我们想要运行的汇编指令。接下来的第二个步骤,我要做的就是想办法让计算机可以认识这些汇编指令。这个时候我们就要使用汇编语言编译程序对源程序文件中的源程序进行编译,产生计算机可以识别的目标文件,接着我们还需要将目标文件关联起来,保证计算机系统可以正确的运行这些文件。第三步也就是最后我们只需要执行可执行文件中的程序即可。
(相关资料图)
总结一下:
(2)end
end和ends不同,这个小伙伴们需要注意,end主要是用来标识一个汇编程序的结束。编译器再编译汇编程序的过程中,如果碰到了伪指令end,就会结束对汇编程序的编译,因此我们在编写程序的时候,如果程序写完了,就需要在结尾处加上伪指令end,否则编译器无法感知编译工作已经结束。
(3)assumeassume再英文中有假设的含义。
1.4 程序的结构
在此之前,我们在学习指令语句的时候都是通过DOSBOS的Debug功能进行的,这样对于简短的程序确实是十分的方便,但是如果对于语句很多,逻辑很复杂的程序,显然就不能够再采取这种方式,我们需要编写一个用来编译的源程序,而相对的,这个源程序也需要有它自己的结构。
1.5 程序返回当一个程序执行结束后,我们需要通知CPU并且交还它的控制权,那么我们该如何实现呢?现阶段我们接触到的概念有三种方式与结束有关,分别是:
它在运行时其实会遇到一些问题,因为这个程序并没有设定一个返回值,当然这个问题再编译的时候是没有办法被发现的,我们没有办法说这段源码是一个错误的程序。因为它的语法是没有问题的(这里其实还有一个隐藏的问题,稍后会提到),仅是逻辑上存在一些漏洞。而相对应的,如果我再该段代码中拼错单词,比如assume codeA修改为codeB,由于程序中并没有codeB的声明,因此在编译阶段就会被编译器发现,这种就是很明显的语法错误。
2. 创建源程序的过程当我们了解完一个源程序的相关结构后,我们可以尝试的创建一个源程序出来。
2.1 编辑源程序首先我们需要有个容器来保存我们的源程序,当然不需要很复杂,我们只需要创建一个纯文本文档即可。
2.2 编译源程序(1) 编译器MASM
当我们完成源文件的编写后,我们接下来就需要将源文件编译成一个包含机器指令的目标文件。
这里我们需要一个相应的编译器,在后续的博文中我们都会指定使用masm汇编编译器,文件名为masm.exe,还没有下载的同学点击下面的链接下载。链接:https://pan.baidu.com/s/1HXkmC5rn-2DvFcIgnkKAOw 提取码:xlzb
这里讲一下编译器应该怎么用:由于masm再win10环境下不兼容,因此需要搭配DosBox一起使用,在使用前我们先讲下关于DosBox的配置文件,让我们打开DosBox:
我们来解释下这两句话是什么含义:
确认了生成的文件名后,编译器接下来询问我们编译目标文件时是否产生列表文件,这里直接回车即可
忽略了列表文件生成后,这里编译器询问我们是否产生交叉引用文件,忽略即可
修改后我们再运行一次:
此时已经运行成功了,进入对应的工作空间会发现新生成了一个OBJ后缀的文件:
2.3 连接刚刚我们完成了codeA.asm到codeA.OBJ的转变,接下来我们需要将文件进行连接,从而得到一个可以直接被执行的.exe文件。
刚刚再百度网盘中下载的文件包含了三个
其中debug和masm我们都用过了,这里将要用到的就是最后一个Link(1) 打开dosbox,输入link命令
这里我们输入想要连接的文件名
接着输入我们想要生成的目标文件名,采用默认的话回车即可:
这里是询问我们是否生成映射文件,现阶段忽略即可:
同样,这里是询问是否生成库文件,忽略即可。
到这里连接就结束了,我们还是查看工作空间,会发现一个新生成的EXE文件。
这里有一个warning警告,含义是没有栈段,忽略即可。
连接的作用这里我们简单的讲一下连接的作用:
1.当源程序很大时,可以拆分为多个源程序文件编译,每个源程序文件编译成目标文件后,可以通过连接程序将他们连接在一起,生成一个可执行文件。2.程序中调用了某个库文件中的子程序,需要将这个库文件和该程序生成的目标文件连接到一起,生成一个可执行文件。3.一个源程序编译后,得到了存有机器指令的目标文件,目标文件中的有些信息还不能直接生成可执行文件,需要连接程序将这些信息处理为最终可运行的内容,所以再只有一个源程序文件而又不需要调用其他库的时候,也必须进行连接操作。
2.4 简化编译、连接过程当然MASM和LINK也为我们提供了简化的方式:
总结一下格式就是:masm或link命令 + 文件盘符+分号。
2.5 exe可执行文件这里我们已经生成了学习到这里的第一个可执行文件:codeA.exe,很遗憾win10的操作系统还是无法直接运行它,我们依然要借助DosBox运行:
是不是很奇怪,为什么程序运行后没有任何结果,仿佛没有运行一样?其实程序肯定是运行了的,只不过我们的程序中并没有任何向显示器输出信息的指令,不过不要遗憾,随着课程的进行,我们会学到更多的指令来帮助我们完成各种各样复杂的程序。
二、补充1. exe文件与内存在我们调用可执行文件的时候,操作系统会为EXE文件本身划分一段安全的内存,这段内存仅供当前的exe文件使用。而在DOS中,可执行文件若想要执行,必须有一个正在运行的程序将其加载入内存,在上面我们运行codeA.exe的时候,就是由DosBox程序将其加载入内存,其运行结束后再将CPU的控制权交还。
2. 程序执行过程的追踪当然我们也可以通过debug程序配合运行我们的exe文件:
然后我们就可以通过Debug自身的命令来观察CPU各个寄存器的变化:
这里我们看到我们编写在源程序中的指令已经被加载进来了,接下来使用T命令执行即可,这里我就不再赘述了,感兴趣的可以查看《汇编语言 第四版》中相关描述:
3. psp内存区1.当我们启动dosbox的时候,操作系统会为它规划一段起始地址为SA:0000(即起始地址偏移量为0)的容量足够的内存区。2.这段内存区的前256个字节中,会创建一个称为程序前缀(PSP)的数据区,DOS系统需要利用PSP来和被加载进来的可执行程序进行通信。3.从PSP内存区后面,程序将会被装入,起始地址为:SA+10H:0000 ;4.将该内存区的段地址存入ds寄存器中,初始化其他相关寄存器后,将cs:ip指向程序的入口。
三、预习实验这里为了接下来的学习,需要同学们将课本中的实验三完成:
结语下一篇:最后一页
Copyright 2015-2022 亚洲日报网 版权所有 备案号:京ICP备2021034106号-51 联系邮箱:5 516 538 @qq.com