将较小的值移动到寄存器中
Moving a value of a lesser size into a register
我已经存储了 8
的一个字节值,我想将其移入 rax
寄存器。我目前正在使用 movzx
对字节进行零扩展:
.globl main
main:
push %rbp
mov %rsp, %rbp
movb , -1(%rbp)
movzx -1(%rbp), %rax <-- here
...
movzx
指令'know'如何让-1(%rbp)
处的值只有一个字节长?从这里说,如果我正确阅读它,它可以在 byte
和 word
上工作,但它怎么知道呢?例如,如果我在 -2(%rbp)
处添加了一个两字节的值,它怎么知道要获取这两个字节的值?是否有另一条指令,我可以在地址处获取 one
或 two
或 four
字节值并将其插入 64 位寄存器?
我想另一种方法是先将寄存器清零,然后将其添加到 8 位(或多少位)组件中,例如:
mov [=11=], %rax
mov -1(%rbp), %al
有没有一种方法比另一种方法更受欢迎?
How does the movzx
instruction 'know' that the value at -1(%rbp)
is only one byte long?
有两个(甚至三个)指令:
movzxb
(-1(%rbp)
是一个字节长)和 movzxw
(-1(%rbp)
是一个 16 位字长)。
我的汇编程序将 movzx
解释为 movzxb
;但是,您不应该依赖它!
最好使用包含源代码大小的指令名称(movzxb
或 movzxw
)以确保汇编程序使用正确的指令。
它有歧义并且依赖于一些默认值,你不应该这样写代码。
这就是为什么 AT&T 语法有 movzb
和 movzw
指令(通常用作 movzbl -1(%rbp), %eax
),用于 Intel-syntax [=16= 的两种不同的源大小】 助记。参见 (不,AT&T 编造了新名称。)
是的,您 可以 xor %eax,%eax
/ mov -1(%rbp), %al
合并到低字节,但那毫无意义地低效。 x86-64保证像movzx.
这样的386指令的可用性
令人惊讶的是,movzx -1(%rbp), %rax
assemble。如果你 assemble 它,然后用 objdump -d foo.o
disassemble 回到 AT&T 语法,你会得到 movzbq
(字节到四边形),包括一个无用的 REX 前缀而不是让 implicit zero-extension do the job 写入 EAX 之后。
48 0f b6 45 ff movzbq -0x1(%rbp),%rax
或将 assemble 转换为英特尔语法 objdump -drwC -Mintel
:
48 0f b6 45 ff movzx rax,BYTE PTR [rbp-0x1]
有趣的事实:如果您只写 movz
,GAS 无法推断 movzb
与 movzw
,因为 movz
不是指令助记符。与可以从操作数推断出的 operand-size 后缀不同,b
和 w
被视为助记符的一部分。但是你可以写 movzx
然后它会从寄存器操作数中推断出两种大小,就像在 Intel-syntax 模式中一样。
5: 0f b6 c0 movzbl %al,%eax # source: movzx %al, %eax
8: 0f b7 c0 movzwl %ax,%eax # source: movzx %ax, %eax
movzw
和 movzb
本身就像指令助记符(可以从目标寄存器推断大小后缀)。 Semi-related: What does the MOVZBL instruction do in IA-32 AT&T syntax?
也相关:cdq 的 table 等 movsx
和 AT&T 等价物:What does cltq do in assembly?
也相关:MOVZX missing 32 bit register to 64 bit register - 因为这隐含在编写 32 位寄存器中。
我已经存储了 8
的一个字节值,我想将其移入 rax
寄存器。我目前正在使用 movzx
对字节进行零扩展:
.globl main
main:
push %rbp
mov %rsp, %rbp
movb , -1(%rbp)
movzx -1(%rbp), %rax <-- here
...
movzx
指令'know'如何让-1(%rbp)
处的值只有一个字节长?从这里说,如果我正确阅读它,它可以在 byte
和 word
上工作,但它怎么知道呢?例如,如果我在 -2(%rbp)
处添加了一个两字节的值,它怎么知道要获取这两个字节的值?是否有另一条指令,我可以在地址处获取 one
或 two
或 four
字节值并将其插入 64 位寄存器?
我想另一种方法是先将寄存器清零,然后将其添加到 8 位(或多少位)组件中,例如:
mov [=11=], %rax
mov -1(%rbp), %al
有没有一种方法比另一种方法更受欢迎?
How does the
movzx
instruction 'know' that the value at-1(%rbp)
is only one byte long?
有两个(甚至三个)指令:
movzxb
(-1(%rbp)
是一个字节长)和 movzxw
(-1(%rbp)
是一个 16 位字长)。
我的汇编程序将 movzx
解释为 movzxb
;但是,您不应该依赖它!
最好使用包含源代码大小的指令名称(movzxb
或 movzxw
)以确保汇编程序使用正确的指令。
它有歧义并且依赖于一些默认值,你不应该这样写代码。
这就是为什么 AT&T 语法有 movzb
和 movzw
指令(通常用作 movzbl -1(%rbp), %eax
),用于 Intel-syntax [=16= 的两种不同的源大小】 助记。参见
是的,您 可以 xor %eax,%eax
/ mov -1(%rbp), %al
合并到低字节,但那毫无意义地低效。 x86-64保证像movzx.
令人惊讶的是,movzx -1(%rbp), %rax
assemble。如果你 assemble 它,然后用 objdump -d foo.o
disassemble 回到 AT&T 语法,你会得到 movzbq
(字节到四边形),包括一个无用的 REX 前缀而不是让 implicit zero-extension do the job 写入 EAX 之后。
48 0f b6 45 ff movzbq -0x1(%rbp),%rax
或将 assemble 转换为英特尔语法 objdump -drwC -Mintel
:
48 0f b6 45 ff movzx rax,BYTE PTR [rbp-0x1]
有趣的事实:如果您只写 movz
,GAS 无法推断 movzb
与 movzw
,因为 movz
不是指令助记符。与可以从操作数推断出的 operand-size 后缀不同,b
和 w
被视为助记符的一部分。但是你可以写 movzx
然后它会从寄存器操作数中推断出两种大小,就像在 Intel-syntax 模式中一样。
5: 0f b6 c0 movzbl %al,%eax # source: movzx %al, %eax
8: 0f b7 c0 movzwl %ax,%eax # source: movzx %ax, %eax
movzw
和 movzb
本身就像指令助记符(可以从目标寄存器推断大小后缀)。 Semi-related: What does the MOVZBL instruction do in IA-32 AT&T syntax?
也相关:cdq 的 table 等 movsx
和 AT&T 等价物:What does cltq do in assembly?
也相关:MOVZX missing 32 bit register to 64 bit register - 因为这隐含在编写 32 位寄存器中。