第一个汇编程序「建议收藏」

第一个汇编程序「建议收藏」本文将开始编写完整的汇编语言程序,用编译器将它们编译成为可执行文件(如:*.exe文件),在操作系统中运行。本文地址:http://www.cnblogs.com/archimedes/p/assem

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

本文将开始编写完整的汇编语言程序,用编译器将它们编译成为可执行文件(如:*.exe文件),在操作系统中运行。

本文地址:http://www.cnblogs.com/archimedes/p/assembly-first-program.html,转载请注明源地址。

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

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

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

使用文本编辑器(如Edit、记事本等),用汇编语言编写汇编源程序。
使用汇编语言编译程序对源程序文件中的源程序进行编译,产生目标文件;再用连接程序对目标文件进行连接,生成可在操作系统中直接运行的可执行文件。
可执行文件中包含两部分内容:
程序(从原程序中的汇编指令翻译过来的机器码)和数据(源程序中定义的数据)
相关的描述信息(比如:程序有多大、要占多少内存空间等)
在操作系统中,执行可执行文件中的程序。
操作系统依照可执行文件中的描述信息,将可执行文件中的机器码和数据加载入内存,并进行相关的初始化(比如:设置CS:IP指向第一条要执行的指令),然后由CPU执行程序。

2、源程序

先看一段代码:

assum 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

segment和ends是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指令。
segment和ends的功能是定义一个段,segment说明一个段开始,ends 说明一个段结束。
一个段必须有一个名称来标识,使用格式为:

段名 segment

段名 ends

一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当作栈空间来使用。一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。
end 是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令 end,就结束对源程序的编译。如果程序写完了,要在结尾处加上伪指令end 。否则,编译器在编译程序时,无法知道程序在何处结束。
注意:不要搞混了end和ends。
nassume:含义为“假设”。它假设某一段寄存器和程序中的某一个用 segment … ends 定义的段相关联。通过assume说明这种关联,在需要的情况下 ,编译程序可以将段寄存器和某一个具体的段相联系。
程序经编译连接后变为机器码:
第一个汇编程序「建议收藏」
标号:
一个标号指代了一个地址。
codesg:放在segment的前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段的段地址。
任务:编程运算 2^3

assume cs:abc
abc segment
mov ax,2
add ax,ax
add ax,ax
abc ends
end 

 应该在程序的末尾添加返回的程序段。

mov ax,4c00H
int 21H

这两条指令所实现的功能就是程序返回。

第一个汇编程序「建议收藏」

3、编辑源程序

进入DOS方式,运行edit,在其中编辑程序,如下图所示:

第一个汇编程序「建议收藏」

 4、编译

进入DOS方式,进入 C:\masm 目录,运行masm.exe。如果源程序文件不是以 asm 为扩展名的话,就要输入它的全名。比如p1.txt。在输入源程序文件名的时候一定要指明它所在的路径。如果文件就在当前路径下,只输入文件名就可以。

第一个汇编程序「建议收藏」

输入要编译的源文件文件名后,按 Enter键。目标文件(*.obj)是我们对一个源程序进行编译要得到的最终结果。编译程序默认要输出的目标文件名为1.obj,所以可以不必再另行指定文件名。

第一个汇编程序「建议收藏」

编译程序提示输入交叉引用文件的名称。

这个文件同列表文件一样,是编译器将源程序编译为目标文件过程中产生的中间结果。
可以不生成这个文件,直接按 Enter 键即可。

一般来说,有两类错误使我们得不到所期望的目标文件:

(1)我们程序中有“Severe Errors”;

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

5、连接

在对源程序进行编译得到目标文件后,我们需要对目标文件进行连接,从而得到可执行文件。继续上面的过程,我们再将C:\masm\1.obj连接为C:\masm\1.exe。

第一个汇编程序「建议收藏」

进入DOS方式,进入C:\masm目录,运行link.exe。如果目标文件不是以obj为扩展名的话,就要输入它的全名。比如:p1.bin。在输入目标文件名的时候,要注意指明它所在的路径。这里,我们要连接的文件是当前路径下1.obj,所以此处输入“1”。

第一个汇编程序「建议收藏」

输入要连接的目标文件名后,按Enter键。可执行文件是我们对一个程序进行连接要得到的最终结果。连接程序默认要输出的可执行文件名为 1.EXE ,所以可以不必再另行指定文件名。我们直接按 Enter 键,使用连接程序设定的可执行文件名。

映像文件是连接程序将目标文件连接为可执行文件过程中产生的中间结果。可以不生成这个文件,直接按 Enter 键即可。

连接程序提示输入库文件的名称。

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

如果没有调用任何子程序,直接按Enter键即可。

第一个汇编程序「建议收藏」

连接的作用:

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

程序中调用了某个库文件中的子程序,需要将这个库文件和该程序生成的目标文件连接到一起,生成一个可执行文件;

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

所以,在只有一个源程序文件,而又不需要调用某个库中的子程序的情况下,也必须用连接程序对目标文件进行处理,生成可执行文件。

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

我们编译、连接的最终目的是用源程序文件生成可执行文件。在这个过程中所产生的中间文件都可以忽略。我们可以用一种较为简捷的方式进行编译、连接。

编译:

第一个汇编程序「建议收藏」

连接:

第一个汇编程序「建议收藏」

7、1.exe的执行

现在,终于将我们的第一个汇编程序加工成了一个可在操作系统下执行的程序文件。1.exe的执行情况:

第一个汇编程序「建议收藏」

我们的程序没有像显示器输出任何信息。程序只是做了一些将数据送入寄存器和加法的操作,而这些事情,我们不可能从显示屏上看出来。程序执行完成后,返回,屏幕上再次出现操作系统的提示符。

8、可执行文件中的程序装入内存并运行的原理

DOS中有一个程序command.com ,这个程序在 DOS 中称为命令解释器,也就是DOS系统的shell。

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

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

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

汇编程序从写出到执行的过程:

第一个汇编程序「建议收藏」

9、程序执行过程的跟踪

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

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

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

用U命令查看一下其他指令:

第一个汇编程序「建议收藏」

用T命令但不执行程序中的每一条指令,并观察每条指令的执行结果,到了 int 21,我们要用P命令执行:

第一个汇编程序「建议收藏」

int 21 执行后,显示“Program terminated normally”,返回到Debug中。表示程序正常结束。

注意,要使用P命令执行int 21。

参考资料

《汇编语言》–王爽

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/167857.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 关于我妈的一切_networkmanager是什么服务

    关于我妈的一切_networkmanager是什么服务NetworkManager(NetworManager)是检测网络、自动连接网络的程序。无论是无线还是有线连接,它都可以令您轻松管理。对于无线网络,网络管理器可以自动切换到最可靠的无线网络。利用网络管理器的程序可以自由切换在线和离线模式。网络管理器可以优先选择有线网络,支持VPN。网络管理器最初由Redhat公司开发,现在由GNOME管理。1.查看NetworkManager…

    2022年10月4日
    2
  • 别让你的敏感词过滤系统把正常的文字过滤了!

    别让你的敏感词过滤系统把正常的文字过滤了!昨天csdn上发了一段文字评论(绝对非常规矩的文字),结果提示有敏感词,然后直接把我的博客和谐掉了。访问博客时提示:我们不去探讨过滤所谓敏感词的必要性和意义。既然做了这个系统,就要保证过滤质量,该过滤的过滤,不该过滤的词汇就不要过滤。如下这段话,作者实在没看出那里有不和谐因素。请读者指教啊:PS:会不会因为发了这篇文章博客再次被关闭啊!补充:经

    2022年5月10日
    35
  • Android中Context具体解释 —- 你所不知道的Context

    Android中Context具体解释 —- 你所不知道的Context

    2021年12月2日
    59
  • C语言中数组的总结

    C语言中数组的总结目录一维数组的创建和初始化一维数组的使用一维数组在内存中的存储指针的初步介绍一维数组的指针访问二维数组的创建和初始化二维数组的使用二维数组在内存中的存储二维数组的指针访问有关数组的运算数组作为函数参数1.一维数组的创建和初始化数组的创建:在创建数组时,我们必须定义数组的类型和大小,数组的大小不能为0,数组中的元素类型都是相同的。eg:intarr[

    2022年5月2日
    50
  • pycharm绘制图形_pycharm安装后无解释器

    pycharm绘制图形_pycharm安装后无解释器importnumpyasnpimportmatplotlib.pyplotaspltdefmain():#线的绘制x=np.linspace(-np.pi,np.pi,256,endpoint=True)c,s=np.cos(x),np.sin(x)#绘制plt.figure(1)#自变量…

    2022年8月28日
    7
  • iic通信协议是什么[通俗易懂]

    iic通信协议是什么[通俗易懂] iic通信协议是什么  IIC协议是二线制,信号线包含SDA和SCL,且信号线是双向的,开路结构,需要通过上拉电阻到VCC,具体的电阻值影响的是信号反应速度和驱动能力。  首先,IIC通信与UART,还有SPI统称为串行接口通信,不过它们之间还是有区别的,如UART的负电平逻辑,还有UART通信不需要时钟,只需要特定的波特率即可,SPI与IIC都可以有一个主机,多个从机的情况,…

    2022年6月9日
    49

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号