前言
进入一个全新的阶段,编写我们的第一个汇编程序,Hello World!
一个源程序从写出到执行的过程
- 一个汇编语言程序从写出到最终执行的简要过程: 编写 -> 编译连接 -> 执行
- 对源程序进行编译连接:
- 使用汇编语言编译程序(MASM.EXE)对源程序文件中的源程序进行编译,产生目标文件【.obj文件】
- 再用连接程序(LINK.EXE)对目标文件进行连接,生成可在操作系统中直接运行的可执行文件【.EXE文件】
- 可执行文件包含两部分内容:
- 程序(从源程序的汇编指令翻译过来的机器码)和数据(源程序中定义的数据);
- 相关的描述信息(比如:程序有多大、要占多少内存空间等);
- 执行可执行文件中的程序:
- 在操作系统(如:MSDOS)中,执行可执行文件中的程序;
- 操作系统依照可执行文件中的描述信息,将可执行文件中的机器码和数据加载入内存,并进行相关的初始化(比如:设置 CS:IP 指向第一条要执行的指令),然后由 CPU 执行程序;
源程序的主要结构
源程序由“ 汇编指令+伪指令+宏指令 ”组成: 伪指令:编译器处理; 汇编指令:编译为机器码;
伪指令:
- 没有对应的机器码的指令,不能由 CPU 直接执行;
- 伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作;
segment 和 ends【定义一个段】
segment 和 ends 是一对成对使用的伪指令;
编写汇编程序【必须】使用到的指令;
segment 和 ends 的功能是定义一个段:
- segment:说明一个段开始;
- ends:说明一个段结束;
一个段必须有一个名称来标识,使用格式为
一个汇编程序由多个段组成: 这些段用来存放【代码,数据或当作栈空间】来使用,一个有意义的汇编程序至少要有一个段,这个段用来存放代码。
end【真正的没了】
- end 是一个汇编程序的结束标记;
- 编译器在编译汇编程序的过程中,如果碰到了伪指令 end,就结束对源程序的编译;
- 如果程序写完了,要在结尾处加上伪指令 end,否则,编译器无法知道程序在何处结束;
- 【切记】不要把 end 和 ends 搞混了!
- end:汇编程序的结束标记;
- ends:与 segment 成对出现,表示一个段结束;
assume【寄存器和段的关联假设】
- 它假设某一段寄存器和程序中的某一个用 segment...ends 定义的段相关联;
- 通过 assume 说明这种关联,在需要的情况下,编译程序可以将段寄存器和某一具体的段相联系;
程序和源程序
- 我们将源程序文件中的所有内容称为【源程序】
- 将源程序中最终由计算机执行处理的指令或数据称为【程序】
- 程序最先以汇编指令的形式,存储在源程序中,然后经过编译、连接后转变为机器码,存储在可执行文件中;
标号,标号与段名称有所区别:
- 一个标号指代了一个地址,即是段名称,类似指针。
- 段名称(codesg)放在 segment 的前面,作为一个段的名称,这个段的名称最终将被汇编、连接程序处理为一个段的段地址;
任务:编程运算 23;
assume cs:abc
abc segment
mov ax,2
add ax,ax
add ax,ax
abc ends
end
DOS 中的程序运行:
- DOS 是一个单任务操作系统: 1) 一个程序 P2 在可执行文件中,则必须有一个正在运行的程序 P1,将 P2 从可执行文件中加载入内存后,将 CPU 的控制权交给 P2,P2 才能得以运行。P2 开始运行后,P1 暂停运行。 2) 而当 P2 运行完毕后,应该将 CPU 的控制权交还给使它得以运行的程序 P1,此后,P1 继续运行。
- 一个程序结束后,将 CPU 的控制权交还给是他得以运行的程序,称这个过程为:程序返回;
程序返回 应该在程序的末尾添加返回的程序段。
【中断机制】是 DOS 最伟大的机制,Windows 系统上是【消息机制】,这两条指令所实现的功能就是程序返回;
几个和结束相关的内容:
段结束:伪指令 通知编译器一个段的结束【ends】
程序结束:伪指令 通知编译器程序的结束【end】
程序返回:汇编指令
语法错误和逻辑错误:
- 语法错误
- 程序在编译时被编译器发现的错误;
- 容易发现;
- 逻辑错误
- 在编写时不会表现出来的错误、在运行时会发生的错误;
- 不容易发现;
以简化的方式进行汇编和连接
汇编使用的程序:masm.exe 连接使用的程序:link.exe 简化方式进行汇编和连接的程序:ml.exe
MASM下载链接,提取码:gd2c;
跟之前 汇编(三):DEBUG 中提到的操作一样,修改配置文件,自动挂载 MASM 目录,可以输入 dir
进行验证;
编写一个 Hello World 程序:
.model small
.data
strs DB 'hello world',13,10,'$'
.code
start:
mov ax,@data
mov ds,ax
mov dx,offset strs
mov ah,09h
int 21h
mov ah,4ch
int 21h
end start
先复制到 txt 文本中,然后将后缀改成 asm,使用 masm 1.asm
命令进行汇编;
然后通过 link 1.obj
进行链接;
最后执行所生成的 exe 文件;
汇编和连接的作用
连接的作用:
- 当源程序很大时,可以将他们分成多个源程序文件夹编译,每个源程序编译成为目标文件后,再用连接程序将它们连接在一起,生成一个可执行文件;
- 程序中调用了某个库文件中的子程序,需要将这个库文件和该程序生成的目标文件连接到一起,生成一个可执行文件;
- 一个源程序编译后,得到了存有机器码的目标文件,目标文件中的有些内容还不能直接用来生成可执行文件,连接程序将这些内容处理为最终的可执行信息。所以在只有一个源程序文件,而又不需要调用某个库中的子程序的情况下,也必须用连接程序对目标文件进行处理,生成可执行文件;
可执行文件中的程序装入内存并运行的原理
- 在 DOS 中,可执行文件中的程序 P1 若要运行,必须有一个正在运行的程序 P2,将 P1 从可执行文件中加载入内存,将 CP U的控制权交给P1,P1 才能得以运行;
- 当 P1 运行完毕后,应该将 CPU 的控制权交还给使他得以运行的程序;
- 操作系统的外壳:
- 操作系统是由多个功能模块组成的庞大、复杂的软件系统,任何通用的操作系统,都需要提供一个称为 shell(外壳)的程序,用户(操作人员)使用这个程序来操作计算机系统工作;
- DOS 中有一个程序 command.com,这个程序在 DOS 中称为命令解释器,也就是 DOS 系统的 shell;
- 执行可执行文件 1.exe 时, (1)什么程序将 CPU 的控制权交给了 1.exe? (2)将程序 1.exe 加载入内存后,如何使程序得以运行? (3)1.exe 程序运行结束后,返回到了哪里?
- 在 DOS 中直接执行 1.exe 时,是正在运行的 cmd.exe 将 1.exe 中的程序加载入内存;
- cmd.exe 设置 CPU 的 CS:IP 指向程序的第一条指令(即,程序的入口),从而使程序得以运行;
- 程序运行结束后,返回 cmd.exe 中,CPU 继续运行 cmd.exe;
汇编程序从写出到执行的过程:
EXE文件中的程序的加载过程
- 程序加载后,ds 中存放着程序所在内存区的段地址,这个内存区的偏移地址为 0 ,则程序所在的内存区的地址为:
ds:0
;
- 这个内存区的前256个字节中存放的是 PSP,dos 用来和程序进行通信。
- 从 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:0。