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

发布于 2022-09-18 16:39:50 字数 1824 浏览 19 评论 0

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)");
              }
          }
...}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

来世叙缘 2022-09-25 16:39:50

你所问的是 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

尤怨 2022-09-25 16:39:50

谢谢,那|| scale != 0其实是多余的

︶葆Ⅱㄣ 2022-09-25 16:39:50

再请教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 ~]#

沫离伤花 2022-09-25 16:39:50

原帖由 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 死板,或者说不够智能,这样很容易迷惑人

故人的歌 2022-09-25 16:39:50

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.

不知道是什么意思?

ヅ她的身影、若隐若现 2022-09-25 16:39:50

原帖由 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

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

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

末骤雨初歇 2022-09-25 16:39:50

我想可能的解释是想让我们知道

pushq  0x80494f4(,%riz,2)

的指令序列是不同于

pushq  0x80494f4

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

泛滥成性 2022-09-25 16:39:50

这里证实了我的想法,可以使用.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]

复制代码

枯寂 2022-09-25 16:39:50

原帖由 qtdszws 于 2010-1-22 09:13 发表
我想可能的解释是想让我们知道

pushq  0x80494f4(,%riz,2)

的指令序列是不同于

pushq  0x80494f4

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

这对编译器内部有用
但对用户来说, objump 直接显示出来,就显得很不智能和造成困拢了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文