免费注册 查看新帖 |

Chinaunix

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

请教这个宏的实现思路 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-10-24 09:08 |只看该作者 |倒序浏览
#define PAGE_ALIGN(addr,thePageSize)   (((addr) + thePageSize - 1) &  ~(theP
ageSize - 1))

这个宏是实现根据pagesize的值进行对齐的,并且是正确的。

请问这个宏实现的思路是什么呢?以后碰到类似的问题应该怎么解决。

谢谢。

论坛徽章:
0
2 [报告]
发表于 2006-10-24 09:09 |只看该作者
原帖由 shelleycao 于 2006-10-24 09:08 发表
#define PAGE_ALIGN(addr,thePageSize)   (((addr) + thePageSize - 1) &  ~(theP
ageSize - 1))

这个宏是实现根据pagesize的值进行对齐的,并且是正确的。

请问这个宏实现的思路是什么呢?以后碰到类 ...


谁也不知道写这个宏的心里怎么想的,就跟我现在不知道你心里想什么一样。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
3 [报告]
发表于 2006-10-24 09:19 |只看该作者
这个问题以前有很多人问过了,
你搜一下。
要是搞不清楚,你用实际的数字自己手算一下,
看看奥妙在哪里。

论坛徽章:
0
4 [报告]
发表于 2006-10-24 09:21 |只看该作者
thePageSize必须是2的n次幂这个宏才是正确的...

论坛徽章:
0
5 [报告]
发表于 2006-10-24 23:23 |只看该作者
以前对于这个宏有讨论过,不过似乎都讲得很模糊,作为一个知识点不应该有模糊

这个宏的目的是:将地址值调整为下一个边界上。

先问问自己:我应该怎么去实现这个功能呢?



假设: addr = 0xbfdf8cf3        也就是:1011 1111 1101 1111 1000 1100 1111 0011

那么:如果我要将这个值调整到下一个2字节边界上
      就应该是:xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx10
         也就是2的倍数上。

      如果我要将这个值调整到下一个4字节边界上
      就应该是:xxxx xxxx xxxx xxxx xxxx xxxx xxxx x100
      也就是4的倍数上。

      最后,如果我要将这个值调整到下一个8字节界边上
      就应该是:xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1000
         也就是8的倍数上


怎么做呢? 我必须根据所要调整边界的要求 将 addr 的低几位置 0,同时还要增加一个 模值


例如:我要将 addr 调整到 4 字节界上,于是我就有一个初步的想法

1、addr 加上 0100 使它跳到下一个 4 字节
    addr + 0000 0000 0000 0000 0000 0000 0000 0100
      结果为:1011 1111 1101 1111 1000 1100 1111 0111

2、将上一步的结果低 2 位清 0,从而实现调整要求
   1011 1111 1101 1111 1000 1100 1111 0111
&  1111 1111 1111 1111 1111 1111 1111 1100
--------------------------------------------------------------
    1011 1111 1101 1111 1000 1100 1111 0100
   

3、1111 1111 1111 1111 1111 1111 1111 1100 怎么通过 4 运算得出来呢?

    负数:-4 在机器中表示为: -4 = ~4 + 1
              即: 1111 1111 1111 1111 1111 1111 1111 1011        =  ~4
                  + 0000 0000 0000 0000 0000 0000 0000 0001        =  1
                 -----------------------------------------------------------------------------
                     1111 1111 1111 1111 1111 1111 1111 1100        =  -4
         

4 、总结一下,得出以下算法
    (addr + align_size) & (-align_size)




所以:我可以这样定义这个宏

#define PAGE_ALIGN(addr, align_size)  ((addr+align_size) & (-align_size))


而后来:我发现,只要加上被清0位数上的最大值,就可以跳到下一个对齐边界上,
        也就是: 4 字节对齐时,只要加上3就可以了,
                 8 字节对齐时,只要加上7就可以了,
                 2 字节对齐时,只要加上1就可以了,

            即: addr + align_size - 1 就可以了 !!!

        下一步做 & 时:4字节对齐,只要将 3 取反就得出 0xFFFF FFF4
                                   8字节对齐,只要将 7 取反就得出 0xFFFF FFF8
                                   2字节对齐,只要将 1 取反就得出 0xFFFF FFF2
      


于是: 我就有了算法的另一个版本:
       ( addr + align_size - 1 ) & (~(align_size - 1))

      
最后, 我就可以将宏定义为:
      
#define PAGE_ALIGN(addr, align_size) ((addr+align_size-1) & ~(align_size-1))

  

也就是,LZ 所问的宏是怎么来的

论坛徽章:
0
6 [报告]
发表于 2006-10-24 23:51 |只看该作者
补充一点:

(addr + align_size) & (-align_size)

这个算法,忽略了对 低几位是 0 的情况的考虑!

如果:xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx00
这种情况的话 addr + align_size 导致空跳到下一边界
addr + align_size - 1 无论什么情况下都是正确的。

-align_size 与 ~ (align_size - 1) 本质上是一样的, 而 - align_size 似乎更好理解,建议采用这种形式
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP