一个汇编语言程序从写出到最终执行的简要过程:

   编写--〉编译--〉连接--〉执行

我们通过一个实例来说明,代码如下:

assume cs:codesg

codesg segment

start:mov ax,0123h

      mov bx,0456h

      add ax,bx

      add ax,ax

      mov ax,4c00h

      int 21h

codesg ends

end

 

第一步:使用文本编辑器(如Edit、记事本等),用汇编语言编写汇编源程序。源程序的扩展名一般为asm,此处我们保存为1.asm.

 

第二步:下载汇编语言工具MASM7.0,版本大家可以自行选择

 

第三步:使用汇编语言编译程序对源程序文件中的源程序进行编译,产生目标文件;再用连接程序对目标文件进行连接,生成可在操作系统中直接运行的可执行文件。

 

方法如下:进入MASM,点入DOS环境(在运行中输入Command),进入MASM,输入MASM 1.asm(此处假处1.asm在当前目录下,否则需要带盘符),成功后产生1.obj

 

第四步:使用Link 1.obj,产生可执行文件1.exe。可执行文件中包含两部分内容:

程序(从原程序中的汇编指令翻译过来的机器码)和数据(源程序中定义的数据)

相关的描述信息(比如:程序有多大、要占多少内存空间等)

 

第五步:直接执行1.exe即可。

 

现在我们来详细的解说一下上面的程序:

在汇编语言中,包含两种指令,一种是汇编指令,一种是伟指令

   汇编指令

         有对应的机器码的指令,可以被编译为机器指令,最终为CPU所执行。如上代码:

      mov ax,0123h

      mov bx,0456h

      add ax,bx

      add ax,ax

      mov ax,4c00h

      int 21h

伪指令:没有对应的机器码的指令,最终不被CPU所执行。谁来执行伪指令呢?

伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。如下代码:

 

    XXX segment

   XXX ends

  end

assume

 

其中XXX segment XXX ends表示一个段,xxx表示段名,分别对应段开始和结束,一个汇编程序必须至少要有一个段,作用就好像我们在c语言中的main一样,一般一个汇编程序中不止一个段,一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当作栈空间来使用。

 

n        End 是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令 end,就结束对源程序的编译。

n        如果程序写完了,要在结尾处加上伪指令end 。否则,编译器在编译程序时,无法知道程序在何处结束。

n        注意:不要搞混了endends

 

n        assume:含义为假设

n        它假设某一段寄存器和程序中的某一个用 segment … ends 定义的段相关联。

通过assume说明这种关联,在需要的情况下 ,编译程序可以将段寄存器和某一个具体的段相联系(这里因为codesg被当作代码段来处理,所以我们需要说明:assume cs:codesg

 

现在我们来看看编译的过程(如下图):

61m.jpg

 

n        程序返回

n        我们的程序最先以汇编指令的形式存在源程序中,经编译、连接后转变为机器码,存储在可执行文件中,那么,它怎样得到运行呢?(讨论)

n        现在,我们知道,一个程序结束后,将CPU的控制权交还给使它得以运行的程序,我们称这个过程为:程序返回。

n        如何返回呢?为什么要返回呢,看下面的解释:

(1).我们在DOS中直接执行 1.exe 时,是正在运行的command1.exe中的程序加载入内存。

2command设置CPUCS:IP指向程序的第一条指令(即程序的入口)从而使程序得以运行。

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

 

上面的程序解释完毕,现在我们来看看可执行程序是如何装入内存并运行的原理:

n        1.exe的执行过程:

n        1)我们在提示符“C:\masm”后面输入可执行文件的名字“1”,按Enter键。

   问题4.1

n        21.exe中的程序运行;

n        3)运行结束,返回,再次显示提示符“C:\masm

 

n        为了观察程序的运行过程 ,我们可以使用Debug

n        Debug 可以将程序加载入内存,设置CS:IP指向程序的入口,但Debug并不放弃对CPU 的控制,这样,我们就可以使用Debug 的相关命令来单步执行程序 ,查看每条指令指令的执行结果。

 

n            接下来可以用R命令看一下各个寄存器的设置情况:

 

62m.jpg

n        可以看到,Debug将程序从可执行文件加载入内存后,cx中存放的是程序的长度。1.exe 中程序的机器码共有15个字节。

n        现在程序已从 1.exe 中装入内存,接下来我们查看一下它的内容,可是我们查看那里的内容呢?

程序被装入内存的什么地方?

我们如何得知?

DOS系统中.EXE文件中的程序的加载过程如下

 

 

63m.jpg

 

 

总结

1.程序加载后,ds中存放着程序所在内存区的段地址,这个内存区的偏移地址为 0 ,则程序所在的内存区的地址为:ds:0

2.这个内存区的前256 个字节中存放的是PSPdos用来和程序进行通信。

3. 256字节处向后的空间存放的是程序。

总结(续)

所以,我们从ds中可以得到PSP的段地址SAPSP的偏移地址为 0,则物理地址为SA×16+0。因为PSP256100H)字节,所以程序的物理地址是:

   SA×16+0+256= SA×16+16×16=SA+16)×16+0

   可用段地址和偏移地址表示为:SA+10(16的十六进制表示):0

我们用U命令分析一下结果是否正确:

64m.jpg

针对我们的总结一句句分析:

1..程序加载后,ds中存放着程序所在内存区的段地址,此处ds=129e,实际上程序所有的内存区包含两部分,一部分是psp,另一部分是程序,其中cs=129E+10=12AE,刚好与我们的分析是对应的,相关图可表示如下:

65m.JPG

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

posted on 2009-03-26 17:06  jasonM  阅读(1954)  评论(0编辑  收藏  举报