网站建设能做什么工作,河北网络公司排名,微信平台APP网站建设怎么样,官方网站建设情况第五章 逻辑运算 本章讲解逻辑运算符与逻辑运算#xff0c;移位运算符与移位运算。
本章学习知识概要#xff1a; 逻辑运算符 位运算符
5.1 逻辑运算符
本节必须掌握的知识点#xff1a; 示例十六 代码分析 汇编解析
5.1.1 示例十六
逻辑运算符包括逻辑与、逻辑或、逻辑…第五章 逻辑运算 本章讲解逻辑运算符与逻辑运算移位运算符与移位运算。
本章学习知识概要 逻辑运算符 位运算符
5.1 逻辑运算符
本节必须掌握的知识点 示例十六 代码分析 汇编解析
5.1.1 示例十六
逻辑运算符包括逻辑与、逻辑或、逻辑非如表5-1所示。 运算符 表达式 说明 逻辑与并且 条件1条件2 两个条件同时为真时结果为真 ||逻辑或或 条件1||条件2 两个条件有一个为真时结果为真 逻辑非非 条件 条件为真时结果为假 条件为假时结果为真 表5-1逻辑运算符
■逻辑与
语法格式expr1 expr2;
当两个条件同时为真时结果为真否则为假。在C语言中非0为真0为假。
举例
1 2 //真真 --结果为真
0 1 //假真 --结果为假当expr1为假时将直接返回假不会再计算expr2。
-1 0 //真假 --结果为假
23 2 //假真 --结果为假当expr1为假时将直接返回假不会再计算expr2。
■||逻辑或
语法格式expr1 || expr2;
当两个条件有一个为真时结果为真否则为假。
举例
0 || 1 //假||真 --结果为真当expr1为假时会继续计算expr2。
0 || 0 //假||假 --结果为假当expr1为假时会继续计算expr2expr2为假则为假两个条件都为假时结果为假。
■逻辑非
语法格式expr当条件为真时结果为假当条件为假时结果为真。
举例
0 //假 --结果为真
1 //真 --结果为假
(12) //假 --结果为真
■德摩根定律
对各条件取非然后将逻辑与变为逻辑或逻辑或变为逻辑与然后再取其否定结果和原条件一样。
举例
x y 和 !(! x || !y )相等
x || y 和 !(! x !y )相等
【注意】单目运算符 ‘-’取补码单目运算符‘~’ 符号取反。
示例代码十六
/* 逻辑运算符
*/
#include stdio.h
#include stdlib.h int main(void) { int x 2,y 4,z 6; int num; printf(请输入一个整数); scanf_s(%d, num); if (y num z num) printf(两个条件表达式同时为真时逻辑与表达式为真\n); if (x num || y num) printf(其中任意一个表达式为真时逻辑或表达式为真\n); if (!num) printf(num为零时逻辑非表达式为真\n); printf(num符号取反之后的值是%d\n, -num); //取num的补码 printf(num补码的值是%d\n, ~num); //num符号取反 system(pause); return 0;
}
输出结果
测试1
请输入一个整数5
两个条件表达式同时为真时逻辑与表达式为真
num补码的值是-5
num符号取反之后的值是-6
测试2
其中任意一个表达式为真时逻辑或表达式为真
num补码的值是-4
num符号取反之后的值是-5
测试3
请输入一个整数0
num为零时逻辑非表达式为真
num补码的值是0
num符号取反之后的值是-1
5.1.2 代码分析 示例十六代码中定义了3个变量xyz。然后有用户输入一个整数值存入变量num中。接下来3个if条件语句中各包含一个逻辑运算符、||、!。如果if语句条件为真使用printf函数输出结果。最后一个printf语句使用单目运算符 “-”符号取反然后输出结果。 当我们需要同时判断多个条件表达式时我们可以使用“”逻辑与运算符或者“||”逻辑或运算符将多个条件表达式连接起来。
如果使用“”逻辑与运算符连接的两个条件表达式同时为真时结果为真如果其中一个条件表达式为假则结果为假。可以尽量选择条件为假可能性较大的表达式前置如果前置条件表达式为假则结果为假后置的条件表达式就无需判断了这样可以提高程序的运行效率。
如果使用“||”逻辑或运算符连接的两个条件表达式只要其中一个为真则结果为真如果两个表达式全部为假则结果为假。我们可以选择条件为真可能性较大的表达式前置当前置表示为真时结果为真后置的表达式就无需判断了。
符号取反单目运算符 ‘~’。取补码运算符‘-’并不是逻辑运算符。
5.1.3 汇编解析
■汇编代码 ;C标准库头文件和导入库
include vcIO.inc .data
x sdword 2
y sdword 4
z sdword 6
num sdword ?
.const
szMsg1 db 请输入一个整数,0
szMsg2 db %d,0
szMsg3 db 两个条件表达式同时为真时逻辑与表达式为真,0dh,0ah,0
szMsg4 db 其中任意一个表达式为真时逻辑或表达式为真,0dh,0ah,0
szMsg5 db num为零时逻辑非表达式为真,0dh,0ah,0
szMsg6 db num符号取反之后的值是%d,0dh,0ah,0
szMsg7 db num补码的值是%d,0dh,0ah,0
.code
start: ;输入整数num invoke printf,offset szMsg1 invoke scanf,offset szMsg2,ADDR num ; mov eax,num .if (y eax) (z eax) invoke printf,offset szMsg3 .endif mov eax,num .if (x eax) || (y eax) invoke printf,offset szMsg4 .endif .if !num invoke printf,offset szMsg5 .endif ;补码 mov eax,num neg eax invoke printf,offset szMsg7,eax;输出结果 ;符号位取反 mov eax,num not eax ;not取反指令,各位取反符号位不变 mov num,eax invoke printf,offset szMsg6,num;输出结果 ; invoke _getch ret
end start 输出结果与C代码相同。 上述汇编代码使用了.if\.else\.endif高级汇编决策伪指令与C语言中的if/else语句基本相同。C语言中的‘-’运算符对应汇编中的neg求补指令。C语言中的‘~’运算符对应汇编not取反指令。
■反汇编代码 int x 2,y 4,z 6;
00EF4ED2 mov dword ptr [x],2 int x 2,y 4,z 6;
00EF4ED9 mov dword ptr [y],4
00EF4EE0 mov dword ptr [z],6 int num; printf(请输入一个整数);
00EF4EE7 push offset string \xc7\xeb\xca\xe4\xc8\xeb\xd2\xbb\xb8\xf6\xd5\xfb\xca\xfd\xa3\xba (0EF7B30h)
00EF4EEC call _printf (0EF104Bh)
00EF4EF1 add esp,4 scanf_s(%d, num);
00EF4EF4 lea eax,[num]
00EF4EF7 push eax
00EF4EF8 push offset string %d (0EF7B48h)
00EF4EFD call _scanf_s (0EF138Eh)
00EF4F02 add esp,8 if (y num z num)
00EF4F05 mov eax,dword ptr [y]
00EF4F08 cmp eax,dword ptr [num]
00EF4F0B jge main82h (0EF4F22h)
00EF4F0D mov eax,dword ptr [z]
00EF4F10 cmp eax,dword ptr [num]
00EF4F13 jle main82h (0EF4F22h) printf(两个条件表达式同时为真时逻辑与表达式为真\n);
00EF4F15 push offset string \xc1\xbd\xb8\xf6\xcc\xf5\xbc\xfe\xb1\xed\xb4\xef\xca\xbd\xcd\xac\xca\xb1\xce\xaa\xd5\xe6\xca\xb1\xa3\xac\xc2\xdf\xbc\xad\xd3... (0EF7E40h)
00EF4F1A call _printf (0EF104Bh)
00EF4F1F add esp,4 if (x num || y num)
00EF4F22 mov eax,dword ptr [x]
00EF4F25 cmp eax,dword ptr [num]
00EF4F28 je main92h (0EF4F32h)
00EF4F2A mov eax,dword ptr [y]
00EF4F2D cmp eax,dword ptr [num]
00EF4F30 jne main9Fh (0EF4F3Fh) printf(其中任意一个表达式为真时逻辑或表达式为真\n);
00EF4F32 push offset string \xc6\xe4\xd6\xd0\xc8\xce\xd2\xe2\xd2\xbb\xb8\xf6\xb1\xed\xb4\xef\xca\xbd\xce\xaa\xd5\xe6\xca\xb1\xa3\xac\xc2\xdf\xbc\xad\xbb... (0EF85E8h)
00EF4F37 call _printf (0EF104Bh)
00EF4F3C add esp,4 if (!num)
00EF4F3F cmp dword ptr [num],0 if (!num)
00EF4F43 jne main0B2h (0EF4F52h) printf(num为零时逻辑非表达式为真\n);
00EF4F45 push offset string num\xce\xaa\xc1\xe3\xca\xb1\xa3\xac\xc2\xdf\xbc\xad\xb7\xc7\xb1\xed\xb4\xef\xca\xbd\xce\xaa\xd5\xe6\xa3\xa1\n (0EF7BECh)
00EF4F4A call _printf (0EF104Bh)
00EF4F4F add esp,4 printf(num补码的值是%d\n, -num);//取num的补码
00EF4F52 mov eax,dword ptr [num]
00EF4F55 neg eax
00EF4F57 push eax
00EF4F58 push offset string num\xb2\xb9\xc2\xeb\xb5\xc4\xd6\xb5\xca\xc7%d\n (0EF7FA4h)
00EF4F5D call _printf (0EF104Bh)
00EF4F62 add esp,8 printf(num符号取反之后的值是%d\n, ~num);//num符号取反
00EF4F65 mov eax,dword ptr [num]
00EF4F68 not eax
00EF4F6A push eax
00EF4F6B push offset string num\xb7\xfb\xba\xc5\xc8\xa1\xb7\xb4\xd6\xae\xba\xf3\xb5\xc4\xd6\xb5\xca\xc7%d\n (0EF7CF8h)
00EF4F70 call _printf (0EF104Bh)
00EF4F75 add esp,8 上述C语言的反汇编代码我们可以清晰的看到C语言中的条件表达式被翻译为CMP/JCC条件判断语句 if (y num z num)
00EF4F05 mov eax,dword ptr [y]
00EF4F08 cmp eax,dword ptr [num]
00EF4F0B jge main82h (0EF4F22h) ;如果ynum则跳转到0EF4F22h地址处
00EF4F0D mov eax,dword ptr [z]
00EF4F10 cmp eax,dword ptr [num]
00EF4F13 jle main82h (0EF4F22h) ;如果znum则跳转到0EF4F22h地址处
…
00EF4F1A call _printf (0EF104Bh)
… if (x num || y num)
00EF4F22 mov eax,dword ptr [x] 结论
1C语言中的条件表达式最终被翻译为汇编语言中的JCC条件判断语句。
2C语言语句和高级汇编的决策伪指令非常相似。
3如果把汇编语言中的寄存器改为编译器自动选取CMP/JCC条件判断语句简化为条件表达式汇编语言就变成了C语言。
本文摘自编程达人系列教材《汇编的角度——C语言》。资料下载www.bcdaren.com