[汇编] 程序简述,bx/loop 指令

目录

程序简述

源程序示例:

伪指令

关于程序返回

BX和LOOP

BX

LOOP

段前缀

一段安全的空间

包含多个段的程序

dosbox

dos程序运行 

程序加载过程(exe)

一个好习惯


程序简述

之前聊寄存器和内存的一些事情,是在debug调试模式下写一些指令。下面我们简单看看编写完整的汇编语言程序是个怎样的过程。

源程序示例:

assume cs:codesgcodesg segment            mov ax,0123h            mov bx,0456h            add ax,bx            add ax,ax            mov ax,4c00h            int 21hcodesg endsend

源程序里有两种指令,一种是汇编指令/机器指令,由CPU执行;

                                    另一种是伪指令,由编译器识别。

伪指令

在上面的源码中出现了3类:

① 

XXX 段名   segmentXXX 段名   ends

segment 和 ends 是成对使用的伪指令,来定义一个段。前者表示段的开始,后者表示段的结束。当然定义一个段一定要有名字。

end  汇编程序结束标志

与ends(end segment)区分开

③assume:将有特定用途的和相关的段寄存器关联起来

上述程序中的 assume cs(寄存器名):codesg(段名) 就是把一个代码段和段寄存器联系起来了。

源程序和程序:

这里有必要区分,即:

源程序文件中的所有内容共同成为源程序,而最终由计算机执行处理的指令、数据则称为 程序。

所以两者的关键在于伪指令的包括与否。

(程序首先是源程序中的汇编指令,之后转变为机器码存在.exe可执行文件中)

关于标号:

上面的栈名 codesg实际上作为一个栈的名称,从内存角度看 指代了一个地址,我们称之为标号。

源程序是由一个个段组成的。

关于程序返回

 对于DOS,这样一个单任务操作系统,一个程序的运行可以概括如下:

一个程序P2在可执行文件中要想运行,就必须有一个正在运行的程序P1,让P1将P2从可执行文件中加载进入内存,再由P1将CPU控制权交给P2,P2得以运行,P1暂停运行。

P2运行完毕,CPU控制权还给P1,P1继续运行。

上述程序结束,交还CPU控制权的过程,我们称为 程序返回。

这在上述源程序中体现为:

         mov ax,4c00h         int 21h

作为汇编指令,由CPU执行。这和end/ends 两个伪指令是完全不同的。

——————————————————————————————

BX和LOOP

BX

我们知道,要完整表示一个内存单元,需要两种信息:

①内存单元的地址 ②内存单元的长度(这一点通常由类型可知)

BX本身作为一个寄存器,存储着数据,而

[BX]就表示一个内存单元,它的偏移地址在BX中,配合段地址在段寄存器ds中。

所以操作的内存空间即起始地址为DS:BX,长度为数据类型

eg:

mov ax , [bx]

LOOP

就是一循环语句。

只是循环次数由寄存器CX里的值是否为0决定,所以我们循环前要给cx赋值。

我们直接来看它的格式:

mov cx , 次数 s:     循环语句loop s#这里的S只是一个循环标识符,代表地址。你可以另行命名

段前缀

汇编指令里,我们可以显式的指明内存单元的段地址,像DS: CS: SS: ES:

这些称之为段前缀。

段前缀可以配合不同寄存器,简化很多涉及到不同段地址的代码。

一段安全的空间

0:200~02ff 没系统/程序数据。

——————————————————————————————

dosbox

dos程序运行 

注意,一段代码指令的运行,有debug和汇编编译器masm两种处理方式。

debug是我们通过-a逐步填写的。

masm则是提前编辑好汇编指令txt文件去编译处理。

1.像masm模式下,十六进制数据后要加H,而debug则直接用数字表示;

2.汇编源程序里,数据不能以字母开头。像FFFF这样的数据,前面要加上数字0。 

debug则不然

3.对于同样的 mov bl,[idata] ,debug视 [idata] 为内存单元 DS:IDATA;masm则直接认为[idata]为一个常量idata了。

(当然,masm模式下指代内存单元,前面要加上ds,即ds:[idata])

关于操作系统的外壳 shell

操作系统通常提供一个shell程序,让用户能够利用它操作计算机系统 进行工作。

对于DOS,它的shell是command.com,称为命令解释器。

Dos启动,先初始化,然后运行command.com。运行完毕,由command.com在屏幕上显示盘符和当前路径组成的提示符,等待用户输入。用户输入的所有指令由command执行。

执行过程需要的文件也由command处理。

注意:

1.这里的shell — command.com内容和上面的DOS单任务操作系统的程序运行可以相互补充来看。

2.COMMAND往往充当程序P1的身份,同时COMMOND也负责程序运行过程中,设置CPU的CS:IP指向程序入口(程序的第一条指令),使该程序正常运行。

3.debug模式下,command会加载运行debug,由debug负责加载运行用户程序的一些工作。

一个源程序从写出到执行要经历 的过程:

编写源程序(txt→asm)——编译(asm→obj)——连接(obj→exe)——生成exe可执行文件(程序)

涉及到 编译指令 masm + 被编译asm文件 ,连接指令 link  +被连接obj文件

拓展

中间会有很多中间文件:

source listing [NUL.LST] : 列表文件

cross-reference[NUL.CRF]:交叉引用文件

List File [NUL.MAP]:映像文件 

Libraries[.LIB]:提示输入库文件名称

(如果程序调用了某一库文件子程序,需要在连接时将该库文件和目标文件连接在一起)

这些目标文件在非必要情况下可以直接ENTER 跳过。

中间过程的所有文件(包括目标文件)都可以指定名称甚至路径。

程序加载过程(exe)

1.找一段起始地址SA:0000的容量足够的空闲内存。

2.在该内存区前256字节中,创建一个PSP(程序段前缀)的数据区。DOS利用PSP和被加载的程序进行通信。

3.在该内存区PSP后(256字节处)装入程序。程序起始地址:SA+10H:0

(PSP区和程序区物理地址连续,但是段地址截然不同)

这里有一步重定位工作没有讲解,不讨论。

一个好习惯

把内存单元里的数据存放在某个寄存器DX中,要考虑以下基本问题:

1.运算后的结果是否超出寄存器dx 所能存储的范围?

2.我们能否将该内存单元中的数据直接累加到dx中?

3.内存单元和寄存器之间的数据类型是否匹配?

即,结果大小的越界和数据类型的匹配 问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值