移植64位发生的问题(跟cltq指令有关)

Posted 爱搬砖的摄影师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了移植64位发生的问题(跟cltq指令有关)相关的知识,希望对你有一定的参考价值。

原文地址:http://filwmm1314.blog.163.com/blog/static/218259192012102424024131/

同事昨天在群里问了一个问题,大概将一个32位机器上运行良好的程序,移植到64位机器上之后出现了问题,看了一下core,大概是一个返回指针的函数,在函数内查看返回值还是正确的,但是到调用函数里面,返回值却被截掉了一段,引起了core。

具体代码如下: char *attach_shm(char *shmstr, int defaultkey, int shmsize)     char *shmptr;     int shmkey, shmid;     shmkey = search_shmkey(shmstr);     if (shmkey < 1024)         shmkey = defaultkey;     shmid = shmget(shmkey, shmsize, 0);     if (shmid < 0)     ........
    else     ........         return shmptr; attach_shm实现很简单,分配一块共享内存,然后返回内存的(首)地址。
调用处的代码:    char * myTmp =          attach_shm(shmkey, 5000 + mode * 10,                             sizeof(struct FILESHM) * maxnum);
有一点要提的是:调用attach_shm和定义attach_shm的不是同一个源文件。(后面会知道,这也是产生问题的原因之一) 这里的问题是,在使用GDB跟踪的时候打印shmptr出来看还是一个64位的值,但是函数返回之后打印myTmp的值确实32位的,这肯定要引起core啊。 可是问题是,这里上下文也不存储缓冲区溢出之类的可能,为什么返回值会被截掉一段呢? 使用GDB跟踪了一下,发现,在attach_shm里面,返回值去%rax的值还是正确的,可是到返回之后%rax的值却变了。这下更郁闷了,难道还有什么东西改变了%rax的值?以我浅薄的知识理解,都是没有这种可能的啊。 实在没办法了,只要将这两个函数反编译出来看看汇编代码了,在调用attach_shm的地方发现了一下代码:   43063f:       48 89 ca                mov    %rcx,%rdx   430642:       48 89 c7                mov    %rax,%rdi   430645:       b8 00 00 00 00          mov    $0x0,%eax   43064a:       e8 00 c3 fe ff          callq  41c94f <attach_shm>   43064f:       48 98                    cltq   430651:       48 89 85 00 ff ff ff    mov    %rax,-0x100(%rbp)   430658:       48 8b 85 00 ff ff ff    mov    -0x100(%rbp),%rax 注意被标注红色的cltq指令,在函数返回之后为什么会有这个指令?怎么其他函数调用之后没看到这个呢?这条指令我之前没接触过,不知道是干什么用的,于是google了一把,就发现早就有人踩过这个cltq这个坑了。
具体链接在  这里 ,这里说的很详细,我就不太多解释了。不明白cltq指令的意思的同学,可以看文章里面那个pdf 文档。
简单来说就是attach_shm这个函数在调用函数编译的时候没有声明过,于是编译器便将这个函数的返回值默认为32位,这个在32位机器上不会有什么问题,因为在32位机器上指针的长度也是32位,但在64位机器上,指针的长度是64位,默认32位的话,就有问题了。这也就是返回值被截断的原因了。 解决的方法很简单,使用头文件声明一下attach_shm这个函数,再让调用该函数的地方包含该头文件就行了。 整个解决问题的过程给我的感觉就是,懂一点汇编,或者说看的懂汇编,对于调试还是挺有帮助的。

以上是关于移植64位发生的问题(跟cltq指令有关)的主要内容,如果未能解决你的问题,请参考以下文章

将 32 位 C++ 代码移植到 64 位 - 值得吗?为啥?

32位程序移植64位经验

c语言int类型占的字节数因不因机子是64位还是32位的而改变啊?

将 Psyco 移植到 64 位可能存在哪些缺陷?

Arm64 中缺少 SSAT 和 USAT 指令的替代方案?

VS2008的32位的程序如何移植到64位的系统,具体操作上的问题