32bit的编译器向64bit移植时要注意的一个小问题.
Intel CPU
当一个32bit的编译器向64bit移植时,要处理的地方有很多,以下是一个非常常见的指令在两个系统中的细微差别:
32bit
CALL DWORD PTR [N32]
这里调用的是地址为N32处的代码
64bit
address0: CALL DWORD PTR [N32]
这里调用的是地址为address0+N32处的代码
为何这样设计? 这样的好处是64bit与32bit的指令长度都是5byte,当然带来的麻烦是代码的单次跳转范围必须在2G内(一般都够用了),这是兼容带来的代价
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
兼容自然是要损失一些东西的,通用,就会损失效率、存储,不通用,就可以提高效率、存储。使用STL自然不可能有你为特定项目特意设计的算法效率高(当然,前提是设计者不是个棒槌)。编码的冗余问题。鱼与熊掌不可兼得,但是很多时候,兼容是至关重要的东西,只要别的损失并不离谱,会选择兼容
所言极是.
:wink: 顶...
没看懂楼主是什么意思,lz这个是masm的汇编??感觉LZ把32位的call指令弄错了.
call指令的几种区别.
relative是以当前指令结束时的EIP为参考地址,absolute指绝对地址.
rel32=立即数
r32=寄存器
m32=内存访问(指针)
机器码 指令 说明
E8 cd CALL rel32 Call near, relative, displacement relative to next instruction
FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32
9A cp CALL ptr16:32 Call far, absolute, address given in operand
FF /3 CALL m16:32 Call far, absolute indirect, address given in m16:32
表格取自intel开发者文档第二卷的指令手册
也就是说
call function 相对地址
mov eax,function
call eax 绝对地址
不要看到call c000000h就以为是绝对跳转,汇编器会做地址转换,并且生成一个重定位项,链接器在链接时对其进行重定位.
可以做一个简单的实验.
test1.asm call 1000h
test2.asm nop nop nop nop call 1000h
编译--反编译对比一下机器码.
其实编码到机器语言,还是相对地址偏移。
复制代码
编译
gcc -c 1.c
gcc 1.o
然后
objdump -D 1.o
有
17: e8 fc ff ff ff call 18 <func2+0xd>
objdump -D a.out
则有
080483b4 <func>:
...
80483cb: e8 e4 ff ff ff call 80483b4 <func>
在masm中
Call dword ptr [N32] 子程的入口地址在内存 ds:[N32] 处的双字
抱歉,我masm不熟.........
这样确实是绝对地址,属于call m32格式,相当于c里面用函数指针.
大侠也是一内行,希望能多多交流! :wink:
越来越关注LZ
64位很多第3方软件不能用,还没用64的OS,LZ竟然移植64位编译器。拜一个