自己建设网站麻烦吗,附近广告设计与制作门店电话,海外网站推广方法,中学加强校园网站建设本节必须掌握的知识点#xff1a; 位运算 示例十七 代码分析 汇编解析
5.2.1 位运算
位运算符如表5-2所示#xff1a; 运算符 作用 示例 按位与 两个操作数同时为1#xff0c;结果为1#xff1b; | 按位或 两个操作数只要有一个为1#xff0c;结果就为1 位运算 示例十七 代码分析 汇编解析
5.2.1 位运算
位运算符如表5-2所示 运算符 作用 示例 按位与 两个操作数同时为1结果为1 | 按位或 两个操作数只要有一个为1结果就为1 ~ 按位非 操作数为1结果为0操作数为0结果就为1 ^ 按位异或 两个操作数相同结果为0不相同结果为1 左移 右侧空位补0 右移 左侧空位补符号位 无符号右移 左侧空位补0 表5-2位运算符 所有的位运算只适用于char、short、int、unsigned char、unsigned short、unsigned int整型数据类型。位运算需要按位表示例如unsigned char c 07h。
把变量c按位表示【最左侧为最高位第7位最右侧为最低位第0位】。 0 0 0 0 0 1 1 1 ■按位与运算 语法格式expr1 expr2;两个操作数同时为1结果为1。 | 按位或运算
语法格式expr 1 | expr2;两个操作数只要有一个为1结果就为1。 ■~按位非运算
语法格式~expr 1;操作数为1结果为0操作数为0结果就为1。 ■^按位异或运算
语法格式expr 1 ^ expr 2 ;两个操作数相同结果为0不相同结果为1 ■左移运算
0x011左移表示所有的位向左移一位右侧补0 0 0 0 0 0 0 0 1 向左移一位 0 0 0 0 0 0 1 0 0xEF3左移表示所有的位向左移三位右侧补0 1 1 1 0 1 1 1 1 向左移三位 0 1 1 1 1 0 0 0 ■右移运算
0x011右移表示所有的位向左移一位左侧补0 0 0 0 0 0 0 0 1
向右移一位 0 0 0 0 0 0 0 0 有符号数0xEF3右移表示所有的位向左移一位有符号左侧补符号位。 1 1 1 0 1 1 1 1 向右移三位 1 1 1 1 1 1 0 1 5.2.2 示例十七 /* 位运算符
*/
#include stdio.h
#include stdlib.h int main(void) { char c1 0x01;//十六进制数 char c2 0xEF; printf(%d\n, c1 c2);//与运算 printf(%d\n, c1 | c2);//或运算 printf(%d\n, ~c1); //非运算 printf(%d\n, c1 ^ c2);//异或运算 printf(%d\n, c1 1);//左移 printf(%d\n, c2 3);//右移 system(pause); return 0;
}
●输出结果
1
-17
-2
-18
2
-3
5.2.3 代码分析
示例代码非常简单分别输出两个char类型变量c1和c2与运算、或运算、非运算、异或运算、左移和右移的结果。
5.2.4 汇编解析
■汇编代码
;C标准库头文件和导入库
include vcIO.inc .data
c1 sbyte 1
c2 sbyte 0EFh
.const
szMsg db %d,0dh,0ah,0
.code
start: movsx eax,sbyte ptr c1 movsx ebx,sbyte ptr c2 and eax,ebx invoke printf,offset szMsg,eax;输出结果 ; movsx eax,sbyte ptr c1 movsx ebx,sbyte ptr c2 or eax,ebx invoke printf,offset szMsg,eax;输出结果 ; movsx eax,sbyte ptr c1 not eax invoke printf,offset szMsg,eax;输出结果 ; movsx eax,sbyte ptr c1 movsx ebx,sbyte ptr c2 xor eax,ebx invoke printf,offset szMsg,eax;输出结果 ; movsx eax,sbyte ptr c1 shl eax,1 invoke printf,offset szMsg,eax;输出结果 ; movsx eax,sbyte ptr c2 sar eax,3 invoke printf,offset szMsg,eax;输出结果 ; invoke _getch ret
end start
输出结果
1
-17
-2
-18
2
-3 上述汇编代码需要关注以下几点 变量c1和c2的数据类型为sbyte 8位有符号整型。因为printf函数的参数入栈为32位因此需要使用movsx指令将变量c1和c2的符号位扩展为32位然后再进行位运算。汇编指令and与运算or或运算not非运算xor异或运算。 接下来的移位指令shl为左移指令将eax的所有数据位左移1位。sar右移指令为有符号数右移指令将eax的所有数据位右移3位左侧最高位填充符号位。
【注意】masm32汇编器不支持0x作为前缀的十六进制数格式改用后缀h表示十六进制数。
■反汇编代码 char c1 0x01;//十六进制数
00FA1838 mov byte ptr [c1],1 char c2 0xEF;
00FA183C mov byte ptr [c2],0EFh printf(%d\n, c1 c2);//与运算
00FA1840 movsx eax,byte ptr [c1]
00FA1844 movsx ecx,byte ptr [c2]
00FA1848 and eax,ecx
00FA184A push eax
00FA184B push offset string %d\n (0FA7B30h)
00FA1850 call _printf (0FA104Bh)
00FA1855 add esp,8 printf(%d\n, c1 | c2);//或运算
00FA1858 movsx eax,byte ptr [c1]
00FA185C movsx ecx,byte ptr [c2]
00FA1860 or eax,ecx
00FA1862 push eax
00FA1863 push offset string %d\n (0FA7B30h)
00FA1868 call _printf (0FA104Bh)
00FA186D add esp,8 printf(%d\n, ~c1); //非运算
00FA1870 movsx eax,byte ptr [c1]
00FA1874 not eax
00FA1876 push eax
00FA1877 push offset string %d\n (0FA7B30h)
00FA187C call _printf (0FA104Bh)
00FA1881 add esp,8 printf(%d\n, c1 ^ c2);//异或运算
00FA1884 movsx eax,byte ptr [c1]
00FA1888 movsx ecx,byte ptr [c2]
00FA188C xor eax,ecx
00FA188E push eax
00FA188F push offset string %d\n (0FA7B30h)
00FA1894 call _printf (0FA104Bh)
00FA1899 add esp,8 printf(%d\n, c1 1);//左移
00FA189C movsx eax,byte ptr [c1] printf(%d\n, c1 1);//左移
00FA18A0 shl eax,1
00FA18A2 push eax
00FA18A3 push offset string %d\n (0FA7B30h)
00FA18A8 call _printf (0FA104Bh)
00FA18AD add esp,8 printf(%d\n, c2 3);//右移
00FA18B0 movsx eax,byte ptr [c2]
00FA18B4 sar eax,3
00FA18B7 push eax
00FA18B8 push offset string %d\n (0FA7B30h)
00FA18BD call _printf (0FA104Bh)
00FA18C2 add esp,8
上述反汇编代码中调用printf函数使用push/call指令movsx语句中使用byte ptr指定数据类型其余反汇编代码与汇编代码相同不再赘述。
练习
1、
int a -1;
int b a 3;
求变量b最后的值
int c 0;
int d !c;
求变量d最后的值 2、请写出下出对应的C语言代码。
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,48h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-48h]
0040101C mov ecx,12h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
00401028 mov dword ptr [ebp-4],0
0040102F xor eax,eax
00401031 cmp dword ptr [ebp-4],0
00401035 sete al
00401038 mov ecx,dword ptr [ebp-4]
0040103B add ecx,eax
0040103D mov dword ptr [ebp-8],ecx
00401040 push offset string pause (0042201c)
00401045 call system (00401090)
0040104A add esp,4
0040104D xor eax,eax
3、
int a 7;
int b ( a 4 4 ? 12 : 13);
本文摘自编程达人系列教材《汇编的角度——C语言》。