~我也来发个字节对齐的问题~

2010-01-31 12:10:14
看过晨星老大在这里发的讨论,感觉还是不十分清楚,在这里发个贴继续~~

处理器只能从对齐的地址处存取数据,这应该是众所周知的。
可是,
究竟是什么原因导致处理器无法访问非对齐的地址?
也就是说,如果一个非对齐的地址被强行加到地址线上,会引发什么后果?
或者是根本不可能把非对齐地址加到地址总线上(例如总线上其实是移位后的地址,一定会对齐)?
还是因为内存条在设计的时候就是以几个字节为一个储存单位,内存控制器只能按这个粒度寻址?
还是有什么更深层的原因?

究竟是处理器对内存访问过程中的哪一步产生了寻址的限制条件?

一口气打了好多个问号……

另外,刚刚随便看了看 Intel 的优化指南,似乎说到即使从 cache 里取数据,也是需要对齐的,不过我也没仔细看~
...全文
214 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
DontKissBossAss 2010-02-02
  • 打赏
  • 举报
回复
汗的,只能设置/default/1/2/4/8/16/byte(s)
DontKissBossAss 2010-02-02
  • 打赏
  • 举报
回复
VS下设置非对齐试试
cnzdgs 2010-02-02
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 hpsmouse 的回复:]
就是说,地址线上已经是移位以后的地址了?

比如 8086 上,访问字节地址 111010(二进制),实际上加到地址线上面的是 11101?
[/Quote]
不是移位,而是在按“字”存取时不使用地址的最低位。
另外补充一下,前面所提的是以“字”为单位访问内存,8086也支持以字节为单位存取,此时会使用地址的最低位。
evanxgsh 2010-02-02
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 cnzdgs 的回复:]
CPU是由地址线输出地址,经地址解码后选定内存单元,再通过数据线来传输数据的。这里的“内存单元”不是指一个字节,而是一个“字”,“字”的位数就是数据线的条数,CPU是按“字”来访问内存的。这里的“地址”也是按“字”编址的,不是按字节,以8086为例,其数据线是16条,每个“字”对应两字节,第1个“字”对应的字节地址是00000和00001,第2个“字”对应的字节地址是00002和00003,而0002和00003,而00001和00002位于两个不同的“字”中,不能一次完成存取。如果程序要从00001处读取一个WORD,CPU只能是分两次把这两个字节所属的“字”分别读出,然后在CPU内部取出这两个字节,组成这个WORD;如果是向00001处写入一个WORD,则需要分别读写两个 “字”,(因为不能覆盖00000和00003),需要四次操作才能完成。所以在没有对其的情况下,存取的效率会降低。所谓“对齐”的概念,就是要避免发生这种跨“字”存取的情况,从而确保程序高效运行。
[/Quote]
正解 , 只要抓住字的概念就对了。
2010-02-02
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 gelu1040 的回复:]
找块32位CPU的DATASHEET 看看,这个不是语言问题这个是硬件问题
[/Quote]
好吧……
我用力把 386 和 486 DATASHEET 的引脚部分看了一遍,果然,386 没有 A0 地址线,486 没有 A0、A1 地址线……

问题解决,谢谢~~

这贴先留几天,欢迎继续讨论~
tiao618 2010-02-02
  • 打赏
  • 举报
回复
举个简单的例子,对于32位的系统(数据总线的宽度是32位),假如整形int是32位,字符char是16位(假设非实际情况),有一块内存区域存放着两种类型,若不是采用对齐的方式,那么对于char一次可以读出,而对int可能需要一次或者两次读出,则在最坏的情况下,大多数int需要2次读出,这大大的影响了处理器的效率(平均情况下也会大大降低效率),而在现在单位存储空间的价格不断的降低,采用这种以空间换取效率的方法变的很值得,于是就采用了这种内存对齐的方式

xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx(32位 一个内存单元)
如上的一个内存单元,可以一次读出,若对齐存放,则int可以一次读出,若不对则一个int可能占用这个内存单元的后16位和下一个内存单元的前16位,就得分两次读出

而对于非对齐方式还会增加硬件的复杂程度
xiaopoy 2010-02-02
  • 打赏
  • 举报
回复
需要对齐字节是因为windows内核会他娘得给出他娘的80000002错误,而且他娘的贼难定位错误地址,特别是错误源在堆栈中时。

至于需要对齐到的程度,当然也是由封装了硬件的系统确定的。
cnzdgs 2010-02-01
  • 打赏
  • 举报
回复
CPU是由地址线输出地址,经地址解码后选定内存单元,再通过数据线来传输数据的。这里的“内存单元”不是指一个字节,而是一个“字”,“字”的位数就是数据线的条数,CPU是按“字”来访问内存的。这里的“地址”也是按“字”编址的,不是按字节,以8086为例,其数据线是16条,每个“字”对应两字节,第1个“字”对应的字节地址是00000和00001,第2个“字”对应的字节地址是00002和00003,而00001和00002位于两个不同的“字”中,不能一次完成存取。如果程序要从00001处读取一个WORD,CPU只能是分两次把这两个字节所属的“字”分别读出,然后在CPU内部取出这两个字节,组成这个WORD;如果是向00001处写入一个WORD,则需要分别读写两个“字”,(因为不能覆盖00000和00003),需要四次操作才能完成。所以在没有对其的情况下,存取的效率会降低。所谓“对齐”的概念,就是要避免发生这种跨“字”存取的情况,从而确保程序高效运行。
gelu1040 2010-02-01
  • 打赏
  • 举报
回复
找块32位CPU的DATASHEET 看看,这个不是语言问题这个是硬件问题
2010-02-01
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 cnzdgs 的回复:]
CPU是由地址线输出地址,经地址解码后选定内存单元,再通过数据线来传输数据的。这里的“内存单元”不是指一个字节,而是一个“字”,“字”的位数就是数据线的条数,CPU是按“字”来访问内存的。这里的“地址”也是按“字”编址的,不是按字节,以8086为例,其数据线是16条,每个“字”对应两字节,第1个“字”对应的字节地址是00000和00001,第2个“字”对应的字节地址是00002和00003,而00?-
[/Quote]
就是说,地址线上已经是移位以后的地址了?

比如 8086 上,访问字节地址 111010(二进制),实际上加到地址线上面的是 11101?
某某9 2010-02-01
  • 打赏
  • 举报
回复
hemiya 2010-02-01
  • 打赏
  • 举报
回复
pengzhixi 2010-02-01
  • 打赏
  • 举报
回复
jf
zhangrenhui 2010-02-01
  • 打赏
  • 举报
回复
up
kingstarer 2010-01-31
  • 打赏
  • 举报
回复

一个非对齐的地址被强行加到地址线上,会引发什么后果?


在unix下会获得一个信号然后程序挂掉,windows上还没试过
2010-01-31
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 thefirstz 的回复:]
究竟是什么原因导致处理器无法访问非对齐的地址?
——效率问题吧,如果说32位的int,如果不是对齐的地址,需要访问两次才能读到
[/Quote]
呵呵,问的就是这个。
就是不太清楚内存访问的粒度是在哪里造成的。
昵称很不好取 2010-01-31
  • 打赏
  • 举报
回复
究竟是什么原因导致处理器无法访问非对齐的地址?
——效率问题吧,如果说32位的int,如果不是对齐的地址,需要访问两次才能读到
2010-01-31
  • 打赏
  • 举报
回复
本来想发到汇编区的,想着 C 版人气比较旺,还是先发这边~
WPooh 2010-01-31
  • 打赏
  • 举报
回复
......学习......

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧