我什么时候应该在x86中使用size指令?

时间:2017-06-15 21:14:11

标签: assembly x86 x86-64

何时在x86中使用size指令似乎有点含糊不清。 This x86 assembly guide说以下内容:

  

通常,给定内存中数据项的预期大小       地址可以从汇编代码指令中推断出来       引用。例如,在所有上述说明中,大小       存储区域可以从寄存器的大小推断出来       操作数。当我们加载32位寄存器时,汇编程序可以       推断我们所指的内存区域是4字节宽。       当我们将一个字节寄存器的值存储到存储器时,       汇编程序可以推断出我们希望地址引用单个地址       内存中的字节。

他们提供的例子非常简单,例如将一个直接值移动到一个寄存器中 但是更复杂的情况呢,例如:

mov    QWORD PTR [rip+0x21b520], 0x1

在这种情况下,QWORD PTR大小指令不是冗余的,因为根据上面的指南,可以假设我们想要将8个字节移动到目标寄存器中,因为RIP是8个字节? x86架构上的大小指令有哪些明确的规则?我无法在任何地方找到答案,谢谢。

更新:正如Ross指出的那样,上例中的目的地不是寄存器。这是一个更相关的例子:

mov    esi, DWORD PTR [rax*4+0x419260] 

在这种情况下,不能假设我们想要移动4个字节,因为ESI是4个字节,这使得DWORD PTR指令变得多余?

3 个答案:

答案 0 :(得分:4)

你是对的;它很模糊。假设我们正在讨论英特尔语法,那么你可以经常使用大小指令来使用而不是。只要汇编程序能够自动计算出来,它们就是可选的。例如,在指令

mov    esi, DWORD PTR [rax*4+0x419260] 

DWORD PTR说明符是可选的,原因如下:汇编程序可以确定它是要移动DWORD大小的值,因为该值正被移动到DWORD大小的寄存器中。

同样,在

mov    rsi, QWORD PTR [rax*4+0x419260] 

QWORD PTR说明符是可选的,原因完全相同。

但它并不总是可选的。考虑你的第一个例子:

mov    QWORD PTR [rip+0x21b520], 0x1

这里,QWORD PTR说明符不是可选。没有它,汇编程序不知道您要从地址rip+0x21b520开始存储的大小值。 0x1应该存储为BYTE吗?延伸到WORD?一个DWORD?一个QWORD?有些装配工可能会猜测,但如果没有明确指出你想要的东西,你就无法确定正确的结果。

换句话说,当值在寄存器操作数中时,大小说明符是可选的,因为汇编程序可以根据寄存器的大小计算出大小。但是,如果您正在处理立即值或内存操作数,则可能需要使用大小说明符来确保获得所需的结果。

就个人而言,我更喜欢始终包括编写代码时的大小。这是几个字符更多的打字,但它迫使我思考它并明确说明我想要的。如果我搞砸了并编码不匹配,那么汇编程序会大声尖叫我,这已经不止一次地捕获了错误。我也认为有它可以提高可读性。所以在这里我赞同old_timer,尽管他的观点似乎有点不受欢迎。

反汇编程序在输出中也往往很冗长,包括大小说明符,即使它们是可选的。 Hans Passant在评论中提出理论,这是为了保持与始终需要这些的老派装配商的向后兼容性,但我不确定这是否属实。它可能是其中的一部分,但根据我的经验,反汇编程序往往在不同方式的批次中变得冗长,我认为这只是为了更容易分析您不熟悉的代码。

请注意,AT& T语法使用略有不同的节拍。不是将大小作为操作数的前缀写入,而是为指令助记符添加后缀:b表示字节,w表示单词,l表示dword,{{1}对于qword。因此,前三个例子变为:

q

同样,在前两条指令中,movl 0x419260(,%rax,4), %esi movq 0x419260(,%rax,4), %rsi movq $0x1, 0x21b520(%rip) l前缀是可选的,因为汇编程序可以推导出适当的大小。在最后一条指令上,就像在Intel语法中一样,前缀是非可选的。因此,AT& T语法与Intel语法相同,只是尺寸说明符的不同格式。

答案 1 :(得分:2)

RIP或地址中的任何其他寄存器仅与寻址模式有关,而与传输的数据宽度无关。内存引用[rip+0x21b520]可以与1,2,4或8字节访问一起使用,常量值0x01也可以是1到8个字节(0x01是相同的as 0x00000001等。所以在这种情况下,必须明确提到操作数大小。

使用寄存器作为源或目标,操作数大小将是隐式的:如果使用EAX,则数据为32位或4字节:

mov    [rip+0x21b520],eax

当然,在非常漂亮的AT& T语法中,操作数大小被标记为指令助记符的后缀(此处为l)。

movl $1, 0x21b520(%rip) 

答案 2 :(得分:-1)

它变得更糟,汇编语言由汇编程序定义,汇编程序读取/解释/解析它。特别是x86,但作为一般规则,对于同一目标的任何两个汇编器没有技术上的原因,它们具有相同的汇编语言,它们往往相似,但不必如此。

你已经陷入了几个陷阱,首先是关于size指令使用的汇编程序的特定语法,然后是默认值。我的建议是总是使用size指令(或者如果有一个独特的指令助记符),那么你永远不必担心它吗?