免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3641 | 回复: 10
打印 上一主题 下一主题

[C] 有关内存对齐的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-19 16:51 |只看该作者 |倒序浏览
在32bit x86平台,mov ax, [1]具体是怎么处理的?

1. 因为地址为ds:1的word,跨越了word边界,那么其处理方式会不会是:读两次内存,分别把ds:0和ds:2处的word读出来,然后取ds:0的后半部和ds:1的前半部合成起来后,赋值给ax。

2. 还是会因为32bit的缘故,直接从ds:0处读一个32bit DWORD 出来,然后取其中的第2、3个字节,赋值给ax?

请问x86 cpu到底是怎么做得呢?

论坛徽章:
0
2 [报告]
发表于 2009-10-19 17:10 |只看该作者
首地址的最后两位不为0则需要两次,反之一次搞定,程序优化中常见问题。。。。

论坛徽章:
1
天蝎座
日期:2013-10-23 21:11:03
3 [报告]
发表于 2009-10-19 17:10 |只看该作者

回复 #1 020794 的帖子

对齐是不是要由编译器处理?
可以通过padding对齐

都到汇编了,除非自己调整,否则应该没有对齐了吧
猜的

论坛徽章:
1
天蝎座
日期:2013-10-23 21:11:03
4 [报告]
发表于 2009-10-19 17:15 |只看该作者
原帖由 emperor 于 2009-10-19 17:10 发表
首地址的最后两位不为0则需要两次,反之一次搞定,程序优化中常见问题。。。。


看来我错了
学习一下
忘了CPU中的指令解析了
是不是要多一些电平变化了

论坛徽章:
0
5 [报告]
发表于 2009-10-19 17:23 |只看该作者
对于这个问题,其实我是从struct内部成员的对齐方式想到的。比方说有

struct S
{
    char a;
    short b;
    char c;
}

根据内存对齐的规则,大家都知道sizeof(S)为6。内存布局为 a0bbc0。(a代表对应字节属于a,0代表padding)

那么其实也可以进行这样的内存布局,比方说abbc。
这样即使b没有按short的长度2对齐,但是其访问也只需要一次访存,因为32bit cpu一次可以读32bit数据,b并没有跨越32bit这个边界,那位什么编译器不是这样做呢?这样做显然比第一种,也就是实际做法占用更小的空间,且效率相同。

实在没想明白。。。

论坛徽章:
0
6 [报告]
发表于 2009-10-19 17:35 |只看该作者
原帖由 020794 于 2009-10-19 17:23 发表
对于这个问题,其实我是从struct内部成员的对齐方式想到的。比方说有

struct S
{
    char a;
    short b;
    char c;
}

根据内存对齐的规则,大家都知道sizeof(S)为6。内存布局为 a0bbc0。(a代表 ...

- - - -
- - - -
- - - -
- - - -
比如上面每个-代表1byte,那么32bit会4个低1byte的传输,而不是一行32bit
其余的不是很了解,intel如此。。。。

论坛徽章:
0
7 [报告]
发表于 2009-10-19 22:30 |只看该作者
原帖由 020794 于 2009-10-19 16:51 发表
在32bit x86平台,mov ax, [1]具体是怎么处理的?

1. 因为地址为ds:1的word,跨越了word边界,那么其处理方式会不会是:读两次内存,分别把ds:0和ds:2处的word读出来,然后取ds:0的后半部和ds:1的前半部合成 ...


对于以前的 x86 处理器来说:

32 位的地址线,processor 提供的物理接口只有 30 条线,分别是 A31 ~ A2,即:Address[31:2],地址线 A0 和 A1 被强制为 0
也就是说只有:00000000h、00000004h、00000008 ~ 依次到 FFFFFFC0h,从而形成了 dword 边界

processor 提供 32 位的数据线,分 4 组分别是:D0[7:0]、 D1[15:8]、 D2[23:16]  和 D3[31:24]

同时 processor 提供了4个字节使能线(Byte Enable),分别是:BE0#、BE1#、BE2# 和 BE3#
这 4 个 Byte Eable 信号用来控制访问相应的 bytes,
BE0#    ----->  D0[7:0]
BE1#    ----->  D1[15:8]
BE2#    ----->  D2[23:16]
BE3#    ----->  D3[31:24]


以你说的这条指令  mov ax, [0001h] 为例:它访问 2 个 bytes

processor 将地址 0000h 送上地址线,同时使 BE0# = 1,  BE1# = 0, BE2# = 0,BE3# = 1

从而使数据送到 D1 和 D2 ,这样来访问 word




2、如果指令 mov ax, [0003h]

则是跨 dword 边界,需要做两次读内存

(1) 读 0000h 地址的 D3[31:24] 使 BE3# = 0, BE2# = BE1# = BE1# =1
(2) 读 0004h 地址的 D0[7:0]     使 BE0# = 0,   BE1# = BE2# = BE3# =1

论坛徽章:
0
8 [报告]
发表于 2009-10-20 10:56 |只看该作者
谢谢楼上的精彩回复,学习了。

论坛徽章:
0
9 [报告]
发表于 2009-10-20 11:16 |只看该作者
那么再问一下:

对于mov ax, [0001h]来说,在通过数据线D1,D2传回数据后,在赋值给ax之前,是不是还要进行shift操作,向低位移8bit呢?

论坛徽章:
0
10 [报告]
发表于 2009-10-20 21:56 |只看该作者
原帖由 020794 于 2009-10-20 11:16 发表
那么再问一下:

对于mov ax, [0001h]来说,在通过数据线D1,D2传回数据后,在赋值给ax之前,是不是还要进行shift操作,向低位移8bit呢?


不存在 shift 操作

D0 ~ D3 代表 data path 0 ~ 3,用来定位在 dword 地址的哪个 data path 里存取 memory

data path 会直接读进相应的 register。同样也会直接从 registers 写进相应的 data path


实际上,D0 ~ D3 是一个变相的地址线

A31 --- A4  A3  A2  A1  A0
-----------------------------------------------------------------------------------------
X     ---  X    X   X    0    0                        ------> D0 (data path 0)
X     ---  X    X   X    0    1                        ------> D1 (data path 1)
X     ---  X    X   X    1    0                        ------> D2 (data path 2)
X     ---  X    X   X    1    1                        ------> D3 (data path 3)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP