免费注册 查看新帖 |

Chinaunix

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

modrm.mod==0,modrm.rm=4,sib.base==5,sib.index==4在sib.scale不同时有何特别之处? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-21 17:27 |只看该作者 |倒序浏览
binutils2.18

objdump 在生成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       pushl  0x80494f4 [内存地址]
            oappend (scratchbuf);
            if (riprel)
              {
                set_op (disp, 1);
                oappend ("(%rip)");
              }
          }
...}

论坛徽章:
0
2 [报告]
发表于 2010-01-21 19:20 |只看该作者
你所问的是 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 寻址模式为 [base],即:寄存器间接寻址

此时,如果,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

它是一个 [disp32],也就是说,它是一个绝对地址寻址。

:[0x080c1040] 这是一个绝对地址寻址



再举个例子:

当 modrm = 01-XXX-100  (modrm.mod = 01)
且当 sib = 11-000-101 (即:sib.scale = 11, sib.index = 000, sib.base = 101)

它的寻址是:[eax*8 + 0x0c] (这个 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

论坛徽章:
0
3 [报告]
发表于 2010-01-21 19:53 |只看该作者
谢谢,那|| scale != 0其实是多余的

论坛徽章:
0
4 [报告]
发表于 2010-01-21 21:57 |只看该作者
再请教mik版主,64位模式下的objdump解码有问题?

[root@mail ~]# printf "\xff\x34\x65\xf4\x94\x04\x08" > x1.dat
[root@mail ~]# 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    pushl  0x80494f4
[root@mail ~]# 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    pushq  0x80494f4(,2)
[root@mail ~]#

论坛徽章:
0
5 [报告]
发表于 2010-01-21 23:12 |只看该作者
原帖由 qtdszws 于 2010-1-21 21:57 发表
再请教mik版主,64位模式下的objdump解码有问题?

[root@mail ~]# printf "\xff\x34\x65\xf4\x94\x04\x08" > x1.dat
[root@mail ~]# objdump -b binary -m i386 -D x1.dat           

x1.dat:     file  ...


  ff 34 65 f4 94 04 08

这个机器码在 32 位下是:  push dword ptr [0x080494f4]

在 64 位下是:push qword ptr [0x080494f4]
------------------------------------------------------------------
在 32 位与 64 位下其实是一样的,只是它们的 operand size 不一样而已



>>>  0:   ff 34 65 f4 94 04 08    pushq  0x80494f4(,2)

我对 gnu 语法并不是很熟,这条 gnu 语法语句 对应的 intel 语法是什么 ??

但是,我能猜到,objdump 的死板,它把 scale = 2 直接给显示出来,才有 (,2) 这样的结果。

我只能说是 objdump 死板,或者说不够智能,这样很容易迷惑人

论坛徽章:
0
6 [报告]
发表于 2010-01-21 23:14 |只看该作者
binutils 2.20 显示结果又不一样

[root@ssq_pppoe binutils]#  printf "\xff\x34\x65\xf4\x94\x04\x08" > x1.dat
[root@ssq_pppoe binutils]# ./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    pushl  0x80494f4(,%eiz,2)
[root@ssq_pppoe binutils]# ./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    pushq  0x80494f4(,%riz,2)
[root@ssq_pppoe binutils]# ./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*2+0x80494f4]

多出了一个riz

查了一下


Changes from binutils 2.18.50.0.1:

7. Add fake index registers, EIZ/RIZ, to x86 assembler/disassembler.


不知道是什么意思?

论坛徽章:
0
7 [报告]
发表于 2010-01-21 23:39 |只看该作者
原帖由 qtdszws 于 2010-1-21 23:14 发表
binutils 2.20 显示结果又不一样

[root@ssq_pppoe binutils]#  printf "\xff\x34\x65\xf4\x94\x04\x08" > x1.dat
[root@ssq_pppoe binutils]# ./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    pushl  0x80494f4(,%eiz,2)
[root@ssq_pppoe binutils]# ./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    pushq  0x80494f4(,%riz,2)
[root@ssq_pppoe binutils]# ./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*2+0x80494f4]

多出了一个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+0x80494f4]    ===> 由于为 riz * 2  等于 0
>>> 最终结果还是等于: push qword ptr [0x080494f4]

这个 eiz 与 riz  是 gnu binutils 自已加上去的东西,并不是 intel 的东西

gnu objdump 又把别人给忽优了



(2)解释一个为什么会有 push   QWORD PTR [riz*2+0x80494f4] 这样的思维?


那是因为:在 x64 体系 64 位模式下,新增了一种寻址方式: rip 相对寻址(rip-rellative 寻址)

这种寻址是这样的:

当 modrm.mod = 0 , modrm.r/m = 5  的时候就出现 [RIP + offset] 这种寻址,它是不需要 SIB 字节的。

在原来的 32 位下, modrm.mod = 0 &  modrm.r/m = 5 的时候,它是 [disp32] 这种寻址


那么:在 modrm.mod = 0, modrm.r/m = 4 并且 sib.base = 5,sib.index = 4 时,出现的是:[disp32] 这种寻址

刚好和 modrm.mod = 0, modrm.r/m = 5 时的寻址是一样的。

这样就产生了重码,一个是仅仅需要 modrm 就可以了,一个是 modrm + sib 两个字节


SO:

我不知道,binutils 是出于什么考虑,要把 [disp32] 和 [rip+offset] 这两种寻址混在一起,binutils 把它们统一起来了。

但是,最终结果,由于 eiz/riz 等于 0 值的  eip/rip

因此,它们的结果是一样的。

只是,显示上这样引起了很大的混乱

论坛徽章:
0
8 [报告]
发表于 2010-01-22 09:13 |只看该作者
我想可能的解释是想让我们知道

pushq  0x80494f4(,%riz,2)

的指令序列是不同于

pushq  0x80494f4

反过来说,让gas据此生成不同的指令序列

论坛徽章:
0
9 [报告]
发表于 2010-01-22 10:30 |只看该作者
这里证实了我的想法,可以使用.allow_index_reg伪指令指示%riz或%eiz的使用

[root@ssq_pppoe i386]# more /root/binutils-2.20/gas/testsuite/gas/i386/x86-64-sib.s                                            

  1. #Test the special case of the index bits, 0x4, in SIB.

  2.         .text
  3.         .allow_index_reg
  4. foo:
  5.         mov     -30,%ebx
  6.         mov     -30(,%riz),%ebx
  7.         mov     -30(,%riz,1),%eax
  8.         mov     -30(,%riz,2),%eax
  9.         mov     -30(,%riz,4),%eax
  10.         mov     -30(,%riz,8),%eax
  11.         mov     30,%eax
  12.         mov     30(,%riz),%eax
  13.         mov     30(,%riz,1),%eax
  14.         mov     30(,%riz,2),%eax
  15.         mov     30(,%riz,4),%eax
  16.         mov     30(,%riz,8),%eax
  17.         mov     (%rbx),%eax
  18.         mov     (%rbx,%riz),%eax
  19.         mov     (%rbx,%riz,1),%eax
  20.         mov     (%rbx,%riz,2),%eax
  21.         mov     (%rbx,%riz,4),%eax
  22.         mov     (%rbx,%riz,8),%eax
  23.         mov     (%rsp),%eax
  24.         mov     (%rsp,%riz),%eax
  25.         mov     (%rsp,%riz,1),%eax
  26.         mov     (%rsp,%riz,2),%eax
  27.         mov     (%rsp,%riz,4),%eax
  28.         mov     (%rsp,%riz,8),%eax
  29.         mov     (%r12),%eax
  30.         mov     (%r12,%riz),%eax
  31.         mov     (%r12,%riz,1),%eax
  32.         mov     (%r12,%riz,2),%eax
  33.         mov     (%r12,%riz,4),%eax
  34.         mov     (%r12,%riz,8),%eax
  35.         .intel_syntax noprefix
  36.         mov    eax,DWORD PTR [riz*1-30]
  37.         mov    eax,DWORD PTR [riz*2-30]
  38.         mov    eax,DWORD PTR [riz*4-30]
  39.         mov    eax,DWORD PTR [riz*8-30]
  40.         mov    eax,DWORD PTR [riz*1+30]
  41.         mov    eax,DWORD PTR [riz*2+30]
  42.         mov    eax,DWORD PTR [riz*4+30]
  43.         mov    eax,DWORD PTR [riz*8+30]
  44.         mov    eax,DWORD PTR [rbx+riz]
  45.         mov    eax,DWORD PTR [rbx+riz*1]
  46.         mov    eax,DWORD PTR [rbx+riz*2]
  47.         mov    eax,DWORD PTR [rbx+riz*4]
  48.         mov    eax,DWORD PTR [rbx+riz*8]
  49.         mov    eax,DWORD PTR [rsp]
  50.         mov    eax,DWORD PTR [rsp+riz]
  51.         mov    eax,DWORD PTR [rsp+riz*1]
  52.         mov    eax,DWORD PTR [rsp+riz*2]
  53.         mov    eax,DWORD PTR [rsp+riz*4]
  54.         mov    eax,DWORD PTR [rsp+riz*8]
  55.         mov    eax,DWORD PTR [r12]
  56.         mov    eax,DWORD PTR [r12+riz]
  57.         mov    eax,DWORD PTR [r12+riz*1]
  58.         mov    eax,DWORD PTR [r12+riz*2]
  59.         mov    eax,DWORD PTR [r12+riz*4]
  60.         mov    eax,DWORD PTR [r12+riz*8]
复制代码

论坛徽章:
0
10 [报告]
发表于 2010-01-22 19:08 |只看该作者
原帖由 qtdszws 于 2010-1-22 09:13 发表
我想可能的解释是想让我们知道

pushq  0x80494f4(,%riz,2)

的指令序列是不同于

pushq  0x80494f4

反过来说,让gas据此生成不同的指令序列


这对编译器内部有用
但对用户来说, objump 直接显示出来,就显得很不智能和造成困拢了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP