码迷,mamicode.com
首页 > 编程语言 > 详细

汇编语言学习第四章-第一个程序

时间:2016-04-19 19:51:19      阅读:320      评论:0      收藏:0      [点我收藏+]

标签:

本博文系列参考自<<汇编语言>>第三版,作者:王爽

前面的几章中我们断断续续的学习了一些指令,但是从来没有完整的通过汇编语言编写一个可执行文件即.exe文件。从本章开始我们将开始使用汇编语言并通过编译器编译链接一个完整的可执行文件。


4.1 一个源程序从写出到执行的过程

如下图所示,为一个完整的汇编程序到执行的过程:

技术分享

上图的过程可以总结成以下几个步骤:

(1) 根据汇编语言语法规则和目标程序工程编写汇编程序。这一步在文本编辑器或者在一些IDE中编写。

(2) 通过汇编编译器将编写的汇编程序编译链接。其中编译的过程产生.obj的目标文件,再进行链接过程将.obj文件链接成可执行文        件。(可执行文件包括两个部分:一部分为程序和数据(程序为汇编语言被汇编编译器翻译成的机器码,数据为程序中定义的数      据),另外一部分为相关的描述信息(包括程序大小,程序运行需要占的内存大小))。

(3) CPU执行可执行文件的机器码。操作系统可根据可执行文件的描述信息将文件载入内存,执行第一条程序指令,比如CS:IP。


4.2 源程序

我们在dos下edit工具下写下如下图所示的一段汇编程序,并将其在C盘的根目录下保存为vpoet.asm 注意汇编源程序的后缀是asm。

技术分享

上面的程序中有三种伪指令(汇编语言中存在汇编指令和伪指令,其中汇编指令是被编译器翻译成机器指令然后由CPU执行的,而伪指令是由编译器翻译和执行的)。

伪指令

1.伪指令 xx segment

             xx  ends

   定义一个段,xx segment代表段的开始,xx  ends代表段的结束。一个汇编程序往往由多个段构成,代码段,数据段,栈段等待。这些段不是必须存在,但是往往我们将代码,数据和栈空间分开,这样有利于在程序的后期维护和管理。一个有意义的汇编程序至少存在一个段,这个段用于存放代码。


2.伪指令 end

    伪指令end代表汇编程序的技术,编译器往往在编译的时候不知道程序什么时候结束,所以就需要找到end这一伪指令来得知程序已经结束。


3.伪指令assume

    伪指令assume用于将一个段寄存器将程序中的一个段相关联,这个段的定义通过伪指令 xx segment和 xx ends来进行定义。比如我们在上面的程序中定义了一个codesg的段,然后通过 assume cs:codesg将该段与代码段相关联


源程序中的“程序”

源程序指的是整个汇编程序,但是显然汇编程序中只有汇编指令会被翻译成机器码又CPU执行的,而伪指令是不被CPU执行的,所以我们将源程序中汇编指令称为程序。程序编译链接成可执行程序,如下图所示:

技术分享

标号

汇编程序除了包括汇编指令和伪指令,还存在标号,比如codesg,这个标号代表一个段,通过assume将该标号代表的段与段寄存器相关联。在最终的编译和链接后会将该编号转换为一个段地址。


程序的返回

在上面的程序中有两行代码:

mov ax,4c00H

int 21H

这两行代码实现的功能即函数返回,那么什么是函数返回呢。函数返回即是将程序运行完成后将CPU控制权交还给调用该函数的程序。比如我们正在运行程序P1,此时我们通过P1要调用程序P2使其运行,那么P1调用P2后将CPU控制权交给P2,等待P2运行完成后程序返回将CPU控制权交还给P1。

目前已经解除过的与结束相关的指令或者伪指令:

技术分享


语法错误与逻辑错误

语法错误为程序编写的时候的语法错误,比如assume写成asume。这种错误会在编译的时候进行提示。

逻辑错误为程序逻辑上的错误,比如忘记函数返回。这种错误会在运行的时候报错。

显然语法错误易于发现和纠正,逻辑错误往往更为隐蔽。】


4.3 编译

本博文系统与王爽书中所用的编译器一致均为masm5.0。要进行编译链接,首先需要下载masm5.0编译器,然后解压即可。

现在我们将masm解压到C盘根目录下masm文件夹下。

接下来我们进入命令行,同时切换到masm目录,键入命令masm命令,结果如下图所示:

技术分享

现在我们要对C根目录下刚刚编写的汇编程序vpoet.asm进行编译:

技术分享

一直回车忽略生成列表文件.lst和交叉引用文件.crf等中间文件。当显示0 Warning Errors和0 Servere Errors则证明编译成功。

可以在masm目录下看到生成的vpoet.obj目标文件

技术分享


4.4 链接

上一小节已经得到了vpoet.obj目标文件,紧接着我们只需要通过链接便可得到vpoet.exe的可执行文件。

通过命令行还是进入masm目录下,同时输入link命令:

技术分享

一路回车,忽略映像文件.map和忽略库文件的链接。最后出现一个警告告诉我们没有栈段,这个警告可以忽略不管。


关于链接的作用:

1 当源程序很大的时候,可以将源程序分为多个源程序文件来分别编译生成目标文件,然后再将其链接到一起生成可执行文件。

2 程序中调用了某个库文件的子程序,需要将这个库文件和该程序生成的目标文件链接到一起,生成可执行文件。

3 一个源程序编译后,得到存有机器码的目标文件,目标文件中有些内容还不能直接生成可执行文件,链接程序将这些内容处理为      最终的可执行程序。


4.4 以简化的方式进行编译和链接,exe的执行

前面的编译和链接过程中会产生很多中间文件的信息。这里我们用更简单的方式编译和链接。

编译: masm 文件名.asm;(记得加分号)

技术分享

链接:link vpoet;(记得加分号)

技术分享

执行:

技术分享

执行后没有任何输出,不用怀疑,这个函数的功能本来就没有做任何输出显示。



4.8谁将可执行文件中的程序装载进入内存并使它运行?

1.在dos中直接执行vpoet.exe时,是正在运行的command 将vpoet直接载入内存中运行。

2.command设置CPU的CS:IP指向程序的第一条指令,从而使程序得以运行。

3.程序结束后,返回到command,CPU继续运行command


技术分享


4.9 程序执行过程的跟踪

现在我们将使用之前介绍过的debug调试工具对生成的vpoet.exe程序进行调试。

首先在命令行下进入vpoet.exe目录,执行命令debug vpoet.exe

技术分享

用R查看寄存器的内容:

技术分享


现在程序已经装入内存了,那么我们如何查看程序的内容呢,程序被装入内存的什么地方也是不得而知的。

下面介绍关于dos下exe的加载过程:

技术分享

(1) 程序加载后CPU段寄存器DS存储的内存的段地址,其偏移地址为0,则程序所在的内存区地址为:DS:0

(2) 该内存区的前256字节为psp区域,该区域用于向dos进行通信。从256开始才是程序的部分。

所以程序的地址为:SA+10H:0

用命令U查看指令:

技术分享

其实地址为14FC:0000 该地址如何得出的呢。由于DS=14EC 所以 14EC+10=14FC 正确了哦

另外CS=14FC IP=0000 可以得出CPU执行的第一条指令的地址为14FC:0000 该地址也是程序的起始地址,再次验证。


用命令T单步执行汇编指令 直到INT 21h 这时候需要用P执行该条指令。

这时会出现:

技术分享

表示程序已经执行完成并返回,此时通过命令q回到command。


OK,本章已经从一个完成汇编程序的角度介绍了其编译,链接以及执行等过程,累!!!

技术分享

汇编语言学习第四章-第一个程序

标签:

原文地址:http://blog.csdn.net/u013018721/article/details/51190085

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!