【新书推荐】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语言》。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

参考数据集INRIA Holidays dataset

Download datasets 很贴心,MATLAB访问代码: % This function reads a siftgeo binary file % % Usage: [v, meta] = siftgeo_read (filename, maxdes) % filename the input filename % maxdes maximum number of descriptors to be loaded % (default=unlimit…

MySQL之SQL的查询语句如何执行

文章目录 前言一、一条查询的SQL是如何执行的二、MySQL的“零件”们1.连接器2.查询缓存3.分析器4.优化器5.执行器 总结 前言 做了多年技术之后&#xff0c;技术更新换代太快&#xff0c;从我入行时候从单体架构到后面分布式SOA&#xff0c;再到微服务&#xff0c;从后端再到全…

进程中线程使用率偏高问题排查

1. top命令查看CPU使用率高的进程 2. top -H -p 15931(进程PID) 查看进程下的线程 3. printf "%x\n" 17503(线程PID) 线程PID 10进制转16进制 0x445f 4. jstack -l 15931(JVM进程PID) 导出java进程栈信息&#xff0c;里面包含线程nid0x445f和所在的类&#xff0…

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

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

Ai知识图谱

总结&#xff1a;从AI技术栈全貌来看&#xff0c;基础模型、基础算法&#xff0c;个人及小公司是玩不起的&#xff0c;大公司才有对应人力、财力、算力 去做&#xff0c;个人更多的是要在应用场景上创新&#xff0c;几个关键的技术必须会&#xff1a;编码语言&#xff08;Pytho…

列式数据库、行式数据库简介

列式数据库、行式数据库简介 1、数据准备2、行式数据库3、列式数据库4、行式、列式存储对比 常见的行式数据库有Mysql&#xff0c;DB2&#xff0c;Oracle&#xff0c;Sql-server等&#xff1b;列数据库&#xff08;Column-Based&#xff09;数据存储方式按列存储&#xff0c;常…

WebSocket学习笔记以及用户与客服聊天案例简单实现(springboot+vue)

一&#xff1a;介绍&#xff1a; 二&#xff1a;http协议与websocket对比&#xff1a; 三&#xff1a;websocket协议&#xff1a; 四&#xff1a;实现&#xff1a; 4.1客户端&#xff1a; 4.2服务端&#xff1a; 五&#xff1a;案例&#xff1a; 环境&#xff1a;做一个书店…

Vim工具使用全攻略:从入门到精通

引言 在软件开发的世界里&#xff0c;Vim不仅仅是一个文本编辑器&#xff0c;它是一个让你的编程效率倍增的神器。然而&#xff0c;对于新手来说&#xff0c;Vim的学习曲线似乎有些陡峭。本文将手把手教你如何从Vim的新手逐渐变为高手&#xff0c;深入理解Vim的操作模式&#…

机器学习 | 掌握线性回归的实战技巧

目录 初识线性回归 损失和优化 欠拟合与过拟合 正则化线性模型 模型的保存与加载 初识线性回归 线性回归(Linearregression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。特点是&#xff1a;有一个自变量的情况称为单…

备战蓝桥杯---数据结构与STL应用(进阶2)

本文将主要围绕有关map的今典应用展开&#xff1a; 下面我用图进行分析&#xff1a; 下面为AC代码&#xff1a; #include<bits/stdc.h> using namespace std; struct Point {int x,y;bool operator < (const Point & r) const {return x < r.x || ( x r.x &a…

Day 1. 学习linux高级编程之Shell命令和IO

1.C语言基础 现阶段学习安排 2.IO编程 多任务编程&#xff08;进程、线程&#xff09; 网络编程 数据库编程 3.数据结构 linux软件编程 1.linux&#xff1a; 操作系统&#xff1a;linux其实是操作系统的内核 系统调用&#xff1a;linux内核的函数接口 操作流程&#xff…

计算机视觉-阅读内容和风格图像

首先&#xff0c;我们读取内容和风格图像。 从打印出的图像坐标轴可以看出&#xff0c;它们的尺寸并不一样。 %matplotlib inline import torch import torchvision from torch import nn from d2l import torch as d2ld2l.set_figsize() content_img d2l.Image.open(../img/…

Linux下编译EtherCAT主站SOEM-1.4.1

目录 1、SOEM下载 2、CMake安装​​​​​​ 3、编译 环境&#xff1a;Ubuntu1604. 1、SOEM下载 最新版为SOEM-v1.4.0&#xff0c;可以从github下载地址&#xff1a; https://github.com/OpenEtherCATsociety/SOEM 2、CMake安装​​​​​​ 3、编译 解压文件&#xff0c…

c++虚函数、静态绑定与动态绑定

首先说明&#xff0c;所谓绑定&#xff0c;就是指函数的调用 接下来&#xff0c;我们直接看一段代码来说明问题 class Base { public:Base(int data10):m_a(data){}void show(){cout<<"Base::show()"<<endl;}void show(int){cout<<"Base::sh…

[python]基于LSTR车道线实时检测onnx部署

【框架地址】 https://github.com/liuruijin17/LSTR 【LSTR算法介绍】 LSTR车道线检测算法是一种用于识别和定位车道线的计算机视觉算法。它基于图像处理和机器学习的技术&#xff0c;通过对道路图像进行分析和处理&#xff0c;提取出车道线的位置和方向等信息。 LSTR车道线…

docker镜像结构

# 基础镜像 FROM openjdk:11.0-jre-buster # 设定时区 ENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # 拷贝jar包 COPY docker-demo.jar /app.jar # 入口 ENTRYPOINT ["java", "-jar"…

[SWPUCTF 2021 新生赛]babyrce

我们打开发现他让我们输入cookie值为admin1 出现一个目录 我们跳转进去 我们可以发现这个有个preg_match不能等于空格不让会跳转到nonono我们可以通过${IFS}跳过

桌面显示器应用Type-C接口有什么好处

随着科技的不断发展&#xff0c;桌面显示器作为我们日常工作中不可或缺的设备之一&#xff0c;也在不断更新换代。其中&#xff0c;Type-C接口的应用成为了桌面显示器发展的一个重要趋势。那么&#xff0c;桌面显示器应用Type-C接口究竟有什么好处呢&#xff1f; 首先&#xff…

一文教你地平线旭日派X3部署yolov5从训练-->转模型-->部署

一文教你地平线旭日派X3部署yolov5从训练&#xff0c;转模型&#xff0c;到部署 近日拿到了地平线的旭日派X3&#xff0c;官方说是支持等效5tops的AI算力&#xff0c;迫不及待的想在上面跑一个yolov5的模型&#xff0c;可谓是遇到了不少坑&#xff0c;好在皇天不负有心人&…

【Leetcode】1690. 石子游戏 VII

文章目录 题目思路代码结果 题目 题目链接 石子游戏中&#xff0c;爱丽丝和鲍勃轮流进行自己的回合&#xff0c;爱丽丝先开始 。 有 n 块石子排成一排。每个玩家的回合中&#xff0c;可以从行中 移除 最左边的石头或最右边的石头&#xff0c;并获得与该行中剩余石头值之 和 相…