计算机中的信息=位+上下文。进一步,信息能够分为两大类:一类是数据,一类是指令。指令用来代表操做的动做,数据用来代表被操做的对象,这二者同时也构成了一个完整的程序。算法
对于数据而言,咱们先来谈整数的表示和运算。无符号编码表示无符号数,补码表示有符号数,相信你们对这两种编码应该是很是熟悉的(无符号编码没有符号位,补码的最高位表示符号位)。函数
在整数的运算方面一共有两种,一种是算术运算,一种是逻辑运算。算术运算就指日常的加减乘数,固然要注意溢出、符号位等各类状况(这个讲起来的话太多了,并且我也担忧本身讲很差,不懂的读者能够去翻翻书)。逻辑运算主要包括移位操做、或与非等,对于移位操做,必定要注意是算术右移仍是逻辑右移,算法右移在所缺的位置要补齐符号位,逻辑右移要补齐零。编码
因为浮点型的表示和运算,我也掌握的不是太好,读者本身翻书吧。翻译
对于指令而言,有传送指令、算术指令、逻辑指令、跳转指令以及支持过程调用和返回的指令。这些指令与c语言中的结构都是对应的,下面我会为你们讲解。指针
传送指令主要是mov a, b这种形式,像c语言中的赋值操做以及取某个变量的值等最后都会转化为这种指令。传送指令一共有三种寻址方式。第一种方式为当即数寻址,形式为mov $imm, EM,表示将imm传送到寄存器或者存储器EM中;第二种方式为寄存器寻址,形式为mov Ea, EM,表示将寄存器Ea中的值传送到EM中;第三种为存储器寻址,形式为mov (Ea), EM,表示将寄存器中的值所表示的存储器位置的值传送到EM中,固然这个有不少变形,但本质是同样的。要注意到不能从存储器传送到存储器。对象
在算术和逻辑指令中,像加减乘除、或与非、移位操做自没必要说,在c语言中的这些操做与汇编中基本是没什么区别。我主要来讲一下lea,即加载有效地址指令,它是mov指令的变形。指令形式为lea S, D,效果是将S的地址传送到D中,其中D必须为寄存器,像c语言中的求地址操做&就对应这种汇编语言。例如lea (Ea), Eb,在mov指令中表示将寄存器中的值所表示的存储器位置的值传送到Eb中,而在lea指令中表示将寄存器Ea中的值传送到寄存器Eb中。同时还能够用这个指令来进行一些算术运算。it
跳转指令主要包括无条件跳转和有条件跳转,无条件跳转的形式为jmp Label或者jmp *Operand,后者的跳转目标是从寄存器或者存储器中读出的。对于有条件跳转,只有在符合某些条件的状况下才会跳转,好比je、jne等,那么在汇编中是如何知道这些条件成立不成立呢?除了整数寄存器,CPU还包含一组单个位的条件码寄存器,好比CF(无符号溢出)、ZF(零)、SF(负数)、OF(有符号溢出),它们描述的是最近操做的属性,也有一些指令专门用来设置条件码而不修改其余寄存器,像test、cmp。跳转指令根据这些条件码的组合状况来决定是否跳转。在c语言中像if语言、for语言、while语言、switch语言最终都会翻译成跳转指令。test
最后一种指令就是支持过程调用和返回的指令。其中call指令用来过程调用,ret指令用来从过程调用中返回。c语言中的过程最后会翻译为汇编中的过程调用代码。在x86系统中一共有8个整数寄存器,其中有两个寄存器支持过程的实现,分别是栈指针%esp,帧指针%ebp。当执行call Label时(Label表示被调用的标记,也能够是*Operand的形式),计算机将返回地址(调用者的下一条指令地址)入栈,再将帧指针中保存的值(调用者的帧指针)入栈,最后将栈指针中保存的值传给帧指针,下面就开始执行被调用者中的指令,当执行ret返回时就是call指令的逆序,先将帧指针中保存的值传给栈指针,再push %ebp,将返回地址更新到程序计数器中,继续调用函数的执行。变量