`
dawuafang
  • 浏览: 1091770 次
文章分类
社区版块
存档分类
最新评论

为什么操作int 类型的指令要快于操作short 的,却可能慢于操作char 的

 
阅读更多

唔,写这篇博客的原因是贴吧里碰到了小破太激动了,看到小破说指令的效率回了几句。。。。

趁着想着这件事的时候写下来吧,因为这个确实不好在QQ 里说明白,改天再写的话我这破脑子一定会忘了……


1. 为什么对int 变量的操作比操作short 变量的指令快

如果你看过操作系统引导部分的资料的话,你就明白在描述符中D/B 位决定了CPU 指令的默认地址,如果置位则表示是32 位地址,复位就是8/16 位地址(我没看过64 位保护模式的资料原谅我吧)。一般来说我们的机器都是32 位的,所以32 位的机器只能操作32 位的地址。
但是这里有一个0x66 指令前缀(Prefixes ),这个前缀的作用就是切换默认操作数大小,所以当你在32 位系统上去操作一个8/16 位的变量的时候,那么就会在机器码前面增加一个0x66 前缀,这是就会多话费一个CPU 周期去执行。

但是对于char 呢?操作int 的指令比操作short 的快,并不代表操作int 的指令都要比操作长度小于sizeof (int) 变量的指令要快。

事实上操作int 的语句确实比操作short 的快,但是至少和操作char 的一样快。


2. 为什么操作int 类型的指令要快于操作short 的,却可能慢于操作char 的

程序:

short aShort = 0;
int aInt = 0;
objdump 之后:
4004b4: 66 c7 45 fe 00 00 movw $0x0,-0x2(%rbp)
4004ba: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp) 
程序:
char aChar = 0;
int aInt = 0;
objdump 之后:
4004b4: c6 45 ff 00 movb $0x0,-0x1(%rbp)
4004b8: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp) 
对于short 类型的确实加了x66 前缀了,但是char 类型的mov 中就没加,差了下指令表:
MOVmi 1100011w oo000www disp data 
蛋疼的是objdump 输出的att 格式的汇编,不顺眼写成MOVim 也行。
对于char 的操作,汇编器选择了直接复位w 位,直接换成对字节的操作了。
short 则不是,w 是置位的,对字操作,但是因为D/B 的关系,默认是操作双字,所以才加的x66 前缀改变了默认操作地址大小为字。

所以操作int 的语句确实比操作short 的快,但是至少和操作char 的一样快。


3. 对于0x66 Prefix 如何起作用的的进一步说明

对于0x66 Prefix,可以用一条x86_64 架构上的机器码手动反汇编过程来说明:

4004b4: 66 c7 45 fe 00 00 
4004b4: 66 c7 45 fe 00 00
66:Operand-Size Override prefix,用来更改默认Operand-Size(Descriptor 上的D/B 位)。
c7:MOVmi 1100011w,其中w 置位。查找指令表1100011,发现只有一条MOVmi 指令符合。所以0xc7 是一条mov 指令,将大小为双字的立即数送到一块内存。但是对于CPU 而言这条指令有Group 属性,需要配合ModR/M.reg 来配合定位(也就是0xc7 并不是完整的opcode)。
45:0b0100_0101,ModR/M 位,为了直观写作0b01_000_101
ModR/M.mod = 0b01:寻址模式base+disp8。
ModR/M.reg = 0b000:MOVmi 中对应的ModR/M.reg 位是oo000www,由ModR/M.reg 和0xc7 共同确定了指令MOVmi。
ModR/M.r/m = 0b101:结合ModR/M.mod = 0b01,查表可得rbp+disp8
fedisp8,8 位偏移量,-2
00 00:imm8,8 位立即数(实际上是16 位):0。之所以实际上是16 位,原因是原本立即数是8 位的,但是因为D/B 位被置位,立即数大小变为32,这里又加了0x66 前缀,所以立即数大小变为16 位。
结合0x66 前缀,操作数由双字变为字,对应指令就是

movw $0x0000, -0x2(%rbp)

这就是0x66 Prefix 起作用的一个例子,事实上手动反汇编的结果和objdump 之后得到的结果完全一致。



就是这样。

分享到:
评论

相关推荐

    《你必须知道的495个C语言问题》

    然后根据实际的机器环境把它们定义为int、short、long等类型。这样看来,所有的问题都解决了,是吗? 2  1.4 新的64位机上的64位类型是什么样的? 3 指针声明 3 1.5 这样的声明有什么问题?char *p1, p2; 我...

    你必须知道的495个C语言问题

    然后根据实际的机器环境把它们定义为int、short、long等类型。这样看来,所有的问题都解决了,是吗? 1.4 新的64位机上的64位类型是什么样的? 指针声明 1.5 这样的声明有什么问题?char*p1,p2;我在使用p2的...

    深入浅出MIPS

    这条指令的操作符可以为 Load 或 Store,一次 Load/Store 操作的范围可以为字/半字/ 字节(对应 gcc 的 int, short 和 char)。偏移量是一个带符号的 16bit 整数。两个作为操作数 的寄存器可以是任何通用寄存器。...

    JAVA基础之java的移位运算

    但是,如果你对一个负的byte 或者short类型的值进行移位运算,它被扩大为int 型后,它的符号也被扩展。这样,整数值结果的高位就会被1填充。因此,为了得到正确的结果,你就要舍弃得到结果的高位。这样做的最简单...

    语言程序设计课后习题答案

    由于图形用户界面的应用,程序运行由顺序运行演变为事件驱动,使得软件使用起来越来越方便,但开发起来却越来越困难,对这种软件的功能很难用过程来描述和实现,使用面向过程的方法来开发和维护都将非常困难。...

    超级有影响力霸气的Java面试题大全文档

     ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,...

    net学习笔记及其他代码应用

    1. 简述 private、 protected...因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。 47.当一个线程进入一个对象的一个synchronized方法后,其它线程是否可...

    一些C面试题,希望能对大家有帮助

    在某些16位编辑器下, int可能是2字节,那么结果是 int2 + DATE10 + double8 = 20 4、队列和栈有什么区别? 队列先进先出,栈后进先出 5、写出下列代码的输出内容 #include int inc(int a) { return(++a); } int multi...

    java 面试题 总结

    ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector...

    EDA/PLD中的从汇编程序中访问C程序变量

    在C程序中声明的全局变量可以被汇编程序通过地址间接访问,具体访问方法如下。  ·使用IMPORT伪指令声明该全局变量。  ·使用LDR指令读取该全局变量的内存地址,通常该全局... ·对于int类型的变量通过指令LDR/ST

    从汇编程序中访问C程序变量

    在C程序中声明的全局变量可以被汇编程序通过地址间接访问,具体访问方法如下。  ·使用IMPORT伪指令声明该全局变量。  ·使用LDR指令读取该全局变量的内存地址,通常该全局... ·对于int类型的变量通过指令LDR/ST

    C 语言编程常见问题解答.chm

    15.4 char,short,int和long类型分别有多长? 15.5 高位优先(big-endian)与低位优先(little—endian)的计算机有什么区别? 第16章 ANSI/ISO标准 16.1 运算符的优先级总能起作用吗? 16.2 函数参数类型...

    CheatEngine71.exe

    Symbolhandler现在可以在指针前面具有以下类型:(BYTE),(WORD),(DWORD),(QWORD),(CHAR),(SHORT),(INT),(INT64)将指针转换为值这种类型的 Structure Dissect现在可以检测vc ++和对象Pascal...

    C语言编程要点

    15.4. char,short,int和long类型分别有多长? 212 15.5. 高位优先(big—endian)与低位优先(little-endian)的计算机有什么区别? 213 第16章 ANSI/ISO标准 214 16.1. 运算符的优先级总能起作用吗? 214 16.2. 函数...

    C语言之GCC中支持的内存对齐指令

    1:gcc中支持但不推荐使用的指令 #pragma pack() :取消内存对齐访问 #pragma pack(n) (n=1/2/4/8):按n字节对齐 #pragma pack(2) struct mystruct1 { int a; char b; short c; } struct mystruct2 { ...

    Objective-C2.0程序设计

    4.1.1 int类型 4.1.2 float类型 4.1.3 double类型 4.1.4 char类型 4.1.5 限定词:long、long long、short、unsigned及signed 4.1.6 id类型 4.2 算术表达式 4.2.1 运算符的优先级 4.2.2 整数运算和一元负号运算符 ...

    整理后java开发全套达内学习笔记(含练习)

    float类型要跟f或F;或强制类型转换 科学计数法:12.5E3 类型转换默认序列: byte > short > int > long > float > double char 」 注意:默认类型转换(自动类型提升)会丢失精度,但只有三种情况: int>float;...

    千方百计笔试题大全

    96、Hibernate工作原理及为什么要用? 22 97、Hibernate是如何延迟加载? 22 98、Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系) 22 99、说下Hibernate的缓存机制 22 100、Hibernate的查询方式 23 101...

Global site tag (gtag.js) - Google Analytics