movsbl 和 movzbl 是 mov 指令的两个扩展形式。
考虑两种情形的 C 代码以及相应的汇编代码:
movzbl
点击(此处)折叠或打开
-
unsigned char c = 0xA5;
- unsigned int a = c
汇编代码
点击(此处)折叠或打开
-
movb $-91, -1(%ebp)
- movzbl -1(%ebp), %eax
在这种情形下,我们将一个 unsigned char 类型的变量赋值给一个 unsigned int 类型的变量。编译器对待这种情况,一个原则是尽可能保留表达式中涉及的值的精度,就如同你用一个 double 型和一个 int 型相加时,int 型要转化为 double 型才相加,这种类型提升的道理同样适用于上面的情况,即将 unsigned char 型扩展为 unsigned int 型,因此此时 movzbl 的意思,传送数值(十进制 -91 为 0xA5 的有符号形式所转化为的十进制),并将高位的 3 个字节用 0 扩展(指令中的 z 就是 zero 之意),所以这种方式也称为“零扩展”。
movsbl
点击(此处)折叠或打开
-
char c = 0xA5;
- int a = c
汇编代码
点击(此处)折叠或打开
-
movb $-91, -1(%ebp)
- movsbl -1(%ebp), %eax
对于上面的情形,是将一个 char 型赋值给一个 int 型,char 型和 int 型默认是有符号的。比如 0x80 不会被认为是 128,而是被认为是 -1 。因此,在这种情况下,在赋值时需要进行符号位扩展,即将高 3 个字节用 C 的最高位来填充,如果是 c 的最高位是 0 那么就用 0 来填充,如果 c 的最高位是 1 就用 1 来填充。