3.5算数和逻辑操作
3.5.1加载有效地址
加载有效地址(load effective address)指令leaq时就会movq指令的变形。它的指令形式是从内存读数据到寄存器,但实际上它根本就没有引用内存。它的第一个操作数看上去是一个内存引用,但该指令并不是从指定的位置读入数据,而是将有效地址写入到目的操作数。
3.5.2一元和二元操作
第二组中的操作是一元操作,只有一个操作数,即是源又是目的。这个操作数可以是一个寄存器,也可以是一个内存位置。
第三组是二元操作,其中,第二个操作数即是源又是目的。
3.5.3 移位操作
最后一组是移位操作。先给出移位量,然后第二项给出的是要移位的数。可以进行算数和逻辑右移。移位量可以是一个立即数,或者放在单字节寄存器%cl中。
3.5.5 特殊的算术操作
3.6控制
C语言中的某些结构,比如条件语句、循环语句和分支语句,要求有条件的执行,根据数据测试的结果来决定操作执行的顺序。,机器代码提供两种基本的低级机制来实现有条件的行为:测试数据值,然后根据测试的结果来改变控制流或者数据流。
3.6.1条件码
CF:进位标志
ZF:零标志
SF:符号标志
OF:溢出标志
3.6.2访问条件码
条件码通常不会直接读取,常用的使用方法有三种:
1)可以根据条件码的某种组合,将一个字节设置为0或者1,
2)可以条件跳转到程序的某个其他的部分,
3)可以有条件地传送数据。
3.6.3跳转指令
正常执行的情况下,指令按照它们出现的顺序一条一条地执行。跳转指令会导致执行切换到程序中一个全新的位置。在汇编代码中,这些跳转的目的地通常用一个标号指明。
3.6.5用条件控制来实现条件分支
将条件表达式和语句从C语言翻译成机器代码最常用的方式是结合有条件和无条件跳转。
3.6.6用条件传送来实现条件分支
实现条件操作的传统方法是通过使用控制的条件转移。当条件满足时,程序沿着一条执行路径执行,而当条件不满足时就走另一条路径,这种机制简单而通用,但是在现代处理器上,它可能会非常低效。
一种替代的策略是使用数据的条件转移。这种方法计算一个条件操作的两种结果,然后再根据条件是否满足,从中选取一个。只有在一些受限制的情况中,这种策略才可行,但是如果可行,就可以用一条简单的条件传送指令来实现的条件传送指令更符合现代处理器的性能特性。
3.6.7循环
C语言提供了多种循环结构,即do-while while和for,汇编中没有相应的指令存在,可以用条件测试和跳转组合起来实现循环的效果。GCC和其他汇编器产生的循环代码主要基于两种基本的循环模式。
3.7过程
过程是软件中一种很重要的抽象。提供了一种封装代码的方式,用一组指定的参数和一个可选的返回值实现了某种功能,然后可以在成一种不同的地方调用这个函数,设计良好的软件,用过程作为抽象机制隐藏某个行为的具体实现,同时又提供清晰简洁的接口定义说明要计算的是哪些值过程,会对程序状态产生什么样的影响,不同编程语言中过程形式多样,函数方法,子例程,处理函数等等,但是他们有一些共有的特性。
传递控制
传递数据
分配和释放内存
3.7.1运行时栈
3.7.2转移控制
3.8数组分配和访问
c语言中的数组是一种将变量数据聚集成更大数据类型的方式,c语言实现数字的方式非常简单,因此很容易翻译成机器代码。C语言的一个不同寻常的特点是可以产生指向数组中元素的指针,并对这些指针进行运算。在机器代码中,这些指针会被翻译成地址计算。
优化编译器非常善于简化数组索引所使用的地址计算。不过这使得C代码和它的机器代码的翻译之间的对应关系有些难以理解。
3.8.1基本原则
对于数据类型T和整形常数N,声明如下:
T A[N];
3.8.2指针运算
C语言允许对指针进行运算,而计算出来的值会根据该指针引用的数据类型的大小进行伸缩,也就是说如果p是一个指向类型为T的数据的指针,p的值为Xp,那么表达式p+i的值为Xp+L*i,这里L是数据类型T的大小。
网友评论