1.相关的汇编指令
1.movsx:有符号扩展,就是将扩展后的最高位(符号位),对应SF标志位的内容,填充到扩展的高位部分
2.movzx:无符号扩展就是直接用0去填充扩展的高位部分
2.无符号代码验证
#include"stdio.h"
int main()
{
unsigned char a = 0xff;
printf("%d\n", a);
int b;
b = a + 1;
printf("%d\n", b);
a = a + 1;
printf("%d\n", a);
return 0;
}
结果
查看相应的汇编代码
2: int main()
3: {
00A33E60 55 push ebp
00A33E61 8B EC mov ebp,esp
00A33E63 81 EC D8 00 00 00 sub esp,0D8h
00A33E69 53 push ebx
00A33E6A 56 push esi
00A33E6B 57 push edi
00A33E6C 8D 7D E8 lea edi,[ebp-18h]
00A33E6F B9 06 00 00 00 mov ecx,6
00A33E74 B8 CC CC CC CC mov eax,0CCCCCCCCh
00A33E79 F3 AB rep stos dword ptr es:[edi]
00A33E7B B9 08 C0 A3 00 mov ecx,offset _D9388DD4_size@cpp (0A3C008h)
00A33E80 E8 82 D4 FF FF call @__CheckForDebuggerJustMyCode@4 (0A31307h)
4: unsigned char a = 0xff;
00A33E85 C6 45 FB FF mov byte ptr [a],0FFh
5: printf("%d\n", a);
00A33E89 0F B6 45 FB movzx eax,byte ptr [a]
00A33E8D 50 push eax
00A33E8E 68 CC 7B A3 00 push offset string "%d\n" (0A37BCCh)
00A33E93 E8 0A D5 FF FF call _printf (0A313A2h)
00A33E98 83 C4 08 add esp,8
6: int b;
7: b = a + 1;
00A33E9B 0F B6 45 FB movzx eax,byte ptr [a]
00A33E9F 83 C0 01 add eax,1
00A33EA2 89 45 EC mov dword ptr [b],eax
8: printf("%d\n", b);
00A33EA5 8B 45 EC mov eax,dword ptr [b]
00A33EA8 50 push eax
00A33EA9 68 CC 7B A3 00 push offset string "%d\n" (0A37BCCh)
00A33EAE E8 EF D4 FF FF call _printf (0A313A2h)
00A33EB3 83 C4 08 add esp,8
9: a = a + 1;
00A33EB6 0F B6 45 FB movzx eax,byte ptr [a]
00A33EBA 83 C0 01 add eax,1
00A33EBD 88 45 FB mov byte ptr [a],al
10: printf("%d\n", a);
00A33EC0 0F B6 45 FB movzx eax,byte ptr [a]
00A33EC4 50 push eax
00A33EC5 68 CC 7B A3 00 push offset string "%d\n" (0A37BCCh)
00A33ECA E8 D3 D4 FF FF call _printf (0A313A2h)
00A33ECF 83 C4 08 add esp,8
11: return 0;
00A33ED2 33 C0 xor eax,eax
12: }
a.最初的char类型的变量的长度是byte
b.类型转换中char类型向int类型转换
使用到了movzx指令,实现了无符号扩展,此时eax中的值为 0x00ff
随后加一,并将eax中的值 0x0100 赋给b,
所以最终b值为256
c.char 类型的无符号溢出
同样的先使用movzx进行无符号扩展
不过与b不同的点在于,将al寄存其中的值赋给了a,也就是0x0100的后两位 00
所以最后a 的值为0
3.有符号代码验证
#include"stdio.h"
int main()
{
char a = 0xff;
printf("%d\n", a);
int b;
b = a + 1;
printf("%d\n", b);
a = a + 1;
printf("%d\n", a);
return 0;
}
代码
汇编代码
2: int main()
3: {
00983E60 55 push ebp
00983E61 8B EC mov ebp,esp
00983E63 81 EC D8 00 00 00 sub esp,0D8h
00983E69 53 push ebx
00983E6A 56 push esi
00983E6B 57 push edi
00983E6C 8D 7D E8 lea edi,[ebp-18h]
00983E6F B9 06 00 00 00 mov ecx,6
00983E74 B8 CC CC CC CC mov eax,0CCCCCCCCh
00983E79 F3 AB rep stos dword ptr es:[edi]
00983E7B B9 08 C0 98 00 mov ecx,offset _D9388DD4_size@cpp (098C008h)
00983E80 E8 82 D4 FF FF call @__CheckForDebuggerJustMyCode@4 (0981307h)
4: char a = 0xff;
00983E85 C6 45 FB FF mov byte ptr [a],0FFh
5: printf("%d\n", a);
00983E89 0F BE 45 FB movsx eax,byte ptr [a]
00983E8D 50 push eax
00983E8E 68 CC 7B 98 00 push offset string "%d\n" (0987BCCh)
00983E93 E8 0A D5 FF FF call _printf (09813A2h)
00983E98 83 C4 08 add esp,8
6: int b;
7: b = a + 1;
00983E9B 0F BE 45 FB movsx eax,byte ptr [a]
00983E9F 83 C0 01 add eax,1
00983EA2 89 45 EC mov dword ptr [b],eax
8: printf("%d\n", b);
00983EA5 8B 45 EC mov eax,dword ptr [b]
00983EA8 50 push eax
00983EA9 68 CC 7B 98 00 push offset string "%d\n" (0987BCCh)
00983EAE E8 EF D4 FF FF call _printf (09813A2h)
00983EB3 83 C4 08 add esp,8
9: a = a + 1;
00983EB6 0F BE 45 FB movsx eax,byte ptr [a]
00983EBA 83 C0 01 add eax,1
00983EBD 88 45 FB mov byte ptr [a],al
10: printf("%d\n", a);
00983EC0 0F BE 45 FB movsx eax,byte ptr [a]
00983EC4 50 push eax
00983EC5 68 CC 7B 98 00 push offset string "%d\n" (0987BCCh)
00983ECA E8 D3 D4 FF FF call _printf (09813A2h)
00983ECF 83 C4 08 add esp,8
11: return 0;
00983ED2 33 C0 xor eax,eax
12: }
此处char型变量a中值最初是0xff,此时的符号位为1
使用movsx指令进行有符号扩展后将值存入eax中,eax中保存的值为0xffff
eax加1之后,发生溢出,此时eax中保存的值为0x0000
所以最终b中的值为0
此处同理,在eax进行带符号扩建并加1操作之后,eax值为0x0000,此时的al中的值为0x00.
所以最终a 中的值为0