20日学习汇编语言的感受 下面我们就可以写hellowrold了program helloworld;#include(stdlib.hhf)begin helloworld;stdout.put(Hello,world!!!, nl);end helloworld;我先来解释下这个程序啊#include和以前我们学的C的#include一样的就是复制粘贴stdlib.hhf中的内容为什么要这样做啊因为下面的stdout.put在那个stdlib.hhf里面啊stdout.put就是高级汇编语言的格式化输出到标准输出设备的语句。后面的nl是一个常量表示换行转义序列。现在我们把这个程序代码保存为helloworld.hla然后我们在cmd中执行hla helloworld看看效果如何很棒吧有1个警告不知道怎么回事以后应该会知道的了四 高级汇编的数据声明我们先来看1种类型的声明带符号整数类型int8,int16,int32就分别对应8位16位32位的带符号证书类型简单吧我们来看看它的一般申明格式statici8: int8 : 8;i16: int16 : 1600;i32: int32 : -3200000;i8,i16,i32就是声明的变量的名字了static代表我们声明的是静态的:后面的表示初始值也就是操作系统把程序载入存储器的时候会把这个初始值给变量。高级汇编变量声明的实例与新的概念现在呢我知道了如何声明带符号的整型类型啦那么高级汇编的stdout.put是不是和C语言的printf一样可以有多个参数呢另外stdout.put会如何处理输出整型数值呢还有如果我们要想输入怎么办呢有没有类C的scanf呢还有关于高级汇编的注释怎么做的呢我们来看看下面这个程序:Program DemoVars;#include(stdlib.hhf)staticInitDemo: int32 :5;NotInitialized: int32;begin DemoVars;//输出带符号整型变量的值stdout.put(InitDemos value is, InitDemo, nl);//输入1个数值到变量中stdout.put(Enter an integer value:);stdin.get(NotInitialized);stdout.put(You entered:, NotInitialized, nl);end DemoVars;从这个例子我们得出结论并验证了我们刚才的猜测啦首先stdout.put是允许有多个参数的如果制定了一个整数数值那么输出的时候stdout.put会把这个值转换为它的字符串形式stdin.get语句是从标准输入设备读入一个数值把它转换为整型数然后再把该数存储到为初始化的变量中。再则在高级汇编语言中和C C一样用//表示注释。五 高级汇编中的布尔值在高级汇编中标准库为布尔对象提供了支持我记得C中标准库都没有布尔的支持嘿嘿!是不是突然感觉到高级汇编好高好高级啊所以我们就可以在高级汇编的程序中声明布尔变量也可以使用布尔字面常量所以在布尔表达式中可以使用布尔变量并输出布尔变量的值啦聪明的我们一下子就知道布尔常量肯定是由true和false标识符表达的。true当然就是1来代表false就是0来代表。HLA中是用的一个字节来表示布尔值的。我们来看下它的典型声明staticBoolVar:boolean;HasClass:boolean : flase;IsClear:boolean : ture;嘿嘿我突然发觉高级汇编的语法好酷啊都没有括号六 高级汇编中的字符值HLA高级汇编语言允许使用char数据类型来声明单字节的ASII字符对象好棒啊也可以使用单引号括起来的字面字符值来初始化字符变量而且可以使用stdout.put来输出字符变量还可以使用stdin.get过程调用读取字符变量这里我忘记了说明下在HLA标准库中不允许通过stdin.get来读取一个布尔值哦下面我们来看看HLA中声明和初始化字符变量的方法staticc:char;LetterA:char:A;七 Intel 80X86处理器简介到这里我不得不告诉大家一个很残酷的现实啊虽然我们之前已经写了几个小程序了但是你发现没有我们写的那些小程序要么是数据声明要么是对HLA标准库的调用一点汇编语言的影子都没有啊。唉沮丧啊不过也别急了我们学习HLA高级汇编的目的就是让学习真正汇编语言更轻松啊这个HLA的意义所在啊那么我们现在开始了解下Intel 80x86处理器因为不理解处理器的基本结果机器指令将没有任何意义。我们之前不是了解过了嘛在前几节笔记中但是我这里要说明的是现在我们所学习的方向是32位操作系统中的汇编语言。它对寄存器啊进行了扩展Extended.Intel系统的CPU啊一般都归为风诺依曼式机器这种计算机系统主要包括3个主要模块CPU 存储器和输入输出(I/O)。这3部分通过系统总线相连其实我们之前已经知道啦Intel系列CPU提供了几个通用寄存器其中包含八个32位寄存器EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP哇竟然有ESPESP不是日本著名的吉他制造商吗大家是不是觉得和我们第一第二节笔记的寄存器名字不太一样啊前面怎么多了1个E啊。其实这个E代表扩展的意思该前缀将32位寄存器和八个16位的寄存器和8个八位的寄存器区分开来但是遗憾的是啊这些并非都是分离的寄存器也就是说80X86并未提供24个独立的寄存器那么它是怎么办的呢它是将16位寄存器重叠于32位寄存器之上的同理也将8位寄存器重叠于16位寄存器之上。我们来看个图大家一定要理解这一个图的意义啊不然经常会犯错的这个错误就是寄存器值的破坏。因为它们并不独立啊修改一个寄存器可能会影响到其他三个寄存器的。EFLAGS是一个32位寄存器它是由几个1位的布尔值组成的。EFLAGS寄存器中的大多数要么是为核心模式函数所保留的要么就是程序员所不感兴趣的。其中有8位是程序员编写汇编程序所必须要用到的所以我们重点是关注这8位了啊它们分别是溢出标志方向比啊在中断进制标志符号标志零标志进位标志奇偶标志还有辅助近卫标志其中要特别注意的是溢出标志进位标志符号标志和零标志这4个哦为什么要重点注意这几个呢说一个例子比如根据这些标志的状态就可以测试出前一次计算的结果。在对于两个值进行比较以后条件标志就会告诉你其中1个值是小于等于还是大于另一个值的。我们现在通过一个图来理解EFLAGS的布局为什么寄存器如此重要呢因为在80X86CPU中所以的计算都和寄存器有关的。比如将两个变量相加再把它们的和存入第3个变量中首先必须先将其中一个变量装入一个寄存器中并将第2个操作数和寄存器的值相加然后将寄存器中的值存入目的的变量。在这个过程中寄存器在每次计算机中都充当媒体。所以汇编语言程序中寄存器是非常重要的。为什么通过寄存器的这个通用是相对的因为有些寄存器是有特殊的目的的比如ESP它就不能用于任何其他的目的它只能是用于栈指针。EBP也是特殊目的的。但是你通过静心构造也是可以运用的但是通常不会这么做。还要记住余下的寄存器在程序中不可以完全互换。存储子系统我们知道在32位系统中可以寻址2的32次方个不同的存储单元也就是4G。如果我们要问什么是一个存储单元呢80X86中最基础的存储单元就是1个字节所以1个字节就是1个存储单元。内存是看不着也摸不着的那么我们怎么去理解内存呢怎么去理解内存才更合适呢最好的理解方式就是把内存看作是字节线性数组。首字节的地址为0最后1字节的地址为2的32次方-1。比如以下声明Memory: array [0..4294967295] of byte;这样一来我们为了执行Memory[125] 0;就是CPU将数值0放在数据总线上将地址125放在地址总线上并设置写信号。我们如下图来表示如果是执行CPU:Memory[125],则CPU会将地址125放到地址总线上并设置读信号然后从数据总线上读取数据的结果这个过程可以用下图表示哦原来是这样做的但是上面我们只是处理的单字节要是遇到更大的东西需要字或者双字怎么办啊其实这个很简单了使用连续的存储单元序列就可以了啊是啊我们就把这个对象的首地址做为这个对象的内存地址而且大家发现没有用4的整数倍的地址来对准四字节对象是最好的注意啊。因为如果该对象的地址为对象长度的整数倍那么访问内存中的数据对象的效率最高啊。理解内存与HLA变量之间的相关性既然电脑是这样工作的那么我们声明变量当然就必须自己去做入帮比那里和内存地址所关联的步骤啦但是我们现在用的是HLA高级汇编语言哦这些过程HLA已经帮我们做了以后要用这些变量就通过变量的名称来引用它们啦但是我们一定要明白HLA其实后台帮我们做了很多工作哦。这样的话我们以后写真正的汇编就知道具体该如何做了。HLA可以帮我们更容易的去学汇编的八 基本的机器指令学到机器指令啦大家肯定都觉得很难了其实大多数汇编语言程序中可能用到的机器指令就30来个了。我先来看1条C语句destination_operand source_operand;这个语句在汇编中如何用指令去直线的啊我们从C的角度知道这个是1个赋值语句啊也就是说把数据从1个位置移动到另一个位置应该说成复制好点因为并不会破坏原数据该指令的HLA语法如下mov ( source_operand, destination_operand );大家要注意source_operand可以是一个寄存器内存变量或者一个常量。destination_operand可以是一个寄存器或者内存变量。从技术角度上说80X86是不允许两个操作数都为内存变量的哦一定要记住哦但是HLA会自动将一条两字或者双字的内存操作数的MOV指令翻译为一对指令的。所以在HLA中对mov指令操作数的主要限制是它们必须具有相同的长度。也就是说你可以在两个8位16位32位对象之间移动数据。但是2个操作数的长度必须相同。而且HLA中的mov指令允许的将两个存储器操作数指定为源操作数和目的操作数的这种特殊的翻译方式只适用于mov不能推广到其他的指令哦