如何在Intel汇编中添加2个无符号1字节数?

时间:2015-03-17 16:11:12

标签: assembly

我刚开始学习自动编写程序集。

如何在x86_64上使用linux添加两个1字节整数。

1 个答案:

答案 0 :(得分: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.使用英特尔语法编写的相同示例如下:

movzx eax,[rbp-8]  ; A -> eax
movzx edx,[rbp-4]  ; B -> edx
lea eax,[rax+rdx]  ; A+B -> eax

可以认为,当只有32位寄存器被初始化时,添加64位寄存器是很奇怪的。考虑到使用MOVZX指令将位8到31初始化为0,RAX的上半部分发生的任何事情都不重要。 RAX的低8位将包含我们添加的8位结果(可能有或没有溢出)

Visual Studio,当没有启用优化时,会生成一个更“可预定”的版本,这个函数的汇编程序版本,你可以学习,以及它的原始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位值加载到更大的寄存器中。使用签名的字符,您将看到会发生什么。