自己这段时间上了微机原理,想起来这本书也看完了,就一同综合做个笔记。因而有部分是只属于MIPS的,我会标注出来,如果不需要应付考试的话我是不推荐读里面相关段落的一个字的,而为应付考试的话标注属于MIPS的应为重点,利用crtl +F 搜索MIPS即可
主要是二进制的比特串的存放规则与译码规则的不同
储存的基本单元:
即如地址0x00000001
中储存了0xcc
这样的数据
字:
寻址:
如int x地址为0x100
; 即&x = 0x100
,x的四个字节储存在0x100 0x101 0x102 0x103
处
大端机:最高有效字节在最前面
小端机:最高有效字节在最后面
如 0x01234567 高位是0x01 低位是0x67
地址 | 0x100 |
0x101 |
0x102 |
0x013 |
---|---|---|---|---|
大端机 | 0x01 |
0x23 |
0x45 |
0x67 |
小端机 | 0x67 |
0x45 |
0x23 |
0x01 |
- show_bytes程序
//可用于按位模式显示数据
#include
typedef unsigned char *byte_pointer;
template <typename T>
void show_bytes(T x)
{
byte_pointer start = (byte_pointer)&x;
for (int i =0;i<sizeof(T);++i)
{
printf("%.2x", start[i]);
}
printf("\n");
}
右移k位:逻辑右移:左端补0
算术右移:左端补1 (有符号数几乎都是用算术右移)
Attention: 加减优先级比位移高
注意,以下仅讨论整数,那么提升,截取等都只对整数而言.
B2T_w(Binary to Two’s-complement)
反码(Ones’ Complement): 为 补码 的最高有效位的权 小一
原码(Sign-Magnitude):最高有效位是符号位,用于确定剩下的位应该取正还是负
原码,反码,补码关系
强制类型转换: 结果保持位值不变,只是改变了解释这些位的方式
简单的丢弃掉前面多的位数.
#include
using namespace std;
float sum_elements(float a[], unsigned length)
{
float sum = 0;
for (int i=0;i<= length-1;++i)//由于length 为unsigned,当length=0时,length-1会下溢
{
sum += a[i];
}
return sum;
}
int main()
{
float x[4] = { 1.0,2.0,3.0,4.0 };
cout << sum_elements(x, 0) << endl;
}
这里先给出数学表达式,再讲述其中符号的意思,再说明如何自己译码并进行计算.
符号解释
符号(sign) s
尾数(significand) M
阶码(exponent) E
将浮点数的位表示划分为三个字段,分别为这些值进行译码
单精度float 32位 各个字段
31 | 30 23 | 22 0 |
---|---|---|
s | exp | frac |
双精度double 64位 各个字段
63 | 62 52 | 51 0 |
---|---|---|
s | exp | frac |
3. 译码
以float说明如何解释各个字段并读出十进制值这里记住偏置 Baias=2k−1−1
由于以下运算步骤,因而1+1e120-1e120 = 0,而1e120-1e120+1 = 1
加减计算方式
大体分为六步
这里用一个例子综合地回顾浮点数的表示与运算(also MIPS)
1.3+3.7
1.3(float表示):易知s = 0
1.3二进制数为1.3_d = 1.0 1001 1001 1001 10011001 1001..._b
那么为规范数.
其阶码为0,加上偏置(bias = 127) 得到阶码位为127_d = 0111 1111_b
然后其小数位就需要去除整数部分的1,然后进行舍入到23位,为0 1001 1001 1001 1001 1001 10
最后其二进制表示就是0(符号位)0111 1111(阶码位)0 1001 1001 1001 1001 1001 10
整理为16进制就是0x3fa66666
在小端机上就会显示为0x66 66 a6 3f
3.7(float表示):易知 s= 0
3.7二进制数为3.7_d = 11.1 0110 0110 0110 0110 0110 0110 0110..._b
那么为规范数
小数点需左移一位,那么阶码为1,加上偏置得到阶码位128_d = 1000 0000_b
左移后数为1.11 0110 0110 0110 0110 0110 0110 0110..._b
然后进行小数位舍入得到11 0110 0110 0110 0110 0110 1
注意左后的1是舍入得到的
最后其二进制表示就是0(符号位)1000 0000(阶码位)11 0110 0110 0110 0110 0110 1
整理为16进制就是0x406ccccd
在小端机上就会显示为0xcd cc 6c 40
1.3 + 3.7 相加
均不为0
1.3阶码小,进行对阶,将小数部左移1位,相当于
此时再将位数相加,这里要注意3.7尾数前有隐含的1,而1.3对阶后没有了隐含的1,那么相当于
1.1101 1001 1001 1001 1001 101 +
0.1010 0110 0110 0110 0110 011
的到10.1000 0000 0000 0000 0000 000
规范化,由上一步算出来的式子还需要左移一位得到规范的尾数,那么阶码+1 得到为2 加上偏置为129.
阶码 129_d =1000 0001
尾数变为010 0000 0000 0000 0000 0000
得到结果为0 1000 0001 010 0000 0000 0000 0000 0000
16进制为0x40 a0 00 00
当做一门新的语言来,但是是一门贴近硬件的底层语言,在应用过程中加深对底层架构的理解。像硬件应用开发一样,直接操作寄存器,内存。
这里很容易理解指令集中各个指令属于哪一类的指令码,以下三类指令格式的不同,表明了其在微处理器的实现过程中操作的硬件设施的不同,主要由这里的op与funct字段决定.这里会详解 如何根据需要汇编指令写出其二进制表示
R型指令:仅具有寄存器操作数的指令
一般格式为
op | rs | rt | rd | shamt | funct |
---|---|---|---|---|---|
6位 | 5位 | 5位 | 5位 | 5位 | 6位 |
操作码,表明指令基本功能 | 第一个源操作数寄存器的编码 | 第二个源操作数寄存器的编码 | 目的操作数寄存器的编码 | 位移指令的移位次数编码 | 功能码,确定op决定指令的详细功能 |
实例:
I型指令:含有立即操作数的指令
一般格式为
实例:
J型指令:无条件跳转指令
一般格式