【新书推荐】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…

ROS方向第二次总汇报

文章目录 1.本阶段学习内容&#xff1a;2.过程中遇到的问题及解决方法&#xff1a; 本篇链接:https://blog.csdn.net/m0_54470078/article/details/136019940?spm1001.2014.3001.5501 本人主页::https://blog.csdn.net/m0_54470078?spm1011.2124.3001.5343 1.本阶段学习内容&…

使用Rsync软件工具将Linux服务器上的文件同步到Windows 服务器

使用Rsync软件工具将linux服务器上的文件同步到Windows 服务器 测试环境&#xff08;推送&#xff1a;Linux 推送到Windows&#xff09;&#xff1a; Windows 服务器&#xff1a;172.20.26.97 Linux服务器&#xff1a;172.20.26.34 一、在172.20.26.97上安装cwRsyncServer-v…

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

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

React Hook之钩子调用规则(不在循环、条件判断或者嵌套函数中调用)

文章目录 React Hook之钩子调用规则&#xff08;不在循环、条件判断或者嵌套函数中调用&#xff09;错误使用案例案例具体解决方法 React Hook之钩子调用规则&#xff08;不在循环、条件判断或者嵌套函数中调用&#xff09; hooks使用规则 只能在函数最外层调用 Hook。不要在…

八、测试分析报告(软件工程)

1&#xff0e;引言 1.1编写目的 1.2项目背景 1.3定义 1.4参考资料 2&#xff0e;测试计划执行情况 2.1测试项目 2.2测试机构和人员 2.3测试结果 3&#xff0e;软件需求测试结论 4&#xff0e;评价 4.1软件能力 4.2缺陷和限制 4.3建议 4.4测试结论 …

字面跳动前端面试题:React Hook为什么不能放在if/循环/嵌套函数里面?

答&#xff1a;首先&#xff0c;React Hooks 是为了简化组件逻辑和提高代码可读性而设计的。将 Hook 放在 if/循环/嵌套函数中会破坏它们的封装性和可预测性&#xff0c;使得代码更难维护和理解。同时&#xff0c;这样做也增加了代码的复杂度&#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的…

美敦力呼吸机PB560硬件分析

1 硬件主要芯片 CPU板的MCU和电源板的MCU通过SPI-0通信。 1.1 CPU板 1&#xff09;ST10F276&#xff0c;16bit MCU 2&#xff09;K6R4016C1D-UI10&#xff0c;Samsung 256K x 16 SRAM&#xff0c;Event Memory 3&#xff09;K9F1G08UOA-PCB0&#xff0c;Samsung 128M x 8 NAND …

修复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…

Nginx如何对运行老业务的服务器平滑升级版本

Nginx如何对运行老业务的服务器平滑升级版本 Nginx是一个开源的、高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP代理服务器。在本文中&#xff0c;我们将讨论如何在不影响现有业务的情况下&#xff0c;对运行老业务的服务器进行Nginx版本的平滑升级。 1. …

学习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;地图的每个坐…