好友
阅读权限20
听众
最后登录1970-1-1
|
鉴于网上64位汇编的中文教材少的可怜,Intel的鸟语手册对我这个CET-4的业余爱好者来说,一没时间看,二没能力学,所以就一边摸索一边学,了解一点儿新知识就跟大家分享一下,专业高手就不要嘲笑我了。
回到正题。
今天在学习64位汇编指令时,发现一个重要的知识点,64位指令的寻址方式与32位指令差异很大,可以说弄懂这个差异,是学好64位汇编的基础。
先来看一条mov语句:
mov ebx,[0]
在32位指令中,意思是把地址0x00000000的一个32位数给ebx:(当然Windows会给出一个异常,但我们讨论机器指令,不讨论Windows)
0040108C | 8B1D 00000000 | mov ebx,dword ptr ds:[0] |
在64位指令中,在内存中输入机器码:8B 1D 00 00 00 00,反汇编出来却是这样:
000000013F291100 | 8B1D 00000000 | mov ebx,dword ptr ds:[13F291106] |
000000013F291106 | 90 | nop |
汇编老手一眼就能看出来,mov指令把当前RIP地址的32位数赋给ebx,而不是绝对地址:0x00000000(有点儿晕?64位地址格式是这样:0x0000000000000000)。
实际上,在x64dbg中输入:mov ebx,[rip],你就能看到它的机器码是:8B 1D 00 00 00 00
有同学说,我不信,我偏要把0x0000000000000000中的内容赋给ebx:
000000013F291100 | ?? ?? ?? ?? ?? ?? ?? | mov rbx, [0]
上面内容是我编辑过的,为了让大家理解,实际上x64dbg根本不会让你通过,直接给出错误提示。
要把0x0000000000000000中的内容赋给ebx,只有一个办法:
000000013F291100 | 48:A1 0000000000000000 | mov rax,qword ptr ds:[0] |
000000013F29110A | 48:89C3 | mov rbx,rax |
或者:
你当前的RIP距离0x0000000000000000 足够近(距离小于32位):
0000000000000040 | 8B1D BAFFFFFF | mov ebx, dword ptr ds:[0x0000000000000000] |
上面的例子可以在x64dlb中自己尝试一下(需要开一个64位模式,一个32模式,方便对照)
如果看晕了,我总结一下32位指令和64位指令寻址的差异:
以 mov ebx,[0x56EF] 指令为例,
32位系统默认的内存地址起点是0x00000000,这条指令是把内存地址0x000056EF的内容赋给ebx,这是绝对寻址方式。
64位系统寻址能力绝大多数情况下也是32位而不是64位!所以它只能采取相对寻址的方式,默认的寻址起点是当前RIP!
假设当前RIP是000000013F291100,000000013F291100 - 56EF = 13F28BA11 超过32位,则 mov ebx,[0x56EF] 这个指令就是非法指令。
不过,有些编译器会修改成下面这样的合法指令:
mov ebx,[rip+0x56EF]
看完这些,大概对x86/x64家族的CPU处理64位数据的能力有了一个感性认识了吧,在64位模式下,CPU的寻址能力太弱了,绝大多数都只能寻址32位,根本就象是一个打了激素的32位CPU,或是一个被阉割了的64位CPU。怪不得Intel一直强调,真正的64位CPU是安腾架构的IA-64,我们目前的64位系统都是IA-32e架构下的64位子模式,Intel 都不承认它是真正的64位。
补充一点:
刚才我一直强调,64位系统寻址能力绝大多数情况下是32位,也就是说还有特例,比如:
mov eax,[0x56EF] 在64位系统中就是合法指令
000000013F291100 | A1 EF56000000000000 | mov eax,dword ptr ds:[56EF] |
在64位汇编指令中,rax是个特殊寄存器,它的功能比其它64位寄存器都强大,在有些指令中寻址能力能达到64位。
|
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|