一个汇编语言程序从写出到最终执行的简要过程:
编写--〉编译--〉连接--〉执行
我们通过一个实例来说明,代码如下:
assume cs:codesg
codesg segment
start:mov ax,0123h
mov bx,0456h
add ax,bx
add ax,ax
mov ax,
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,
int 21h
伪指令:没有对应的机器码的指令,最终不被CPU所执行。谁来执行伪指令呢?
伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。如下代码:
XXX segment
XXX ends
end
assume
其中XXX segment与 XXX ends表示一个段,xxx表示段名,分别对应段开始和结束,一个汇编程序必须至少要有一个段,作用就好像我们在c语言中的main一样,一般一个汇编程序中不止一个段,一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当作栈空间来使用。
n End 是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令 end,就结束对源程序的编译。
n 如果程序写完了,要在结尾处加上伪指令end 。否则,编译器在编译程序时,无法知道程序在何处结束。
n 注意:不要搞混了end和ends。
n assume:含义为“假设”。
n 它假设某一段寄存器和程序中的某一个用 segment … ends 定义的段相关联。
通过assume说明这种关联,在需要的情况下 ,编译程序可以将段寄存器和某一个具体的段相联系(这里因为codesg被当作代码段来处理,所以我们需要说明:assume cs:codesg)
现在我们来看看编译的过程(如下图):
n 程序返回
n 我们的程序最先以汇编指令的形式存在源程序中,经编译、连接后转变为机器码,存储在可执行文件中,那么,它怎样得到运行呢?(讨论)
n 现在,我们知道,一个程序结束后,将CPU的控制权交还给使它得以运行的程序,我们称这个过程为:程序返回。
n 如何返回呢?为什么要返回呢,看下面的解释:
(1).我们在DOS中直接执行 1.exe 时,是正在运行的command将1.exe中的程序加载入内存。
(2)command设置CPU的CS:IP指向程序的第一条指令(即程序的入口)从而使程序得以运行。
(3)程序运行结束后,返回到command中,CPU继续运行command
上面的程序解释完毕,现在我们来看看可执行程序是如何装入内存并运行的原理:
n 1.exe的执行过程:
n (1)我们在提示符“C:\masm”后面输入可执行文件的名字“1”,按Enter键。
问题4.1
n (2)1.exe中的程序运行;
n (3)运行结束,返回,再次显示提示符“C:\masm
n 为了观察程序的运行过程 ,我们可以使用Debug。
n Debug 可以将程序加载入内存,设置CS:IP指向程序的入口,但Debug并不放弃对CPU 的控制,这样,我们就可以使用Debug 的相关命令来单步执行程序 ,查看每条指令指令的执行结果。
n 接下来可以用R命令看一下各个寄存器的设置情况:
n 可以看到,Debug将程序从可执行文件加载入内存后,cx中存放的是程序的长度。1.exe 中程序的机器码共有15个字节。
n 现在程序已从 1.exe 中装入内存,接下来我们查看一下它的内容,可是我们查看那里的内容呢?
程序被装入内存的什么地方?
我们如何得知?
在DOS系统中.EXE文件中的程序的加载过程如下
总结
1.程序加载后,ds中存放着程序所在内存区的段地址,这个内存区的偏移地址为 0 ,则程序所在的内存区的地址为:ds:0;
2.这个内存区的前256 个字节中存放的是PSP,dos用来和程序进行通信。
3.从 256字节处向后的空间存放的是程序。
总结(续)
所以,我们从ds中可以得到PSP的段地址SA,PSP的偏移地址为 0,则物理地址为SA×16+0。因为PSP占256(100H)字节,所以程序的物理地址是:
SA×16+0+256= SA×16+16×16=(SA+16)×16+0
可用段地址和偏移地址表示为:SA+10(16的十六进制表示):0。
我们用U命令分析一下结果是否正确:
针对我们的总结一句句分析:
1..程序加载后,ds中存放着程序所在内存区的段地址,此处ds=129e,实际上程序所有的内存区包含两部分,一部分是psp,另一部分是程序,其中cs=129E+10=12AE,刚好与我们的分析是对应的,相关图可表示如下: