西工大网络空间安全学院计算机系统基础实验一(45678)

本文主要是介绍西工大网络空间安全学院计算机系统基础实验一(45678),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接着来看第4个函数,int replaceByte(int x, int n, int c),看题目给出的例子,replaceByte(0x12345678,1,0xab) = 0x1234ab78。我们可以多写几个例子,进而找出规律,比如:

replaceByte(0x12345678,2,0xab) = 0x12ab5678

replaceByte(0x12345678,3,0xab) = 0xab345678

replaceByte(0x12345678,0,0xab) = 0x123456ab

replaceByte(0x12345678,1,0x00) = 0x12340078

由此我们猜测,返回值可能是(c<<(n<<3))|(~(0xFF<<(n<<3))&x),为什么呢?我们拿题目给的例子为例来讲。replaceByte(0x12345678,1,0xab) = 0x1234ab78,结果可以看成由0x0000ab00与0x12340078相或得到,那么该怎么得到0x0000ab00与0x12340078呢?发现0xab<<8即可得到0xab00,而0xab<<8 == 0xab<<(1<<3),进而发现可以通过(c<<(n<<3))得到0x0000ab00,接着如何得到0x12340078呢?发现0x12340078可由0x12345678&0xFFFF00FF得到,而x即为0x12345678,那么该如何得到0xFFFF00FF呢?发现0xFFFF00FF==~0x0000FF00,而0x0000FF00==0xFF<<(1<<3),即0xFF<<(n<<3)。所以综上所述,我们得到了(c<<(n<<3))|(~(0xFF<<(n<<3))&x),下面我们使用Python进行检验,如(图1:第4个函数——用Python验证想法)所示。经过Python验证,我们的想法是正确的,接着我们重复第1、2、3个函数的流程,使用VS code修改bits.c文件,使用"./dlc bits.c"与"./dlc -e bits.c"命令确保第4个函数中使用的运算符等满足要求,使用"make clean", "make btest"函数编译生成新的btest可执行文件,使用"./btest -f replaceByte"命令保证函数能产生正确的结果。如(图2:第4个函数)所示,成功编写第4个函数。

另外,发现第4个函数还可以再次修改,使得使用到的运算符再少一个,如(图3:优化后的第4个函数)所示。

**************************************************************************************************************

(图1:第4个函数——用Python验证想法)

************************************************************************************************************** 

**************************************************************************************************************

(图2:第4个函数)

**************************************************************************************************************

**************************************************************************************************************

 

(图3:优化后的第4个函数)

**************************************************************************************************************

接着看第5个函数,int mult3div2(int x), 看题目给出的三个例子:mult3div2(11) = 16; mult3div2(-9) = -13; mult3div2(1073741824) = -536870912(overflow)。先看第一个例子,mult3div2(11) = 16,11的十六进制形式为0xB, (0xB<<1)+0xB可以得到0x21,接着0x21>>1得到0x1,十进制形式为16,正好是第一个例子的结果。虽然如此,我们依然可以留心到0x21右移一位时,最低位的1被移走了,但是歪打正着,正好满足了向0舍入的要求。所以我们猜测,返回的表达式是((x<<1)+x)>>1。第二个例子,mult3div2(-9) = -13,-9的16进制形式为0xFFFF FFF7,((0xFFFF FFF7)<<1)+(0xFFFF FFF7)可以得到0xFFFF FFE5,接着0xFFFF FFE5>>1得到0xFFFF FFF2,十进制形式为-14。但是期望中的结果是-13,而不是-14。这时我们发现,0xFFFF FFE5右移一位时,最低位的1被移走了,而且与向0舍入背道而驰。第三个例子,mult3div2(1073741824) = -536870912(overflow),1073741824的十六进制形式为0x4000 0000,(0x4000 0000<<1)+0x4000 0000可以得到0xC000 0000,0xC000 0000>>1得到0xE000 000,十进制形式即为-536,870,912,正好是答案的形式。

现在整理一下,只有当(x<<1)+x的最低位为1,并且x的最高位也为1时,返回的结果需要在((x<<1)+x)>>1的基础上,再多加1,否则不需要加1,直接返回((x<<1)+x)>>1即可。但是,真的是这样子嘛???作者私底下偷偷试过几次,发现还需要添加一条附加条件:(x<<1)+x的最高位也为1。那么如何用表达式表示出来“(x<<1)+x的最低位为1、最高位为1,并且x的最高位也为1”呢?((((x<<1)+x)<<31)&((x<<1)+x)&x)>>31。因为(x<<1)+x被反复使用,所以为了节省运算符,我们选择设置temp=(x<<1)+x,这样子即可写作:((temp<<31)&temp&x)>>31。只有当(x<<1)+x的最低位为1,最高位为1,并且x的最高位也为1时,((temp<<31)&temp&x)>>31的结果为0xFFFFFFFF,否则即为0。注意!!!在这里千万不要简单的将((x<<1)+x)>>1与((temp<<31)&temp&x)>>31相加!!!应该将((temp<<31)&temp&x)>>31取反后加1,即~(((temp<<31)&temp&x)>>31)+1,然后再与((x<<1)+x)>>1相加,才是正确的表达式子。作者就是因为这个错误,改了好一会。仿照着第1、2、3、4个函数的方法,我们来检验我们的函数对不对。如(图4:第5个函数)所示。

最后,至于为什么要添加那一条,作者并不清楚,等以后有时间慢慢研究吧。

**************************************************************************************************************

(图4:第5个函数)

**************************************************************************************************************

第6个函数,int multFiveEighths(int x) ,执行效果应该类似于C语言中的x*5/8,而且向0舍入。这道题比第5题的难度更大。但我们不妨采用类似的方法,先确定大概的轮廓((x<<2)+x)>>3,接着再去细调。而细调的方法是,不断比较对于不同的x,两个表达式((x<<2)+x)>>3与x*5/8的值是否会有不同,以及会有多大的不同。观察发现似乎对于0到2147483647的正整数来说,((x<<2)+x)>>3与x*5/8的值相同,对于-1到-2147483648的负数来说,除非该负数能够整除8,否则 x*5/8=(((x<<2)+x)>>3)+1。而如果x这个负数能够整除8,则x<<29为0x0,并且x>>31=0xFFFF FFFF,写在一起即为(x>>31)&!(x<<29)。所以最终返回的表达式是:(((x<<2)+x)>>3)+((x>>31)&!!(x<<29))(注意这里采用了两个取非符号!!!这个地方很容易错)。仿照第1、2、3、4、5个函数的方法,我们来检验第6个函数的正确性,如(图5:第6个函数)所示。

**************************************************************************************************************

(图5:第6个函数)

**************************************************************************************************************

第7个函数,int addOK(int x, int y),判断x+y是否会发生溢出。如果会发生溢出,那么返回0,如果不会发生溢出,则返回1。而两个int类型变量相加会造成溢出的情况是:当两个正数相加得到的结果为负数,或者两个负数相加得到的结果为正数时,就会发生溢出。用"int sum=x+y"来保存x+y的值。返回!((~((x>>31)^(y>>31)))&((x>>31)^(sum>>31)))。虽然最终通过了,如(图6:第7个函数)所示,但是其中的函数逻辑并没有理清楚,还需要进行一轮又一轮的迭代与优化。

**************************************************************************************************************

(图6:第7个函数)

**************************************************************************************************************

第8个函数,int bitCount(int x),返回int型变量x的十六进制表示形式中1的个数。比如当x=5时,5为0x0101,有2个1,当x=7时,7为0x0111,有3个1。这道题比较复杂,使用到了“汉明重量”的知识。作者结合Java中对于函数bitCount的实现方法,简单修改了下代码,使其满足对于运算符等的要求,之后按照前7个函数相同的方法,写完了第8个函数,如(图7:第8个函数)所示:

**************************************************************************************************************

(图7:第8个函数)

**************************************************************************************************************

最后,45678这8个函数的代码如(图8:5个函数的C语言源代码)所示:

**************************************************************************************************************

int replaceByte(int x, int n, int c) {int temp = n<<3; return (c<<temp)|(~(0xFF<<temp)&x);
}
int mult3div2(int x) {int temp=(x<<1)+x; return (temp>>1)+(~(((temp<<31)&temp&x)>>31)+1);
}
int multFiveEighths(int x) {return (((x<<2)+x)>>3)+((x>>31)&!!(x<<29));
}
int addOK(int x, int y) {int sum=x+y;return !((~((x>>31)^(y>>31)))&((x>>31)^(sum>>31)));
}
int bitCount(int x) {int temp1 = 0x55|(0x55<<8)|(0x55<<16)|(0x55<<24);int temp2 = 0x33|(0x33<<8)|(0x33<<16)|(0x33<<24);int temp3 = 0xf|(0xf<<8)|(0xf<<16)|(0xf<<24);int n = x + ~((x >> 1) & temp1) + 1;n = (n & temp2) + ((n >> 2) & temp2);n = (n + (n >> 4)) & temp3;n = n + (n >> 8);n = n + (n >> 16);return n & 0x3f;
}

(图8:5个函数的C语言源代码)

**************************************************************************************************************

 

这篇关于西工大网络空间安全学院计算机系统基础实验一(45678)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/434033

相关文章

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

客户案例:安全海外中继助力知名家电企业化解海外通邮困境

1、客户背景 广东格兰仕集团有限公司(以下简称“格兰仕”),成立于1978年,是中国家电行业的领军企业之一。作为全球最大的微波炉生产基地,格兰仕拥有多项国际领先的家电制造技术,连续多年位列中国家电出口前列。格兰仕不仅注重业务的全球拓展,更重视业务流程的高效与顺畅,以确保在国际舞台上的竞争力。 2、需求痛点 随着格兰仕全球化战略的深入实施,其海外业务快速增长,电子邮件成为了关键的沟通工具。

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

软件设计师备考——计算机系统

学习内容源自「软件设计师」 上午题 #1 计算机系统_哔哩哔哩_bilibili 目录 1.1.1 计算机系统硬件基本组成 1.1.2 中央处理单元 1.CPU 的功能 1)运算器 2)控制器 RISC && CISC 流水线控制 存储器  Cache 中断 输入输出IO控制方式 程序查询方式 中断驱动方式 直接存储器方式(DMA)  ​编辑 总线 ​编辑

2024网安周今日开幕,亚信安全亮相30城

2024年国家网络安全宣传周今天在广州拉开帷幕。今年网安周继续以“网络安全为人民,网络安全靠人民”为主题。2024年国家网络安全宣传周涵盖了1场开幕式、1场高峰论坛、5个重要活动、15场分论坛/座谈会/闭门会、6个主题日活动和网络安全“六进”活动。亚信安全出席2024年国家网络安全宣传周开幕式和主论坛,并将通过线下宣讲、创意科普、成果展示等多种形式,让广大民众看得懂、记得住安全知识,同时还

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou