【新书推荐】5.2 位运算符

本节必须掌握的知识点:

   位运算

   示例十七

   代码分析

   汇编解析

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;

<<左移运算

0x01<<1左移表示,所有的位向左移一位,右侧补0

0

0

0

0

0

0

0

1

 向左移一位

0

0

0

0

0

0

1

0

0xEF<<3左移表示,所有的位向左移三位,右侧补0

1

1

1

0

1

1

1

1

向左移三位

0

1

1

1

1

0

0

0

>>右移运算

0x01>>1右移表示,所有的位向左移一位,左侧补0

0

0

0

0

0

0

0

1

向右移一位

0

0

0

0

0

0

0

0

有符号数0xEF>>3右移表示,所有的位向左移一位,有符号左侧补符号位。

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语言》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/666539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【lesson38】让minishell支持重定向

文章目录 minishell支持重定向minishell完整代码 minishell支持重定向 支持重定向的核心逻辑&#xff1a; 1.分析字符串是否含有重定向的符号&#xff0c;并且提取文件名。 #define INPUT_REDIR 0 //输入重定向 #define OUTPUT_REDIR 1 //输出重定向 #define APPEND_REDIR…

电脑上常见的绘图软件有哪些?

现在在电脑上绘图很流行&#xff0c;不仅可以随时更改&#xff0c;还可以提高绘图效率&#xff0c;绘图软件中有很多工具。市场上的计算机绘图软件种类繁多。包括艺术设计、工业绘图和3D绘图。那么每个绘图软件都有自己的特点。那么&#xff0c;哪个更适合计算机绘画软件呢&…

路由器、路由器的构成、交换结构

目录 1 路由器 1.1 路由器的结构 “转发”和“路由选择”的区别 1.1.1 输入端口对线路上收到的分组的处理 1.1.2 输出端口将交换结构传送来的分组发送到线路 2.2 交换结构 2.2.1 通过存储器 2.2.2 通过总线 2.2.3 通过纵横交换结构 (crossbar switch fabric) 1 路由器…

算法练习-环形链表(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;链表 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0c;旨在…

用Jmeter进行接口测试

web接口测试工具&#xff1a; 手工测试的话可以用postman &#xff0c;自动化测试多是用到 Jmeter&#xff08;开源&#xff09;、soupUI&#xff08;开源&商业版&#xff09;。 下面将对前一篇Postman做接口测试中的接口用Jmeter来实现。 一、Jmeter 的使用步骤 打开Jme…

SpringCloud Gateway(4.1.0) 返回503:原因分析与解决方案

文章目录 一、环境版本二、原因分析三、解决方案 一、环境版本 Versionspring-cloud-dependencies2023.0.0spring-cloud-starter-gateway4.1.0Nacosv2.3.0 二、原因分析 在 Spring Cloud Gateway 的早期版本中&#xff0c;Ribbon 被用作默认的负载均衡器。随着Spring Cloud的…

修复wordpress安全漏洞

1. 问题描述&#xff1a; 用wordpress建了一个网站&#xff0c;但是学校反映说存在安全漏洞&#xff0c;通过接口https://xxx.xxx.edu.cn/?rest_route/wp/v2/users/可以访问到一些内容&#xff0c;希望可以关闭这个接口。 2. 解决办法 一共两步 &#xff08;1&#xff09;在fu…

系统架构20 - 统一建模语言UML(上)

统一建模语言 组成要素事物关系 在目前的软件开发方法中&#xff0c;面向对象的方法占据着主导地位。面向对象方法的主导地位也决定着软件开发过程模型化技术的发展&#xff0c;面向对象的建模技术方法也就成为主导的方法。 公认的面向对象建模语言出现于20世纪70年代中期。从1…

vulhub中Adminer ElasticSearch 和 ClickHouse 错误页面SSRF漏洞复现(CVE-2021-21311)

Adminer是一个PHP编写的开源数据库管理工具&#xff0c;支持MySQL、MariaDB、PostgreSQL、SQLite、MS SQL、Oracle、Elasticsearch、MongoDB等数据库。 在其4.0.0到4.7.9版本之间&#xff0c;连接 ElasticSearch 和 ClickHouse 数据库时存在一处服务端请求伪造漏洞&#xff08…

学习ArtTs -- 初见ArkTs

作者&#xff1a;Uncle_Tom 原文链接&#xff1a;学习ArtTs -- 初见ArkTs-云社区-华为云 1. 前言 需要静态分析去检查一个语言&#xff0c;必须对这个语言有深刻的认识&#xff0c;才能有效的对这个语言进行有效的检查。 我常说:“作为一个程序分析员需要比一般的程序员考虑…

反演LAI(二)基于查找表的反演

反演LAI(二)基于查找表的反演 相关波段选取 首先我们使用gf-1数据有四个波段,使用其他高光谱会有几十个波段,但并不是所有波段都需要选用,lai对于不同波段的响应不同。根据上一节的敏感性分析结果,可以发现,400-500,600-700的两个波段对于LAI敏感性更大,因此选取这两…

【人工智能时代】AI赋能编程 | 自动化工具助力高效办公

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言泡泡AI工具卡片思维导图Markdown编辑器 其他工具文件免费处理工具结语 合集…

【C/C++ 11】贪吃蛇游戏

一、题目 贪吃蛇游戏机制是通过控制蛇上下左右移动并吃到食物得分。 蛇头碰到墙壁或者碰到蛇身就游戏结束。 食物随机生成&#xff0c;蛇吃到食物之后蛇身变长&#xff0c;蛇速加快。 二、算法 1. 初始化游戏地图并打印&#xff0c;地图的边缘是墙&#xff0c;地图的每个坐…

Python tkinter (14) —— 按键事件

本文主要介绍Python tkinter 几种按键事件及其示例。 目录 按键事件 响应所有按键事件 窗体绑定事件 响应特殊按键事件 指定按键事件 组合按键事件 总结 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— But…

Kafka相关内容复习

为什么要用消息队列 解耦 允许你独立的扩展或修改两边的处理过程&#xff0c;只要确保它们遵守同样的接口约束。 可恢复性 系统的一部分组件失效时&#xff0c;不会影响到整个系统。消息队列降低了进程间的耦合度&#xff0c;所以即使一个处理消息的进程挂掉&#xff0c;加入队…

Transformer 自然语言处理(三)

原文&#xff1a;Natural Language Processing with Transformers 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第八章&#xff1a;使 transformers 在生产中更高效 在之前的章节中&#xff0c;您已经看到了 transformers 如何被微调以在各种任务上产生出色的结果。…

AI 数字人从制作到变现

最近AI很火&#xff0c;无意中发现一个宝藏专栏《AI数字人从制作到变现》&#xff0c;原价599&#xff0c;现在推广阶段&#xff0c;只需要10元&#xff0c;专栏持续更新中&#xff0c;会有更多的知识后续分享。如有兴趣可以用微信扫描左侧海报二维码&#xff0c;下面我将介绍专…

『运维备忘录』之 Cron 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

计算机设计大赛 深度学习 机器视觉 人脸识别系统 - opencv python

文章目录 0 前言1 机器学习-人脸识别过程人脸检测人脸对其人脸特征向量化人脸识别 2 深度学习-人脸识别过程人脸检测人脸识别Metric Larning 3 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 人脸识别系统 该项目…

ping 不支持代理,命令行测试外网网址请使用 curl 测试,如何测试?

如果你想通过命令行测试外网网址的可达性&#xff0c;并且因为 ping 命令不支持通过代理服务器进行操作&#xff0c;你可以使用 curl 命令来测试。curl 是一个强大的工具&#xff0c;可以用来传输数据&#xff0c;它支持多种协议&#xff0c;包括 HTTP、HTTPS 等&#xff0c;而…