如何在英特尔汇编中添加 2 个无符号的 1 字节数字?
How do I add 2 unsigned 1 byte numbers in Intel assembly?
我刚开始自学编写汇编。
如何在 x86_64 上使用 linux 添加两个 1 字节整数。
学习汇编的一种方法是用高级语言(例如 C)编写您希望处理器执行的操作,然后查看编译器生成的内容。
unsigned char addition (unsigned char a, unsigned char b)
{
return a+b;
}
有时这会导致一些奇怪但有效的汇编结构:
movzbl -4(%rbp), %edx ;a
movzbl -8(%rbp), %eax ;b
leal (%rdx,%rax), %eax ;return a+b
这一次,LEA
指令用于将存储在64位寄存器中的两个8位数字相加,而不是预期的ADD
指令。关键是这些寄存器已经使用 MOVZX
指令进行了初始化,该指令将所有未使用的位(直到位 31)填充为 0。使用 Intel 语法编写的相同示例如下所示:
movzx eax,[rbp-8] ; A -> eax
movzx edx,[rbp-4] ; B -> edx
lea eax,[rax+rdx] ; A+B -> eax
在只初始化了32位寄存器的情况下,添加64位寄存器会觉得很奇怪。考虑到第 8 位到第 31 位已使用 MOVZX
指令初始化为 0,因此 RAX
的上半部分发生的任何事情都不重要。 RAX 的低 8 位将包含我们加法的 8 位结果(可能溢出,也可能不溢出)
Visual Studio,当没有启用优化时,生成一个更"predecible"版本的这个函数的汇编版本,你可以研究它,连同它的原始C代码:
注意:这是使用 32 位代码生成编译的。
unsigned char addition (unsigned char a, unsigned char b)
{
00EA10A0 push ebp
00EA10A1 mov ebp,esp
return a+b;
00EA10A3 movzx eax,byte ptr [ebp+8]
00EA10A7 movzx ecx,byte ptr [ebp+0Ch]
00EA10AB add eax,ecx
}
00EA10AD pop ebp
00EA10AE ret
两个编译器都尝试使用其完整大小的寄存器,即使实际上只需要其中的一小部分,这导致两者最终都使用 MOVZX 指令将 8 位值加载到更大的寄存器中。使用带符号的字符,您将看到会发生什么。
我刚开始自学编写汇编。
如何在 x86_64 上使用 linux 添加两个 1 字节整数。
学习汇编的一种方法是用高级语言(例如 C)编写您希望处理器执行的操作,然后查看编译器生成的内容。
unsigned char addition (unsigned char a, unsigned char b)
{
return a+b;
}
有时这会导致一些奇怪但有效的汇编结构:
movzbl -4(%rbp), %edx ;a
movzbl -8(%rbp), %eax ;b
leal (%rdx,%rax), %eax ;return a+b
这一次,LEA
指令用于将存储在64位寄存器中的两个8位数字相加,而不是预期的ADD
指令。关键是这些寄存器已经使用 MOVZX
指令进行了初始化,该指令将所有未使用的位(直到位 31)填充为 0。使用 Intel 语法编写的相同示例如下所示:
movzx eax,[rbp-8] ; A -> eax
movzx edx,[rbp-4] ; B -> edx
lea eax,[rax+rdx] ; A+B -> eax
在只初始化了32位寄存器的情况下,添加64位寄存器会觉得很奇怪。考虑到第 8 位到第 31 位已使用 MOVZX
指令初始化为 0,因此 RAX
的上半部分发生的任何事情都不重要。 RAX 的低 8 位将包含我们加法的 8 位结果(可能溢出,也可能不溢出)
Visual Studio,当没有启用优化时,生成一个更"predecible"版本的这个函数的汇编版本,你可以研究它,连同它的原始C代码:
注意:这是使用 32 位代码生成编译的。
unsigned char addition (unsigned char a, unsigned char b)
{
00EA10A0 push ebp
00EA10A1 mov ebp,esp
return a+b;
00EA10A3 movzx eax,byte ptr [ebp+8]
00EA10A7 movzx ecx,byte ptr [ebp+0Ch]
00EA10AB add eax,ecx
}
00EA10AD pop ebp
00EA10AE ret
两个编译器都尝试使用其完整大小的寄存器,即使实际上只需要其中的一小部分,这导致两者最终都使用 MOVZX 指令将 8 位值加载到更大的寄存器中。使用带符号的字符,您将看到会发生什么。