首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >[ebp*2]指DS或SS段吗?

[ebp*2]指DS或SS段吗?
EN

Stack Overflow用户
提问于 2018-04-08 19:19:40
回答 2查看 819关注 0票数 14

IDM说,如果使用EBP作为基寄存器,则内存op使用SS段。因此,[ebp + esi][esi + ebp]分别引用SS和DS段。参见NASM的文档:3.3有效地址

在上述章节中,NASM提到了如何通过用[eax*2]代替[eax+eax]来生成更短的机器代码。

然而,NASM也为[ebp + ebp] (即没有基本寄存器)生成[ebp*2]

我怀疑[ebp+ebp]引用SS段,[ebp*2]引用DS段。

我问NASM这个问题。他们认为[ebp*2][ebp+ebp]是一样的,但对我来说没有意义。显然,[ebp+ebp] (ebp作为基寄存器)引用SS段。如果它们是相同的,[ebp*2也必须参考SS。这意味着只要ebp是基寄存器或索引寄存器,就会引用SS,这反过来意味着[ebp + esi][esi + ebp]引用SS段,所以它们必须是相同的。

有人知道[ebp*2]使用哪个片段吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-08 21:36:33

Intel手册告诉我们下面的图3-11,它处理Offset = Base + (Index * Scale) + Displacement

一般用途寄存器作为基本或索引组件的使用受到下列限制:

  • ESP寄存器不能用作索引寄存器。
  • 当ESP或EBP寄存器用作时,SS段是默认段。在所有其他情况下--,DS段是默认段。

这意味着,当将[ebp*2]转换为[ebp+ebp]时,NASM是错误的(以避免32位移位)。

[ebp*2]使用DS,因为ebp不用作基

[ebp+ebp]使用SS,因为其中一个ebp用作基

然后最好指定您不想要NASM的这种行为。

在NASM作者意识到自己的错误之前,您可以通过以下方式禁用这种行为(其中EBP被用作索引):

[NoSplit ebp*2]

票数 13
EN

Stack Overflow用户

发布于 2018-04-10 03:53:32

事实上,NASM的优化选择是不一致的,假设ssds在将[ebp*2]拆分为[ebp+ebp]以保存3个字节(disp32与disp8)时是可互换的(即一个平面内存模型),而不是将[ebp + esi]优化为[esi + ebp]以避免disp8。

( NASM手册甚至提到了不同的默认段。,与你从关于[0 + ebp*2][0+ebp+ebp*1]的错误信息中得出的结论相矛盾。)

EBP或ESP 作为基本寄存器意味着SS,否则默认为DS。当在NASM寻址模式中使用两个寄存器时,第一个寄存器是基本寄存器,除非您编写[ebp*1 + esi],否则显式地将比例因子应用于第一个寄存器。索引寄存器绝不意味着段,如果考虑到设计意图,这是有意义的:一个相对于段的索引:由基本寄存器或绝对disp32提供的偏移量。

正如所写的,[ebp*2]是一种索引寻址模式,隐式地需要4字节的零作为32位的移位。您可以让NASM用[nosplit ebp*2]那样对其进行编码。

可能忽略了这一情况,因为平面内存模型在16位代码之外几乎是通用的,(和16位寻址模式不同,不支持规模因素)。尽管您可以在16位代码中使用32位寻址模式来利用规模因素和更广泛的寄存器选择,即使是在纯实模式下,而不是允许您使用“虚幻”模式set segment limits high enough that offsets > 2^16 are usable模式下)。

所有主流的32位和64位x86 OSes都使用一个平面内存模型,其中SS和DS是可互换的,当您不做任何奇怪的事情时,这种优化在这些OSes下是安全的。分割有时是用于在页表支持之前创建不可执行的堆栈。,但这仍然是一个扁平的内存模型。(64位代码修正了CS/DS/ES/SS的基本/限制,因此这种优化在那里总是安全的,除非SS是一个完全不可用的段,如果可能的话,可能是写保护的。)

仍然认为,任何关于平面内存模型的假设都应该是可选的。这是NASM和YASM中的一个bug。他们要么尊重SS和DS之间的区别,要么充分利用平面内存模型来帮助那些不记得哪些寻址模式需要“隐藏”额外字节的程序员,比如优化[ebp+esi]而不将其替换成[esi+ebp]。最好应该有一个选项或指令来告诉汇编程序它可以假设SS和DS是相同的。

LEA的操作数总是可以利用的,因为LEA只处理地址的偏移部分,因此段是无关的。(这将是像[ebp*2]这样没有移位的寻址模式的最常见的用例:使用它作为内存地址可能会模仿可寻址的内存?这很奇怪,通常有一个真正的指针作为地址的一个组成部分。)

理解x86 32/64位寻址模式

除64位RIP相对寻址外,32/64位寻址模式是disp0/8/32 + base_reg + idx_reg*1/2/4/8,的任意子集,其中三个项/组件中的每一个都是可选的。但至少需要一个disp32或基本寄存器。(另见引用内存位置的内容。(x86寻址模式))。

[disp32=0 + ebp*2] (与disp32=zero一起)具有默认段= DS。您可以从[nosplit ebp*2]获得NASM中的这种编码,并且不能分割像[ebp*4]这样的地址。

[ebp + ebp + disp8=0]具有默认段= SS,因为EBP用作基寄存器。

编码意味着没有位移的ebp实际上意味着disp32没有基本reg,因此disp32实际上是基(意味着段寄存器DS,因为基不是EBP或ESP)。这是有或没有SIB字节的情况,所以[ebp + ebp*1]仍然必须使用disp8=0进行编码。其他寄存器没有这个问题,因此通常情况下,拆分将节省4个字节,而不是仅为EBP保存3个字节。(除了使用与RBP相同的ModR/M编码的r13之外,我想部分解码硬件不需要REX前缀中的额外位。)

ESP不能是索引寄存器,因此[esp*2]不可能使用拆分或不拆分进行编码。因此,NASM优化的特例只影响EBP*2。(base=ESP是SIB字节的转义代码,SIB字节中的index=ESP表示没有索引,允许对[esp + 12]进行编码。)

但不幸的是,NASM/YASM拆分了EBP*2 ,即使存在一个需要disp32的常量,比如[symbol + ebp*2],它不保存任何字节,实际上也不保存影响LEA (但不是加载/存储)在沙洲桥-家庭CPU上的性能。。3组件lea eax, [symbol + ebp + ebp*1]比2组件lea eax, [symbol + ebp*2]慢:更高的延迟和1/时钟的吞吐量,而不是2。根据http://agner.org/optimize/的说法,在AMD /Ryzen上,这些都会同样慢,因为一个缩放的指数使得一个“慢速-LEA”,即使只有两个组件。

对于LEA或实际内存操作数,如果有任何旧的CPU使用非缩放索引和三分量寻址模式,则可以使用IDK。

NASM与YASM行为

代码语言:javascript
复制
 $ nasm -felf32 -g -Fdwarf foo.asm
 $ objdump -drwC -Mintel -S foo.o | sed 's/DWORD PTR//'
 # (edited to put the NASM source line's addressing mode onto the same line as the disassembler output, instead of separate lines)
00000000 <sym-0x2c>:
   0:   8b 04 2e                mov    eax, [esi+ebp*1]         ; [esi+ebp]
   3:   8b 44 35 00             mov    eax, [ebp+esi*1+0x0]     ; [ebp + esi]
   7:   8b 04 2e                mov    eax, [esi+ebp*1]         ; [ebp*1 + esi]
   a:   8b 44 2d 00             mov    eax, [ebp+ebp*1+0x0]     ; [ebp*2]
   e:   8b 04 6d 00 00 00 00    mov    eax, [ebp*2+0x0]         ; [nosplit ebp*2]
  15:   8b 45 00                mov    eax, [ebp+0x0]           ; [ebp*1]   ; "split" into base=ebp with no SIB byte
  18:   8b 04 2d 00 00 00 00    mov    eax, [ebp*1+0x0]         ; [nosplit ebp*1]
  1f:   8b 84 2d d2 04 00 00    mov    eax, [ebp+ebp*1+0x4d2]   ; [ebp*2 + 1234]   ; bad split for LEA, neutral on modern CPUs for load/store
  26:   8b 85 15 cd 5b 07       mov    eax, [ebp+0x75bcd15]     ; [ebp*1 + 123456789]
sym:       ; using a symbol reference instead of a numeric constant doesn't change anything
  2c:   8b 84 2d 2c 00 00 00    mov    eax, [ebp+ebp*1+0x2c]    2f: R_386_32    .text   ; [ebp*2 + sym]
  33:   8b 84 2d 2c 00 00 00    mov    eax, [ebp+ebp*1+0x2c]    36: R_386_32    .text   ; [sym + ebp*2]

YASM对所有这些情况的编码与NASM相同。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49721801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档