【王爽《汇编语言(第4版)》笔记】第4章:第一个程序

第4章 第一个程序

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

第一步:编写汇编源程序

结果:产生了一个存储源程序的文本文件。

使用文本编辑器,用汇编语言编写汇编源程序。

第二步:对源程序进行编译连接。

结果:产生了一个可在操作系统中运行的可执行文件。

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

2、可执行文件的组成:

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

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

第三步:执行可执行文件中的程序。

操作系统依照可执行文件中的描述信息,将可执行文件中的机器码和数据加载入内存,并进行相关的初始化(比如设置CS:IP指向第一条要执行的指令),然后由CPU执行程序。

4.2 源程序

// 程序4.1
assume cs:codesg // 伪指令:将用作代码段的段codesg与CPU种的段寄存器cs联系起来
codesg segment // 伪指令:定义一个段,段的名称为"codesg",这个段从此开始,是个代码段
    // 5~11行为汇编指令:
		mov ax, 0123H 
		mov bx, 0456H
		add ax, bx
		add ax, ax
	// 程序返回:
		mov ax, 4c00H 
		int 21H
codesg ends // 伪指令:名称为"codesg"的段到此结束
end // 伪指令:
4.2.1 伪指令

1、在汇编语言的源程序中包含两种指令:汇编指令伪指令

(1)汇编指令:有对应机器码的指令可以被编译为机器指令最终被CPU所执行

(2)伪指令:没有对应的机器指令最终不被CPU所执行;伪指令由编译器执行,编译器根据伪指令来进行相关的编译工作。

2、伪指令的种类:

第一种:segment…ends

segment和ends的功能是定义一个段,segment说明一个段开始,ends说明一个段结束。

段名 segment
...
段名 ends

(1)segment和ends是一对成对使用的伪指令。

(2)segment和ends是在写可被编译器编译的汇编程序时,必须用到的一对伪指令。

(3)一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当作栈空间来使用。

(4)一个有意义的汇编程序中至少要有一个代码段

第二种:end

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

(1)写完程序要在结尾处加上伪指令end。否则编译器不知道程序在何处结束。

(2)区分end和ends:ends与segment成对使用,标记一个段的结束,ends可以理解为end segment;而end的作用是标记整个程序的结束。

第三种:assume

伪指令assume的含义是“假设”。它假设某一段寄存器和程序中的某一个用segment…ends定义的段相关联。

通过assume可以使编译程序将段寄存器和某一个具体的段相联系

4.2.2 源程序中的“程序”

源程序中的“程序”指源程序中最终由计算机执行、处理的指令或数据

源程序源程序文件中的所有内容

程序最先以汇编指令的形式存在源程序中,经编译、连接后转变为机器码,存储在可执行文件中,过程如图:
在这里插入图片描述

4.2.3 标号

一个标号指代了一个地址

程序4.1中"codesg"就是一个标号,codesg在segment前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段的段地址

4.2.4 程序的结构
// 程序4.2:计算2的立方
assume cs:abc // (4)abc被当作代码段来用,所以应该将abc和cs联系起来
abc segment // (1)定义一个段,名称为abc,与结尾abc ends搭配使用
    // (2)在这个段中写入汇编指令
    mov ax, 2  
    add ax, ax
    add ax, ax
    // (5)程序返回
    mov ax, 4c00H
    int 21H
abc ends
end // (3)指出程序在何处结束
4.2.5 程序返回

Q:程序如何得到运行?

1、程序运行过程:在DOS(一个单任务操作系统)的基础上讨论

(1)一个程序P2在可执行文件中,则必须有一个正在运行的程序P1,将P2从可执行文件中加载入内存后,将CPU的控制权交给P2,P2才能得以运行;

(2)P2开始运行后,P1暂停运行;

(3)P2运行完毕后,将CPU的控制权交还给P1;

(4)P1继续运行。

2、程序返回:指一个程序结束后将CPU的控制权交还给使它得以运行的程序的过程。

3、应该在程序的末尾添加返回的程序段,是汇编指令

// 程序返回指令举例,本章暂时只需要记忆这两条指令即可
mov ax, 4c00H
int 21H // 必须输入H才能通过,int可以理解为interrupt
4.2.6 语法错误与逻辑错误

1、语法错误:程序在编译时被编译器发现的错误。

2、逻辑错误:在源程序编译后,运行时发生的错误。

3、语法错误容易发现,容易解决;逻辑错误通常不容易被发现。

4.2.7 与结束相关的概念总结
目的相关指令指令性质指令执行者
通知编译器一个段结束段名 ends伪指令编译时,由编译器执行
通知编译器程序结束end伪指令编译时,由编译器执行
程序返回mov ax,4c00H int 21H汇编指令执行时,由CPU执行

4.3 编辑源程序

程序4.1为例,在任意文本编辑器中编辑源程序,保存为1.asm

4.4 编译

4.4.1 Dosbox的配置

Win10下,在Dosbox的配置文件末尾添加如下代码:
在这里插入图片描述

MOUNT D D:\code\Assembly\Dosbox // 挂载到D盘
D: // 进入D盘
// D:\code\Assembly\Dosbox目录下应有debug.exe、masm.exe等工具
4.4.2 编译过程

1、使用Dosbox运行masm.exe,显示出版本信息。

2、输入.asm文件的名称(不输入扩展名),与masm.exe同目录则只输入名称,不同目录则输入路径。

3、可选修改输出的目标文件的名称,不修改则直接按Enter。

4、两个生成中间文件的过程,按Enter跳过。
在这里插入图片描述

如果输入文件路径,也不需要后缀名。

如D:\code\Assembly\codes\1  不写1.asm
4.4.3 编译注意事项

1、有两类错误使我们不能得到所期望的目标文件:

(1)程序中有"Severe Errors";

(2)找不到所给出的源程序文件。

2、编译过程中,最多可以得到3个输出:目标文件(.obj)、列表文件(.lst)、交叉引用文件(.crf)。

(1)目标文件使我们最终要得到的结果;

(2)列表文件、交叉引用文件是中间结果,可以让编译器忽略其生成,本课程不讨论这两类文件。

4.5 连接

4.5.1 连接的过程

1、使用Dosbox运行link.exe

2、输入要连接的.obj文件名(不输入扩展名),与link.exe同目录则只输入名称,不同目录则输入路径。

3、可选修改要得到的可执行文件的名称,不修改则直接Enter。

4、中间文件,可选择不生成,按Enter直接跳过。

5、提示输入库文件的名称,本程序没有调用库文件中的子程序,因此直接Enter键跳过。

库文件中包含了一些可以调用的子程序,若程序调用了库文件中的子程序,就要在连接的时候将这个库文件和目标文件连接到一起,生成可执行文件。

在这里插入图片描述

4.5.2 连接的作用

连接的最终结果:得到可执行文件。

1、当源程序很大时,可以分为多个源程序来编译,每个源程序编译成目标文件后,再用连接程序将其连接到一起,生成一个可执行文件。

2、若程序调用了库文件中的子程序,就要在连接的时候将这个库文件和目标文件连接到一起,生成可执行文件。

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

4.6 以简化的方式进行编译和连接

1、以简化的方式进行编译1.asm结尾加上分号,如图所示,则自动忽略中间文件的生成,在当前目录下得到1.obj
在这里插入图片描述

2、以简化的方式进行连接1.obj结尾加上分号,如图所示,则自动忽略中间文件的生成,在当前目录下得到1.exe
在这里插入图片描述

4.7 1.exe的执行

在这里插入图片描述

程序运行了,但是在屏幕上看不到任何运行结果,是因为该程序(程序4.1)并不向显示器输出任何信息。

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

操作系统的外壳: 任何通用的操作系统,都要提供一个称为 shell(外壳) 的程序,用户使用这个程序来操作计算机系统进行工作。DOS中有一个程序command.com(类似于cmd.exe)是DOS系统的shell。

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

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

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

汇编程序从写出到执行的过程:编程(Edit)-1.asm-编译(masm)-1.obj-连接(link)-1.exe-加载(command)-内存中的程序-运行(CPU)。

4.9 程序执行过程的跟踪

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

4.9.1 Debug操作步骤

1、输入debug 1.exe1.exe加载入内存,进行相关初始化后设置CS:IP指向程序的入口。
在这里插入图片描述

2、使用R命令查看各个寄存器的设置情况。

(1)cx中存放的是程序的长度1.exe中程序的机器码共有15个字节,因此cx为000FH。

(2)从ds中得到PSP(程序段前缀)的段地址SA,PSP[见4.9.2]的偏移地址为0,则物理地址为SA×16+0。
在这里插入图片描述
3、使用U命令查看其他指令。
在这里插入图片描述

4、使用T命令单步执行程序中的每一条指令,并观察每条指令的执行结果,到了int 21H要使用P命令执行int 21H执行后,显示出Program terminated normally,返回到Debug中,表示程序正常结束。
在这里插入图片描述

5、使用Q命令退出Debug,将返回到command中,因为Debug是由command加载运行的

4.9.2 DOS系统中.exe程序加载过程

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

2、这个内存区的前256个字节中存放的是PSP(程序段前缀),DOS用来与程序进行通信。从256字节处向后的空间存放的是程序。
在这里插入图片描述

4.9.3 程序的加载与返回顺序

在DOS中用debug 1.exe运行Debug对1.exe进行跟踪时:

1、程序加载的顺序:command加载Debug,Debug加载1.exe

2、返回的顺序:从1.exe中的程序返回到Debug,从Debug返回到command。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值