免费注册 查看新帖 |

Chinaunix

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

要将一段代码从32位的Linux移植到64位的Linux下去,该如何做? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-05 16:06 |只看该作者 |倒序浏览
5可用积分
代码如下:
//清除CR0 寄存器WP写保护标志位,并返回原来的value
unsigned int clear_and_return_cr0(void)
{
        unsigned int cr0 = 0;
        unsigned int ret;

        asm volatile ("movl %%cr0, %%eax"   : "=a"(cr0)   );
        ret = cr0;
        /* clear the 20 bit of CR0, a.k.a WP bit */
        cr0 &= 0xfffeffff;
        asm volatile ("movl %%eax, %%cr0"   :     : "a"(cr0)     );
        return ret;
}

最佳答案

查看完整内容

http://blog.chinaunix.net/u/548/showart.php?id=234533

论坛徽章:
0
2 [报告]
发表于 2008-11-05 16:06 |只看该作者

论坛徽章:
0
3 [报告]
发表于 2008-11-05 16:43 |只看该作者
和32位的道理一样, movl改成movq, CR0和Rax都是64位的。

论坛徽章:
0
4 [报告]
发表于 2008-11-05 16:59 |只看该作者

回复 #2 albcamus 的帖子

还有这一句该怎么改:
unsigned char idtr[6];
// 获取中断描述符表寄存器的地址idtr
asm ("sidt %0" : "=m" (idtr));

论坛徽章:
0
5 [报告]
发表于 2008-11-05 17:31 |只看该作者
改成unsigned char idtr[10]怎么样?

查查AMD手册吧,我也是查手册才知道的

论坛徽章:
0
6 [报告]
发表于 2008-11-05 22:51 |只看该作者
原帖由 canjian 于 2008-11-5 16:59 发表
还有这一句该怎么改:
unsigned char idtr[6];
// 获取中断描述符表寄存器的地址idtr
asm ("sidt %0" : "=m" (idtr));


sidt 指令不变,但 idtr[6],改为 idtr[10]

论坛徽章:
0
7 [报告]
发表于 2008-11-06 09:20 |只看该作者

回复 #5 mik 的帖子

感谢热心回复!现在发现了另外一个问题,再次请教。在32位Linux下,为了获取系统调用表,采用了下面的这种方式对内存进行搜索,主要是搜索call sys_call_table * (% eax, 4)对应的机器码0xff 0x14 0x85 *address of sys_call_table。但是到64位系统下对应的机器码多少呢?我没有找到arch/i386/kernel/entry.S这个文件,不知道中断0x80处理方式是否有所改变,os内核是AS4-64 2.6.9-42.ELsmp

void *get_sys_call_table()
{
        unsigned char *p;
        void * system_call;
        unsigned long  system_call_table ;

        unsigned char idtr[6];
        unsigned long base;
        struct idt_descriptor desc;

          // 获取中断描述符表寄存器的地址idtr
        asm ("sidt %0" : "=m" (idtr));
        base = *((unsigned long *) &idtr[2]);

         // 获取int 0x80中断处理程序的地址system_call
        memcpy(&desc, (void *) (base + (0x80*), sizeof(desc));
        system_call = ((void *) ((desc.off_high << 16) + desc.off_low));

            // 从0x80中断服务例程中搜索sys_call_table的地址
        p = (unsigned char *) system_call;
        while (!((*p == 0xff) && (*(p+1) == 0x14) && (*(p+2) == 0x85)))        p++;
        system_call_table  = *((unsigned long*) (p + 3));
        return((void *) system_call_table);
}

论坛徽章:
0
8 [报告]
发表于 2008-11-06 10:10 |只看该作者
原帖由 canjian 于 2008-11-6 09:20 发表
感谢热心回复!现在发现了另外一个问题,再次请教。在32位Linux下,为了获取系统调用表,采用了下面的这种方式对内存进行搜索,主要是搜索call sys_call_table * (% eax, 4)对应的机器码0xff 0x14 0x85 *addres ...

在64位当然要修改啦。

1、首先,64位下,IDTE 是16字节的,也就是说: 64位下的 interrupt descriptor 是16字节(128位)的。
  那么:memcpy(&desc, (void *) (base + (0x80 * 8 ), sizeof(desc));
      要修改为: memcpy(&desc, (void *) (base + (0x80 * 16), sizeof(desc));
      相应的 system_call = ((void *) ((desc.off_high << 16) + desc.off_low));  也要修改。


2、FF 14 85 这3个机器码的汇编语句是: call [eax*4+disp] 是 4 字节边界寻址。
     那么 64 位下,估计实现时会改为: call [rax*8+disp]  8字节边界寻址。
  相应的修改为:FF 14 C5

     所以,应改为搜索 FF 14 C5

论坛徽章:
0
9 [报告]
发表于 2008-11-06 10:16 |只看该作者

回复 #7 mik 的帖子

感谢,现在验证去!另外你的这些东西,哪里能找到资料?

论坛徽章:
0
10 [报告]
发表于 2008-11-06 10:18 |只看该作者
原帖由 albcamus 于 2008-11-6 10:15 发表
http://blog.chinaunix.net/u/548/showart.php?id=234533

赞~强呀

alb 已经有实际例子啦,我的回复也没多大意义了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP