汇编学习笔记(一)

根据实验来学习和巩固数据宽度和逻辑运算的知识。

前言

无论看课程还是资料,始终觉得有朦胧感,对移位运算以及原码补码反码等还是感觉不太理解。于是决定通过实例,上手实验一下,加深理解。关于涉及概念就不在这里赘述了。必要概念还是会说明一下。

学习目标

1、理解并写出“10>>2=2”的原理,并复习数据宽度的概念。

2、测试负数在计算机的存储以及运算结果。(基于移位运算)

实验环境以及资料

1.C语言编译器CodeBlocks。

2.运算还要熟记二进制与十六进制对应表格。

0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
0 1 2 3 4 5 6 7 8 9 A B C D E F

3.数据宽度

用图示法表示最简单
在这里插入图片描述

关于什么类型的数据采用什么大小的数据宽度,可以参考下表。
在这里插入图片描述

实验过程

一、移位运算

实验代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
C
#include<stdio.h>
//移位运算的研究
int main()
{
int unsigned a;
a=10;
printf("%d\n",a>>2);
print_bin(a>>2);
return 0;
}
//直接输出二进制函数
void print_bin(int n)
{
int l = sizeof(n)*8;//总位数。
int i;
if(i == 0)
{
printf("0");
return;
}
for(i = l-1; i >= 0; i --)//略去高位0.
{
if(n&(1<<i)) break;
}

for(;i>=0; i --)
printf("%d", (n&(1<<i)) != 0);
}

移位运算是基于二进制的,符号表示为右移">>"和左移“<<”。

在这里插入图片描述

移位运算的原理可以理解为:

在定义了int类型后,拥有了32位的空间(参考实验环境中的数据宽度)

所以10的二进制表示为:

0000 0000 0000 0000 0000 0000 0000 1010

已注明无符号数的情况下,向右移位两位表示为:

(补位)0000 0000 0000 0000 0000 0000 0000 0010 10(已删除)

即0010 十进制为2
在这里插入图片描述

答案正确

同理进行左移,因为左移不存在补符号位,所以我直接猜测左移答案为

(已删除)00 0000 0000 0000 0000 0000 0000 0010 1000(补位)

即0010 1000

简写为 28

换算为十进制为40

这里出现了个失误,电脑计算器自带进制转换,但是没看懂缩写。

补充上各种进制的英文以及缩写:

1、BIN:binary,二进制的;

2、OCT:octal,八进制的;

3、HEX:hexadecimal,十六进制的;

4、DEC:decimal,十进制的。
在这里插入图片描述

所以答案就是40,写代码验证。就是上面代码换成“<<"即可
在这里插入图片描述

答案正确!

二、有符号和无符号

继续研究有符号位的情况右移。
在这里插入图片描述

这里发现结果还是2,原因可能是符号位为0的原因。

在实验一下符号位为1的情况,直接写一个首位为一的二进制数即可。

写出来为

1000 0000 0000 0000 0000 0000 0000 0000

十进制为2,147,483,648

如果不补符号位的话,结果应该为

0010 0000 0000 0000 0000 0000 0000 0000

十进制为536,870,912

那么写代码进行测试
在这里插入图片描述

与上述答案相差就一个负号,转换为二进制是

0010 0000 0000 0000 0000 0000 0000 0000

未声明无符号的情况下,计算机自动补上了符号位

这里卡壳了,不清楚运算过程中产生的负数是不是按照补码一样存储了,还是只是识别符号位。需要直接输出二进制数验证一下

插入上面的函数,明天再研究,先纳入日程,今天先搞明白这个。

在这里插入图片描述

再定义a为无符号数的情况下,输出的为我们猜测的二进制

接下来试一下不定义。

在这里插入图片描述

可以看到,计算机自动补上了两个1,因为原来最高位为1为负,所以补1

1110 0000 0000 0000 0000 0000 0000 0000

怎么看都不可能输出的是-536870912,研究后发现有符号位首位为1计算机会按其补码存储。那先反过来减一取补码:

1101 1111 1111 1111 1111 1111 1111 1111

然后取反码

0010 0000 0000 0000 0000 0000 0000 0000

答案正确

实验总结

1
2
3
4
5
果然,有了实践对知识的理解更加稳固了,还涉及到了之前所学的数据宽度等一系列知识。顺带还解决了之前C语言学习中的问题。以后的学习都采用这样的方式,围绕实验来对知识进行学习和巩固。以上这些还仅仅是二进制学习的基础,千万不能留下来漏洞。

接下来几天计划选一个实验,学习一下python。

冲冲冲!

参考文献

1.原码,反码,补码的深入理解与原理:

https://blog.csdn.net/afsvsv/article/details/94553228

2.二进制输出代码

https://blog.csdn.net/acmsongye/article/details/90293919

https://blog.csdn.net/zhuxincheng_1218/article/details/86626893