📄 o语言汇编基础教程.htm
字号:
<HTML>
<BODY LINK="#0000ff">
O语言网站http://www.olanguage.org/<br>
什么是O语言?<br>
O语言当前的版本是一门计算机汇编语言,它可以同时支持中文和英文,是当前唯一能支持非英文的计算机语言。本教程主要讲述计算机指令运行机制及汇编语言的相关知识,并用详实的例子来讲解如何使用O汇编语言来编写程序。汇编语言是计算机低级语言,它直接对应的是计算机机器指令,据有执行高效的特点,但由于它的底层性,指令浩繁复杂,如果你熟悉如MASM、FASM或者NASM等其它的汇编语言,那么你将能够很容易地学会使用O语言,它的内部机制与其它汇编语言是一致的;如果你没有接触过汇编语言,那么本教程将为你打开计算机语言的大门,深入细致地解剖聪明的计算机大脑的思考轨迹。如果你使用过C或者其它的计算机语言将对学习O语言有一定的帮助。<br><br>
计算机大脑的结构<br>
如果你已经熟悉CPU的结构可以跳过本节,但还是建议你对本节做简要的浏览,以熟悉O语言对寄存器的命名规则。计算机之所以能够思考全依赖于一个叫做中央处理器(CPU)的芯片,随着时代与科技的发展,处理器主要发展成为两大类别,一类是基于RISC(Reduced Instruction Set Computer)即精简指令系统架构的处理器,这类的处理器主要有以下几种:PowerPC处理器、SPARC处理器、 PA-RISC处理器、MIPS处理器、Alpha处理器。另一类是基于CISC(Complex Instruction Set Computer)即复杂指令系统的处理器,这种类型的处理器被广泛应用于个人电脑,也是人们最为熟悉的处理器,主要由Intel公司生产,所以又叫Intel架构的处理器,目前市场还有AMD公司和Cyrix公司与Intel竞争,让中国人鼓舞的是由中国自主研发的微型处理器已经具有相当的处理能力。本文主要讲述的就是针对这一类型处理器的指令系统,如无特殊说明,本文所说的处理器都指的是Intel架构的处理器,指令都是复杂指令系统的指令。即便是生产的公司与国别不同,处理器的思考方式是相似的,它们都能够处理传统的绝大部分指令,只是在效能上稍有不同。微型处理器的硬件结构决定了它的工作方式,它只能识别规定范围内的指令和数据,我们要想让它为我们工作除了尊重它的思维模式外没有其他任何办法,因此在研究计算机指令和学习计算机语言之前,有必要对这处理器的内部结构作一定的了解。首先来简单地了解一下计算机的工作原理,下图是现代微型计算机模型:<br><IMG src="computer_brain_strucutre_001.jpg"><br>
(图1.1 微型计算机模型)<br><br>
这是典型的微机原理图,我们主要讨论中央处理部分,<br>
处理器(CPU)所有要处理的数据包括执行的二进制码指令都存储在主存储器中,主存储器就是我们常说的内存,处理器内部的控制器从内存中取得指令并执行,并根据指令的意义对数据进行运算,处理后的结果也存储在内存中。处理器不仅要对数据进行运算,还要管理外围的部件,控制它们有序地进行工作。于是相应地汇编指令中不仅有用于加减乘除这样基本的数据运算指令,而且还有中断这样基本的控制指令。接下来让我们进一步了解处理器管理数据的来龙去脉,下面是计算机模型数据通路结构图:<br><IMG src="computer_brain_strucutre_002.jpg"><br>
(图1.2 模型机数据通路结构)<br>
控制器是全机的指挥控制中心,其基本功能是执行指令,由微操作信号发生器根据指令产生控制信号序列以命令相应部件分布完成指定的工作;控制器既可以控制处理器内部的数据传送,使累加器(ALU)完成指定功能和其他内部操作,也可以向处理器外部发出控制信号,控制处理器与存储器或输入输出设备之间的数据传送。微操作命令是最基本的控制信号,通常直接作用于部件或控制门电路的控制信号,简称微命令。这个图有点复杂,搞不懂也没关系,我们只要知道,处理器主要由控制器和运算器来执行指令和处理数据,而运算器又由累加器和寄存器组成,寄存器就是处理器用来内部存储数据用的部件,在控制器的指令控制下,累加器可以从指定的寄存器中获得数据并进行运算处理后返回结果到指定的寄存器中。<br><IMG src="computer_brain_strucutre_003.jpg"><br>
(图1.3 处理器模型)<br>
对汇编程序而言,除了知道数目繁多的汇编指令名称外,用得最多的就是寄存器,因此,我们必须对寄存器要有详细的了解。在二十世纪九十年代,当时的处理器还只处于8086和80286时代,这种处理器的寄存器是16位的,它一条指令最多只能处理16位的数据,因此这种处理器也叫做16位处理器,而处理器与内存进行数据交互使用的地址线是20位;现在应用最广泛的Intel公司生产的奔腾系统的处理器都是32位处理器,它内部的寄存器是32位,一条指令可以处理32位的数据,而且处理器与内存进行数据交互时的地址线也是32位的,关于处理器的内存寻址方式后面章节会进一步阐述。<br>
寄存器按功能可划分为通用寄存器、指令指针寄存器和标志寄存器。O语言是中文语言,它对处理器内部的寄存器都进行了统一的中文命名,图1.4是寄存器模型中,英文命名是标准的寄存器名,而中文是O语言使用的命名方式,寄存器中文命名的规则是寄存器功能加上位数识别,比如AX是16位累加器,中文名则是累加一六,而相应地32位累加器EAX则为累加三二,不区分大小的寄存器则直接使用功能名称,这能够很容易地记住各个寄存器的用途及大小。<br><IMG src="computer_brain_strucutre_004.jpg"><br>
注:着深绿色部分在386或更高处理器可用<br>
(图1.4 80x86/Pentium处理器的寄存器模型)<br><br>
通用寄存器也称多功能寄存器,共有八个通用寄存器,按它们的功能差别,又可分为两组,即:“通用数据寄存器”及“指针寄存器和变址寄存器”。通用数据寄存器用来存放8位、16位或32位的操作数。大多数算术运算和逻辑运算指令都可以使用这些寄存器。共有4个通用数据寄存器,它们是累加寄存器、基址寄存器、计数寄存器和数据寄存器。另外4个通用寄存器,指针寄存器和变址寄存器主要是以不同的方式来访问内存空间时用的寄存器,分别是:堆栈指针寄存器、基址指针寄存器、源变址寄存器和目的变址寄存器。<br>
程序是有序的指令集,但处理器执行时并不是以流水帐的形式一成不变地从指令开始执行到指令结束,而可能是从一个位置跳转到另一位置跳跃式地执行,指令指针寄存器内保存的值下一条指令所在的内存位置,可以用跳转、过程调用及中断等指令来改变这个寄存器的值,这就控制了程序执行的路径。<br>
标志寄存器的使用比较复杂,它内部的每一位都有特定的用途,用于指示微处理器的状态并控制它的操作。图1.5展示了80x86/Pentium系列所有型号微处理器的标志寄存器的情况。早期的8086/8088微处理器的标志寄存器FLAG为16位,且只定义了其中的9位;80286微处理器虽然仍为16位的标志寄存器,但定义的标志位已从原来的9位增加到12位(新增加了3个标志位); 80386及更高型号的微处理器则采用32位的标志寄存器EFLAGS,所定义的标志位也有相应的扩充。<br><br>
<IMG src="computer_brain_strucutre_005.jpg"><br>
(图1.5 80x86/Pentium系列处理器的标志寄存器)<br><br><IMG src="computer_brain_strucutre_006.jpg"><br>
(图1.6 8086/8088标志寄存器的格式及各位的功能)<br>
8086/8088系统中所定义的9个标志位:O、D、I、T、S、Z、A、P、C。在这9个标志位中,有6位(即CF、PF、AF、ZF、SF和OF)为状态标志;其余3位(即TF、IF和DF)为控制标志。<br>
<B>状态标志</B>反映微处理器的工作状态,如执行加法运算时是否产生进位,执行减法运算时是否产生借位,运算结果是否为零等;<br>
<B>控制标志</B>对微处理器的运行起特定的控制作用,如以单步方式运行还是以连续方式运行,在程序执行过程中是否允许响应外部中断请求等。<br>
六个状态标志的功能简述如下:<br>
(1) 进位标志CF(Carry Flag): 当执行算术运算指令时,其结果的最高位有进位或借位时将CF置1;否则将CF置0。<br>
(2) 奇偶标志PF(Parity Flag): 该标志位反映操作结果低8位中“1”的个数情况,若为偶数个“1”,则将PF置“1”;若为奇数个“1”,则将PF置“0”。它是早期Intel微处理器在数据通信环境中校验数据的一种手段。今天,奇偶校验通常由数据存储和通信设备完成,而不是由微处理器完成。所以,这个标志位在现代程序设计中很少使用<br>
(3) 辅助进位标志AF(Auxiliary carry Flag):辅助进位标志也称“半进位”标志。AF=1,表示本次运算的低4位中的最高位有进位(加法运算时)或有借位(减法运算时)。AF一般用于BCD运算中是否进行十进制调整的依据。十进制调整指令DAA和DAS测试这个标志位。<br>
(4) 零标志ZF(Zero Flag):反映运算结果是否为零。若结果为零,则ZF=1;若结果不为零,则ZF=0。<br>
(5) 符号标志SF(Sign Flag):反映带符号数(以二进制补码表示)运算结果符号位的情况。若结果为负数,则SF=1;若结果为正数,则SF=0。SF的取值总是与运算结果的最高位(字节操作为D7,字操作为D15,双字操作为D31)取值一致。<br>
(6) 溢出标志OF(Overflow Flag):反映有符号数运算结果是否发生溢出。若发生溢出,则OF=1;否则,OF=0。所谓溢出,是指运算结果超出了计算装置所能表示的数值范围。例如,对于字节运算,数值表示范围为-128~+127;对于字运算,数值表示范围为-32768~+32767。若超过上述范围,则发生了溢出。溢出是一种差错,系统应做相应的处理。<br>
三个控制标志的功能:<br>
(1) 方向标志DF(Direction Flag):用来控制串操作指令的执行。若DF=0,则串操作指令的地址自动增量修改,串数据的传送过程是从低地址到高地址的方向进行;若DF=1,则串操作指令的地址自动减量修改,串数据的传送过程是从高地址到低地址的方向进行。可以设置DF的指令为STD(置1)和CLD(清0)。<br>
(2) 中断标志IF(Interrupt Flag):用来控制对可屏蔽中断的响应。若IF=1,则允许CPU响应可屏蔽中断请求;若IF=0,则CPU不能对可屏蔽中断请求作出响应。可以设置IF的指令有STI(置1)和CLI(置0)。IF对非屏蔽中断和内部中断不起作用。<br>
(3) 陷阱标志TF(Trap Flag):陷阱标志也称单步标志。当TF=1时,微处理器就进入单步工作方式,每执行完一条指令便自动产生一个内部中断(称为单步中断),转去执行一个中断服务程序,可以借助中断服务程序来检查每条指令的执行情况;若TF=0,则CPU正常(连续)执行指令。单步工作方式常用于程序的调试。<br>
指令指针寄存器与标志寄存器的功能是专用的,保存着重要的信息,因此也称它们为专用寄存器。<br>
程序不仅有指令而且还有数据,为了便于管理和使用,将指令和数据分开以片段的形式存储在内存的不同位置,内存地址是连续的,当指令对数据进行操作时就必须能够很容易地定位到数据所在的内存地址,这时就要用到段寄存器,段寄存器内保存着某一段属性相同数据的内存首地址,访问内存数据都以这个首地址作为参照加上偏移量来得到数据的地址。这是简单的内存数据管理模型,内存是处理器活动的主要场所,内存资源是最为宝贵的系统资源,实际对内存空间分配和使用的管理异常复杂,主要由操作系统来完成。下面简单介绍各个段寄存器的功能:<br>
(1) 代码段寄存器CS(Code Segment):代码段顾名思义就是用来存储指令代码的一段内存区域,用以保存微处理器使用的代码(程序或过程)。代码段寄存器定义代码段的起始地址。<br>
(2)数据段寄存器DS(Data Segment):数据段是包含程序所使用的大部分数据的存储区。与代码段寄存器CS类似,数据段寄存器用以定义数据段的起始地址。<br>
(3)附加段寄存器ES(Extra Segment):附加段是为某些串操作指令存放目的操作数而附加的一个数据段。附加段寄存器用以定义附加段的起始地址。<br>
(4)堆栈段寄存器SS(Stack Segment):堆栈是存储器中的一个特殊存储区,用以暂时存放程序运行中的一些数据和地址信息。堆栈段寄存器定义堆栈段的首地址。由堆栈段寄存器和堆栈指针寄存器确定堆栈段内的存取地址。另外,基址一六/基址三二寄存器也可以寻址堆栈段内的数据。<br>
(5)标志段FS和全局段GS寄存器:这两个段寄存器仅对80386及更高型号的微处理器有效,以便程序访问相应的两个附加的存储器段。<br>
小结:这一小节主要介绍了处理器的概貌,并着重讲解了处理器内部寄存器的种类及功能,处理器的工作原理并不复杂,但是它的制造工艺随着技术的发展,其硬件构造的复杂程度已经超过其它任何产品。学习O语言你不需要对处理器内部结构有很深的了解,但必须熟练掌握各种寄存器的名称及功能。如果你是汇编的初学者,上面介绍的寄存器及功能可能并不容易理解,在后面用实例讲述O语言使用时,你将能更直观地感受到它们的用途及使用方法,在这里要求你对它们应留下大致的映像。<br><br>
寄存器对照表<br>
寄存器中文-英文命名对照表<br>
<TABLE BORDER CELLSPACING=1 CELLPADDING=7 WIDTH=494>
<TR><TD WIDTH="12%" VALIGN="TOP">
类型</TD>
<TD WIDTH="22%" VALIGN="MIDDLE">
中文名称</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
英文名称</TD>
<TD WIDTH="16%" VALIGN="TOP">
二进制码</TD>
<TD WIDTH="34%" VALIGN="MIDDLE">
寄存器说明</TD>
</TR>
<TR><TD WIDTH="12%" VALIGN="TOP" ROWSPAN=16>
多 功 能 寄 存 器</TD>
<TD WIDTH="22%" VALIGN="MIDDLE">
累加低八</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
AL</TD>
<TD WIDTH="16%" VALIGN="TOP">
000</TD>
<TD WIDTH="34%" VALIGN="TOP">
累加寄存器低八位</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
累加高八</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
AH</TD>
<TD WIDTH="16%" VALIGN="TOP">
100</TD>
<TD WIDTH="34%" VALIGN="TOP">
累加寄存器低八位</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
累加一六</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
AX</TD>
<TD WIDTH="16%" VALIGN="TOP">
000</TD>
<TD WIDTH="34%" VALIGN="TOP">
16位累加寄存器</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
累加三二</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
EAX</TD>
<TD WIDTH="16%" VALIGN="TOP">
000</TD>
<TD WIDTH="34%" VALIGN="TOP">
32位累加寄存器</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
基址低八</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
BL</TD>
<TD WIDTH="16%" VALIGN="TOP">
011</TD>
<TD WIDTH="34%" VALIGN="TOP">
基址寄存器低八位</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
基址高八</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
BH</TD>
<TD WIDTH="16%" VALIGN="TOP">
111</TD>
<TD WIDTH="34%" VALIGN="TOP">
基址寄存器低八位</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
基址一六</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
BX</TD>
<TD WIDTH="16%" VALIGN="TOP">
011</TD>
<TD WIDTH="34%" VALIGN="TOP">
16位基址寄存器</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
基址三二</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
EBX</TD>
<TD WIDTH="16%" VALIGN="TOP">
011</TD>
<TD WIDTH="34%" VALIGN="TOP">
32位基址寄存器</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
计数低八</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
CL</TD>
<TD WIDTH="16%" VALIGN="TOP">
001</TD>
<TD WIDTH="34%" VALIGN="TOP">
计数寄存器低八位</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
计数高八</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
CH</TD>
<TD WIDTH="16%" VALIGN="TOP">
101</TD>
<TD WIDTH="34%" VALIGN="TOP">
计数寄存器低八位</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
计数一六</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
CX</TD>
<TD WIDTH="16%" VALIGN="TOP">
001</TD>
<TD WIDTH="34%" VALIGN="TOP">
16位计数寄存器</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
计数三二</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
ECX</TD>
<TD WIDTH="16%" VALIGN="TOP">
001</TD>
<TD WIDTH="34%" VALIGN="TOP">
32位计数寄存器</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
数据低八</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
DL</TD>
<TD WIDTH="16%" VALIGN="TOP">
010</TD>
<TD WIDTH="34%" VALIGN="TOP">
数据寄存器低八位</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
数据高八</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
DH</TD>
<TD WIDTH="16%" VALIGN="TOP">
110</TD>
<TD WIDTH="34%" VALIGN="TOP">
数据寄存器低八位</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
数据一六</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
DX</TD>
<TD WIDTH="16%" VALIGN="TOP">
010</TD>
<TD WIDTH="34%" VALIGN="TOP">
16位数据寄存器</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
数据三二</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
EDX</TD>
<TD WIDTH="16%" VALIGN="TOP">
010</TD>
<TD WIDTH="34%" VALIGN="TOP">
32位数据寄存器</TD>
</TR>
<TR><TD WIDTH="12%" VALIGN="TOP">
类型</TD>
<TD WIDTH="22%" VALIGN="MIDDLE">
中文名称</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
英文名称</TD>
<TD WIDTH="16%" VALIGN="TOP">
二进制码</TD>
<TD WIDTH="34%" VALIGN="MIDDLE">
寄存器说明</TD>
</TR>
<TR><TD WIDTH="12%" VALIGN="MIDDLE" ROWSPAN=4>
指针寄存器</TD>
<TD WIDTH="22%" VALIGN="MIDDLE">
堆栈指针一六</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
SP</TD>
<TD WIDTH="16%" VALIGN="TOP">
100</TD>
<TD WIDTH="34%" VALIGN="TOP">
16位堆栈指针寄存器</TD>
</TR>
<TR><TD WIDTH="22%" VALIGN="MIDDLE">
堆栈指针三二</TD>
<TD WIDTH="16%" VALIGN="MIDDLE">
ESP</TD>
<TD WIDTH="16%" VALIGN="TOP">
100</TD>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -