何时在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指令变得多余?
答案 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指令(或者如果有一个独特的指令助记符),那么你永远不必担心它吗?