鱼C论坛

 找回密码
 立即注册
查看: 2257|回复: 6

为什么要数据对齐!

[复制链接]
发表于 2012-9-26 12:05:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这几天在看《汇编语言的编程艺术》书中第18页
3.4 HLA Support for Data Alignment一节,只讲了数据要对齐。
里面有一段,中文书中的解释是:
/*书摘开始*/
        通常,如果对像的大小是2的幂,并且可以达到16个字节,该宽度就是对象的大小。对于大于16字节的对象,将对象调整到8字节或16字节的地址加界上,这就足够了。对于小于16个字节的对象,一般将该对象对齐到恰好比其大小大的下一个2次幂的地址上是合理的。
        访问没有对齐到合适地址的数据需要花费额外的时间;所以,如果要保证程序运行得足够快,应当尽量依据数据对象的大小来对齐。

/*书摘结束*/
但本质原因却没有讲,非常困惑。
在网上搜索了一下:

/********网络的搜索回复***开始***/
什么是对齐,以及为什么要对齐:
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32 位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int数据。显然在读取效
率上下降很多。这也是空间和时间的博弈。
/********网络的搜索回复***结束***/


内存空间既然是按byte分的,将可以到哪里读哪里。
即便访问的对象在特定的内存地址里,也是可以读取到的,为什么要对齐。、
回复说“各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。”,这不就是在说一些平台有些地方是只读,有些是存储,有些是静态,有些是代码,根本没有涉及到对齐。

关键的是这个,“比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32 位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,”

这个最坑爹啊,
读取地址不是cpu控制的么?
高兴叫他从奇数读就从奇数读,高兴偶数读就从偶数读!
难道一个cpu说,“每次给我的地址,最一后一位必须是0,我只能读偶数地址么!”,另一个cpu说,“每次给我的地址,最一后一位必须是1,我只能读奇数地址么!”

非常感谢大牛回答,这个问题困惑我好久了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-9-26 17:19:06 | 显示全部楼层
因为对齐可以提高CPU的读取和处理速度。

简单的想象下:加工流水线的产品是不是都是一排排对齐好处理的?如果零零散散会怎样呢?总体效率是不是会更低呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-9-27 16:06:57 | 显示全部楼层

小甲鱼大哥,首先,非常感谢你,你的汇编让我认识到了很多很多,我在一个电商网站上班,只会java和js,as一类的。
是你让我知道汇编是多么美妙!
我不是学计算机系的。你像技术领导一样,让我在短时间内明白了很多很多底层的东西!
你来回答这个问题,也让我有受宠若惊的感觉。
非常非常非常——谢谢你的回答,无尽谢意。

但我在写上面东西时,我就知道会提高读取的速度了。
/**/卡夫卡的小说中有个叫《论比喻》——在比喻中我输了,我只能理解这个比喻。牛人比喻时,其实普通人还是听不懂的。
爱因斯坦说:“相对论就是你跟爸爸要钱时等待三分钟,你就觉得是三小时。跟女朋友聊天三小时,只相当于3分钟”。但我还是不明白相对论是什么啊。
我不是冒犯你啊,你可能只看到我的题目就回答了。没看我纠缠的内心表述。

为什么对齐就会读取快呢——cpu不是到哪读哪么,只要把ds设置一下就可以了啊!
这个问题我这几天也搜了好久好久。
也问了我很多朋友,但几人知道。

我内心中只有一个摇摆的假想:
   cpu读数据时,可能物理上有两根线(每根里几条我不知道,我看过《编码》),一个线读奇数位,一个线读偶数位。每次cpu读数据时,这两根线必须都工作。奇数位的只能读奇数位的,偶数位的只能读偶数位的,奇数位的读取的地址要比偶数位的要么大,要么小,但不能有时大,有时小。
所以,还是我提问时总结的:
cpu在说:“我的32位数据总线每次读的地址必须是奇数!我有个朋友也是一款cpu,他只能读偶数!哈哈,奇怪的人类,把我们设计成这样!!”




想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-9-27 19:18:53 | 显示全部楼层
我来解释下吧。以32位系统为例,这里的32说明了CPU的地址总线是32比特;数据总线也是32比特。

那么这里就有一个奇怪的问题,当你取地址0000000(32个0)的时候,应该只能取出1个字节到数据总线上,可是为什么数据总线是32位的呢?

其实,在这里只有地址线的高30位(A31  A30  A29,,, A2)连接到了CPU地址线上,A1和A0不连接在地址总线上。这样其实地址的线的低2位总是被忽略。所以读出地址0和地址1和地址2和地址3实际读出的内容都是一样的(因为0,1,2,3只有最低2位不同,而地址总线忽略最低2位)。这样一来,由于忽略的2个比特可以组合出4中状态,所以读出的数据就是4个字节(32比特)。A1和A0将进一步对读出的数据进行字节提取。
以上就是我们常常说的32位系统里的4字节对齐(其实就是不连最低2比特地址线)。这样,显然每次CPU从内存中取出的地址都是4的倍数。接下来的相信LZ已经知道了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-9-27 19:21:16 | 显示全部楼层
前面的书说存放在偶地址,不存放在奇地址,是应为那是16位系统,由于数据线16比特,所以地址线的最低位被忽略。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-9-28 09:32:49 | 显示全部楼层
仰望天上的光 发表于 2012-9-27 19:18
我来解释下吧。以32位系统为例,这里的32说明了CPU的地址总线是32比特;数据总线也是32比特。

那么这里就 ...

在这里只有地址线的高30位(A31  A30  A29,,, A2)连接到了CPU地址线上

大哥,我读到这一句,立即泪漰了。
我明白了。
你的意思只用30位就可以读到了啊!
不管的的地址是
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
00000000 00000000 00000000 00000011

这四个地址,对于cpu来说是一样的,CPU每次读其中任何一个地址的数据,其他几个数据都会被读出来!

太强大了!太强大了!
大哥,非常感谢你!我会好好学习的,回报你的一片栽培!谢谢,你从物理上解答了这个问题!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-9-28 09:37:43 | 显示全部楼层
:loveliness:
我终于明白了!
谢谢小甲鱼大哥,谢谢仰望天上的光大哥!非常感谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-16 07:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表