C语言基础之位运算(二)

C语言基础之位运算(一)
C语言基础之位运算(二)
C语言基础之位运算(三)

1.寄存器的读写

  • ARM中内存与IO是统一编址的,ARM中有很多内部外设,Soc中CPU通过这些外设的寄存器写入一些特定的值来操控这个内部外设,进而操控硬件设备动作。即读、写寄存器就是操控硬件。
  • 寄存器的特点是:按位进行规划和使用,读、写是32位整体进行操作的;
  • 寄存器读写的要求:在改变特定位时,不可改变和影响其他位;
  • 变更寄存器中特定值的步骤:--

:要变更寄存器中某些特定位,先读取寄存器中整体原来的值;
:修改读取的整体原来值中的某些特定位;
:将修改过特定位的整体,统一写入寄存器;

  • 注意:读取一次寄存器的值是32位的,不论修改几位特定值,都必须整体读出32位的内容,在不影响其他原来位值的情况下,将目标特定位进行修改,然后统一写入寄存器;

2.寄存器的读写方式

使用C语言对寄存器赋值时,常常需要用到C语言的位操作符。常用的操作手法有以下几种:

2.1、把寄存器某位清零 &

若希望寄存器中某些特定位变成0,而不影响其他位,可以构造一个合适的二进制数和寄存器中的值进行位与&操作,实现特定位清零。
位与&运算符特点(二进制数)与1位与无变化;与0位与变为0;

把0xaaaa aaaa的低8-15位清零。
第一步:要把0xaaaa aaaa这个十六进制数的低8到15位清零,就得让8-15位和0位与,而其他位不能发生变化;
第二步:要得到一个十六进制数,让该数的8-15位是0,其他位是1,即二进制数的0-31位是:1111 1111 1111 1111 0000 0000 1111 1111;
第三步:把这个二进制数转换为十六进制数得到0xffff 00ff;
第四步:让寄存器中的目标数(0xaaaa aaaa)和清零指定位(0xffff 00ff)进行位与,即可完成8-15位清零;

//1010 1010 1010 1010 '1010 1010' 1010 1010 十六进制一位等于二进制四位
a = 0xaaaa aaaa;
//1111 1111 1111 1111 '0000 0000' 1111 1111
b = 0xffff 00ff;
c = a & b;
//1010 1010 1010 1010 '0000 0000' 1010 1010 这样8-15位就被清零了, 结果为0xaaaa 00aa
c == 0xaaaa 00aa;

2.2、对寄存器某几位赋值 |

寄存器位经过清零操作后,可以构造一个合适的二进制数和寄存器中的值进行位或|操作,实现对清零位的赋值;
位或|运算符特点(二进制数)与1位或变为1,与0位或无变化;

把0xaaaa 00aa清零的低8-15位置1,其他位不变。
第一步:要对0xaaaa 00aa这个十六进制数的第8-15位赋值,就得让8-15位和1位或,而其他位不能发生变化;
第二步:要得到一个十六进制数,让该数的8-15位是1,其他位是0,即二进制数的0-31位是:0000 0000 0000 0000 1111 1111 0000 0000;
第三步:把这个二进制数转换为十六进制数得到0xff00;
第四步:将寄存器中的数(0xaaaa 00aa)和赋值指定位(0xff00)进行位或,即可完成8-15位置1。

//1010 1010 1010 1010 '0000 0000' 1010 1010
a = 0xaaaa 00aa;
//0000 0000 0000 0000 '1111 1111' 10000 0000
b = 0xff00;
c = a | b;
//1010 1010 1010 1010 '1111 1111' 1010 1010 这样8-15位就被置1了。结果为0xaaaa ffaa
c = 0xaaaa ffaa;

2.3、对寄存器某位取反 ~或^

要对寄存器的某个位进行取反操作,即 1 变 0 ,0 变 1;
有以下两种方式:

2.3.1、按位取反 ~

位取反运算符特点:(二进制数)按位取反,1变为0,0变为1;

把0xf0取反。
第一步:将0xf0取反,首先要得到它的二进制。0xf0的二进制数是:1111 0000;
第二步:对二进制每一位进行取反,0变1, 1变0;
第三步:取反后得到0000 1111,转换成十六进制是:0xf

a = 0xf0;// 1111 0000
c = ~b;
c == 0xf;//0000 1111 注意:这里的变量都占32位,这里省略了8-31位,用不到的位,编译器自动补0

2.3.2、特定位取反用 ^

位异或运算符特点(二进制数)与1异或位取反,与0异或无变化;异或就是相异为1,相同则为0。

把0xa的0-1位取反,其他位不改变。
第一步:把0xa转换为二进制数:0xa->1010;
第二步:可以构造一个合适的二进制数和寄存器中的值进行位异或操作,实现对特定位的取反;为对二进制数1010的0-1位取反,则这里构建的对应二进制数位 :0011;
第三步:将构建的二进制数转换成十六进制的,0011->0x3;

a = 0xa;//10'10'   
b = 0x3; //00'11'   
c = a^b;   
c == 0x9; //10'01' 这样0xa的0-1位就取反了,而其他位没有发生变化

2.4、总结:

1、十六进制一位等于二进制四位,32位平台下int数据类型占32位,寄存器也是32位的,分配的变量占32位,我们用不到的位,编译器自动补0。
2、注意位取反~位异或^的区别。前者是给所有位取反的;后者可以完成给特定位取反。


3.位运算构建特定二进制数

对寄存器位操作,经常需要特定位给特定值或者取反;一般通过事先构建一个特别的值,将这个值和原来的值进行位与、位或、位异或、位取反等操作,来达到我们对寄存器操作的要求。构建特定位二进制数值,一般通过以下两种方式

3.1、构建特定位为1的二进制数:左位移、位或

构建目标特定位为1的二进制数:(0xT_V << T_Low_Bit_Index)

解释:

0x:16进制的前缀;
T_V:Target_Value 根据一个低位到高位连续T_L个1构建出来的二进制数,进而转换出来的十六进制数;
T_L: Target_Length 目标特定位长度, 目标特定位的((最高位inedx - 最低位index) + 1) = T_L;
T_Low_Bit_Index:目标特定位的最低位的下标

实现步骤:

1、计算出目标特定位的个数T_L;
2、根据T_L数量,先构建最低位为T_L个连续1的二进制数;
3、将上步骤中构建的二进制数,转换成十六进制数0xT_V;
4、然后将十六进制数0xT_V,左位移T_Low_Bit_Index个位;
5、得出构建目标特定位为1的二进制数:(0xT_L << T_Low_Bit_Index)
⚠️注意:目标特定位必须是连续性的,若不连续就将目标特定位的个数分成多个部分计算并列出来,构建出多个二进制数进行位或运算;

举例:
  • 构建一个bit3~bit7为1(其他位全部为0)的二进制数。

1、计算目标特定位个数:T_L = ((7 - 3) + 1) = 5;// bit3、bit4、bit5、bit6、bit7等5位
2、构建最低位为T_L个连续1的二进制数:0000 0000 0000 0000 0000 0000 0001 1111;// T_L = 5;构建低位往高位连续5个1的二进制数
3、将上步骤中构建的二进制数,转换成十六进制数:T_V = 0x1f; // 0x1f代表11111,在16进制数来看,低4个位为一个f,加上第5位1,就是0x1f
4、代入目标特定位的最低位的下标:T_Low_Bit_Index = 3;// bit3~bit7的最低位bit3
5、得出构建bit3~bit7位为1的二进制数:
(0xT_V << T_Low_Bit_Index) = (0x1f << 3) = 0000 0000 0000 0000 0000 0000 1111 1000 = 0xf8;

  • 构建bit3~bit7,bit23~bit25两段目标特定位为1的二进制数。

// 第一段目标特定位为1的二进制数
1、var_num_1 = (0x1f << 3) = 0xf8 = 0000 0000 0000 0000 0000 0000 '1111 1'000;
// 第二段目标特定位为1的二进制数
2、var_num_2 = (0x7 << 23) = 0x3800000 = 0000 00'11 1'000 0000 0000 0000 0000 0000;
// 两段目标特定位为1的二进制数结合起来的二进制; 位或运算符特点:与1位或变成1,与0位或无变化;
3、result = (0x1f << 3) | (0x7 << 23) = 0x38000f8 = 0000 00'11 1'000 0000 0000 0000 '1111 1'000;


第一段目标特定位为1的二进制数

第二段目标特定位为1的二进制数

两段目标特定位为1二进制位或结果

3.2、构建特定位为0的二进制数:左位移、位或、位取反

有以下两种实现方法

1、可以根据构造多个特定位为1的二进制数,进行位或操作:(0xT_V << T_Low_Bit_Index) | (0xT_V << T_Low_Bit_Index)
2、先将目标特定位为0的二进制数,取反变成构造目标特定位为1的二进制数;然后取反得到目标特定位为0的二进制数:~(0xT_V << T_Low_Bit_Index)

举例:
  • 构建一个bit3~bit7为0(其他位全部为1)的二进制数。

方法一:
目标特定位为0的二进制数:(0xT_V << T_Low_Bit_Index) | (0xT_V << T_Low_Bit_Index) = (0x7<<0) | (0xffffff<<8);// bit0-bit2,bit8-bit31两部分二进制数进行位或,得出目标特定位为0,其他位全位1
方法二:// 推荐
目标特定位为0的二进制数:~(0xT_V << T_Low_Bit_Index) = ~(0x1f << 3) // 直接将特定位为1的二进制数,取反

3.3、总结

1、寄存器中二进制数位:1少0多,可通过连续多个1左移n位,构造特定位为1二进制数;
2、寄存器中二进制数位:0少1多,先构建其位反二进制再按位取反
3、寄存器中二进制数位:连续1(0)不止一个,则通过分段分别构建,再彼此位或即可;


写在最后

C语言操作寄存器的常见手法
进制转换图表与讲解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • C语言基础之位运算(一)[https://www.jianshu.com/p/30b807d69948]C语言基础...
    Eugene_iOS阅读 607评论 0 2
  • C语言定义变量 定义一个变量 给变量赋值 定义一个变量的同时给变量赋值 C语言使用变量之前必须赋值或者初始化 试试...
    闫希鹏阅读 513评论 0 0
  • @[TOC](IOS 逆向开发(二十一) 汇编-基础) 1. 汇编简介 为啥要需要学习汇编? 大学都学习过汇编语言...
    孔雨露阅读 593评论 0 2
  • 前言 从本篇文章开始,即将给大家分享关于iOS逆向安全攻防等相关的知识点,在分析逆向之前,我们必须掌握关于汇编的相...
    深圳_你要的昵称阅读 436评论 0 2
  • 一、二进制 1、什么是二进制 二进制(binary),发现者莱布尼茨[https://baike.baidu.co...
    Streamsle阅读 1,808评论 0 2