modrm.mod==0,modrm.rm=4,sib.base==5,sib.index==4在sib.scale不同时有何特别之处?
binutils2.18objdump 在生成disp时使用了如下代码,没看明白scale!=0是啥意思?
OP_E()
{
....
havedisp = havebase //排除(modrm.mod==0且modrm.rm==5)或(modrm.mod==0且modrm.rm==4且sib.base==5)
|| (havesib //排除modrm.mod==0且modrm.rm==5
&& (index != 4 //排除modrm.mod==0且modrm.rm==4且sib.base==5且sib.index==4
|| scale != 0));//mod_bit64????多余???
if (!intel_syntax)
if (modrm.mod != 0 || (base & 7) == 5)//肯定有dispxx
{
if (havedisp || riprel)//是disp
print_displacement (scratchbuf, disp);// mov -0x4(%ebx),%eax
else//是地址
print_operand_value (scratchbuf, 1, disp);//8048248: ff 35 f4 94 04 08 pushl0x80494f4 [内存地址]
oappend (scratchbuf);
if (riprel)
{
set_op (disp, 1);
oappend ("(%rip)");
}
}
...} 你所问的是 x86/x64 指令体系中最复杂的一个寻址模式:wink:
正好问的是 register id 为 100 和 101 时的情形
100(4)= esp
101(5)= ebp
它的复杂性产生于我所说的两大原则,详见我的网站上的一篇文档:http://www.mouseos.com/x64/modrm_sib_rule.html
基于这两个原则:
当 modrm.r/m = 4 时,它引导出 SIB 字节,那么:
(1)当 sib.index = 4 即 sib.index = esp 时:sib 寻址模式为 ,即:寄存器间接寻址
此时,如果,sib.base = ebp(5) 时, 与 modrm = 00-XXX-101(modrm.mod = 0 & modrm.r/m = 5)时的寻址是一样的。
因此,又依赖于 modrm.mod 是多少
回到你提的问题来:
>> modrm.mod==0,modrm.rm=4,sib.base==5,sib.index==4在sib.scale不同时有何特别之处?
这时,scale 是被忽略,被抛弃。也就是说 scale 并不起作用!
modrm.mod = 0, modrm.r/m = 4 并且 sib.base = 5, sib.index = 4
它是一个 ,也就是说,它是一个绝对地址寻址。
如:] 这是一个绝对地址寻址
再举个例子:
当 modrm = 01-XXX-100(modrm.mod = 01)
且当 sib = 11-000-101 (即:sib.scale = 11, sib.index = 000, sib.base = 101)
它的寻址是: (这个 0x0c 是举个例子):index 是 eax 寄存器, scale 是 8, 无 base 寄存器
此时,scale 才有意义,因为它的 modrm.mod = 1
---------------------------------------
所以:
sib.index = 4 时,寻址模式依赖于 sib.base 并且还要依赖于 modrm.mod 的值
或许你要认真是看一下,我网站上的文档(关于 x86/x64 指令体系):http://www.mouseos.com/x64/index.html 谢谢,那|| scale != 0其实是多余的 再请教mik版主,64位模式下的objdump解码有问题?
# printf "\xff\x34\x65\xf4\x94\x04\x08" > x1.dat
# objdump -b binary -m i386 -D x1.dat
x1.dat: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 34 65 f4 94 04 08 pushl0x80494f4
# objdump -b binary -m i386 -M x86-64 -D x1.dat
x1.dat: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 34 65 f4 94 04 08 pushq0x80494f4(,2)
# 原帖由 qtdszws 于 2010-1-21 21:57 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
再请教mik版主,64位模式下的objdump解码有问题?
# printf "\xff\x34\x65\xf4\x94\x04\x08" > x1.dat
# objdump -b binary -m i386 -D x1.dat
x1.dat: file...
ff 34 65 f4 94 04 08
这个机器码在 32 位下是:push dword ptr
在 64 位下是:push qword ptr
------------------------------------------------------------------
在 32 位与 64 位下其实是一样的,只是它们的 operand size 不一样而已
>>>0: ff 34 65 f4 94 04 08 pushq0x80494f4(,2)
我对 gnu 语法并不是很熟,这条 gnu 语法语句 对应的 intel 语法是什么 ??
但是,我能猜到,objdump 的死板,它把 scale = 2 直接给显示出来,才有 (,2) 这样的结果。
我只能说是 objdump 死板,或者说不够智能,这样很容易迷惑人:mrgreen: binutils 2.20 显示结果又不一样
#printf "\xff\x34\x65\xf4\x94\x04\x08" > x1.dat
# ./objdump -b binary -m i386 -D x1.dat
x1.dat: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 34 65 f4 94 04 08 pushl0x80494f4(,%eiz,2)
# ./objdump -b binary -m i386 -M x86-64 -D x1.dat
x1.dat: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 34 65 f4 94 04 08 pushq0x80494f4(,%riz,2)
# ./objdump -b binary -m i386 -M x86-64,intel -D x1.dat
x1.dat: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 34 65 f4 94 04 08 push QWORD PTR
多出了一个riz
查了一下
Changes from binutils 2.18.50.0.1:
7. Add fake index registers, EIZ/RIZ, to x86 assembler/disassembler.
不知道是什么意思? 原帖由 qtdszws 于 2010-1-21 23:14 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
binutils 2.20 显示结果又不一样
#printf "\xff\x34\x65\xf4\x94\x04\x08" > x1.dat
# ./objdump -b binary -m i386 -D x1.dat
x1.dat: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 34 65 f4 94 04 08 pushl0x80494f4(,%eiz,2)
# ./objdump -b binary -m i386 -M x86-64 -D x1.dat
x1.dat: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 34 65 f4 94 04 08 pushq0x80494f4(,%riz,2)
# ./objdump -b binary -m i386 -M x86-64,intel -D x1.dat
x1.dat: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 34 65 f4 94 04 08 push QWORD PTR
多出了一个riz
查了一下
Changes from binutils 2.18.50.0.1:
7. Add fake index registers, EIZ/RIZ, to x86 assembler/disassembler.
...
以我的为准吧,我所说的是肯定不会错的。
但是,我可以解释一下,objdump 为什么会这样的
(1) eiz/riz 是什么?
如果,我没猜错的话,它们是:eip 和 rip ----> 它们是 zero 的 eip/rip
意思是:为 0 eip/rip 寄存器
那么:push QWORD PTR ===> 由于为 riz * 2等于 0
>>> 最终结果还是等于: push qword ptr
这个 eiz 与 riz是 gnu binutils 自已加上去的东西,并不是 intel 的东西:mrgreen:
gnu objdump 又把别人给忽优了:mrgreen:
(2)解释一个为什么会有 push QWORD PTR 这样的思维?
那是因为:在 x64 体系 64 位模式下,新增了一种寻址方式: rip 相对寻址(rip-rellative 寻址)
这种寻址是这样的:
当 modrm.mod = 0 , modrm.r/m = 5的时候就出现 这种寻址,它是不需要 SIB 字节的。
在原来的 32 位下, modrm.mod = 0 &modrm.r/m = 5 的时候,它是 这种寻址
那么:在 modrm.mod = 0, modrm.r/m = 4 并且 sib.base = 5,sib.index = 4 时,出现的是: 这种寻址
刚好和 modrm.mod = 0, modrm.r/m = 5 时的寻址是一样的。
这样就产生了重码,一个是仅仅需要 modrm 就可以了,一个是 modrm + sib 两个字节
SO:
我不知道,binutils 是出于什么考虑,要把 和 这两种寻址混在一起,binutils 把它们统一起来了。
但是,最终结果,由于 eiz/riz 等于 0 值的eip/rip
因此,它们的结果是一样的。
只是,显示上这样引起了很大的混乱 我想可能的解释是想让我们知道
pushq0x80494f4(,%riz,2)
的指令序列是不同于
pushq0x80494f4
反过来说,让gas据此生成不同的指令序列 这里证实了我的想法,可以使用.allow_index_reg伪指令指示%riz或%eiz的使用
# more /root/binutils-2.20/gas/testsuite/gas/i386/x86-64-sib.s
#Test the special case of the index bits, 0x4, in SIB.
.text
.allow_index_reg
foo:
mov -30,%ebx
mov -30(,%riz),%ebx
mov -30(,%riz,1),%eax
mov -30(,%riz,2),%eax
mov -30(,%riz,4),%eax
mov -30(,%riz,8),%eax
mov 30,%eax
mov 30(,%riz),%eax
mov 30(,%riz,1),%eax
mov 30(,%riz,2),%eax
mov 30(,%riz,4),%eax
mov 30(,%riz,8),%eax
mov (%rbx),%eax
mov (%rbx,%riz),%eax
mov (%rbx,%riz,1),%eax
mov (%rbx,%riz,2),%eax
mov (%rbx,%riz,4),%eax
mov (%rbx,%riz,8),%eax
mov (%rsp),%eax
mov (%rsp,%riz),%eax
mov (%rsp,%riz,1),%eax
mov (%rsp,%riz,2),%eax
mov (%rsp,%riz,4),%eax
mov (%rsp,%riz,8),%eax
mov (%r12),%eax
mov (%r12,%riz),%eax
mov (%r12,%riz,1),%eax
mov (%r12,%riz,2),%eax
mov (%r12,%riz,4),%eax
mov (%r12,%riz,8),%eax
.intel_syntax noprefix
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
mov eax,DWORD PTR
原帖由 qtdszws 于 2010-1-22 09:13 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
我想可能的解释是想让我们知道
pushq0x80494f4(,%riz,2)
的指令序列是不同于
pushq0x80494f4
反过来说,让gas据此生成不同的指令序列
这对编译器内部有用
但对用户来说, objump 直接显示出来,就显得很不智能和造成困拢了
页:
[1]