单周期CPU的设计与实现
关于单周期CPU的设计问题,相信各位在课程上也有所学习,以下是个人的一些理解
- 整个项目的资源下载:这里写链接内容
实验内容
基本要求
- PC和寄存器组写状态使用时钟触发,这是必须的!
- 指令存储器和数据存储器存储单元宽度一律使用8位,即一个字节的存储单位。不能使用32位作为存储器存储单元宽度。
- 控制器部分要学会用控制信号真值表方法分析问题并写出逻辑表达式;或者用case语句方法逐个产生各指令控制信号。注意:控制信号的产生不能使用时钟触发!
- 必须写一段测试用的汇编程序,而且必须包含所要求的所有指令,slti指令必须检查两种情况:“小于”和“大于等于”;beq、bne:“不等”和“等”。这段汇编程序必须尽量优化且出现在实验报告中,同时,给出每条指令在内存中的地址。检查实验时,必须提供。
- Always@(…)的敏感信号表中,时序触发和电平触发不能同时出现,即不能混用。
- 实验报告中应该有每条指令执行的波形(截图),用于说明该指令的正确性。
指令的分析
同时该CPU至少能实现以下指令功能操作。指令与格式如下:
==> 算术运算指令
(1)add rd , rs, rt (说明:以助记符表示,是汇编指令;以代码表示,是机器指令)
000000 rs(5位) rt(5位) rd(5位) reserved
功能:rd←rs + rt。reserved为预留部分,即未用,一般填“0”。
(2)addi rt , rs ,immediate
000001 rs(5位) rt(5位) immediate(16位)
功能:rt←rs + (sign-extend)immediate;immediate符号扩展再参加“加”运算。
(3)sub rd , rs , rt
000010 rs(5位) rt(5位) rd(5位) reserved
功能:rd←rs - rt
==> 逻辑运算指令
(4)ori rt , rs ,immediate
010000 rs(5位) rt(5位) immediate(16位)
功能:rt←rs | (zero-extend)immediate;immediate做“0”扩展再参加“或”运算。
(5)and rd , rs , rt
010001 rs(5位) rt(5位) rd(5位) reserved
功能:rd←rs & rt;逻辑与运算。
(6)or rd , rs , rt
010010 rs(5位) rt(5位) rd(5位) reserved
功能:rd←rs | rt;逻辑或运算。
==>移位指令
(7)sll rd, rt,sa
011000 未用 rt(5位) rd(5位) sa reserved
功能:rd<-rt<<(zero-extend)sa,左移sa位 ,(zero-extend)sa
==>比较指令
(8)slti rt, rs,immediate 带符号
011011 rs(5位) rt(5位) immediate(16位)
功能:if (rs <(sign-extend)immediate) rt =1 else rt=0, 具体请看表2 ALU运算功能表,带符号
==> 存储器读/写指令
(9)sw rt ,immediate(rs) 写存储器
100110 rs(5位) rt(5位) immediate(16位)
功能:memory[rs+ (sign-extend)immediate]←rt;immediate符号扩展再相加。即将rt寄存器的内容保存到rs寄存器内容和立即数符号扩展后的数相加作为地址的内存单元中。
(10) lw rt , immediate(rs) 读存储器
100111 rs(5位) rt(5位) immediate(16位)
功能:rt ← memory[rs + (sign-extend)immediate];immediate符号扩展再相加。
即读取rs寄存器内容和立即数符号扩展后的数相加作为地址的内存单元中的数,然后保存到rt寄存器中。
==> 分支指令
(11)beq rs,rt,immediate
110000 rs(5位) rt(5位) immediate(16位)
功能:if(rs=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4
特别说明:immediate是从PC+4地址开始和转移到的指令之间指令条数。immediate符号扩展之后左移2位再相加。为什么要左移2位?由于跳转到的指令地址肯定是4的倍数(每条指令占4个字节),最低两位是“00”,因此将immediate放进指令码中的时候,是右移了2位的,也就是以上说的“指令之间指令条数”。
(12)bne rs,rt,immediate
110001 rs(5位) rt(5位) immediate
功能:if(rs!=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4
特别说明:与beq不同点是,不等时转移,相等时顺序执行。
==>跳转指令
(13)j addr
111000 addr[27…2]
功能:pc <-{(pc+4)[31…28],addr[27…2],2{0}},无条件跳转。
说明:由于MIPS32的指令代码长度占4个字节,所以指令地址二进制数最低2位均为0,将指令地址放进指令代码中时,可省掉!这样,除了最高6位操作码外,还有26位可用于存放地址,事实上,可存放28位地址了,剩下最高4位由pc+4最高4位拼接上。
==> 停机指令
(14)halt
111111 00000000000000000000000000(26位)
功能:停机;不改变PC的值,PC保持不变。
实验原理
单周期CPU指的是一条指令的执行在一个时钟周期内完成,然后开始下一条指令的执行,即一条指令用一个时钟周期完成。电平从低到高变化的瞬间称为时钟上升沿,两个相邻时钟上升沿之间的时间间隔称为一个时钟周期。时钟周期一般也称振荡周期(如果晶振的输出没有经过分频就直接作为CPU的工作时钟,则时钟周期就等于振荡周期。若振荡周期经二分频后形成时钟脉冲信号作为CPU的工作时钟,这样,时钟周期就是振荡周期的两倍。)
CPU在处理指令时,一般需要经过以下几个步骤:
(1) 取指令(IF):根据程序计数器PC中的指令地址,从存储器中取出一条指令,同时,PC根据指令字长度自动递增产生下一条指令所需要的指令地址,但遇到“地址转移”指令时,则控制器把“转移地址”送入PC,当然得到的“地址”需要做些变换才送入PC。
(2) 指令译码(ID):对取指令操作中得到的指令进行分析并译码,确定这条指令需要完成的操作,从而产生相应的操作控制信号,用于驱动执行状态中的各种操作。
(3) 指令执行(EXE):根据指令译码得到的操作控制信号,具体地执行指令动作,然后转移到结果写回状态。
(4) 存储器访问(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。
(5) 结果写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。
单周期CPU,是在一个时钟周期内完成这五个阶段的处理。

MIPS指令的三种格式:

其中,
op:为操作码;
rs:只读。为第1个源操作数寄存器,寄存器地址(编号)是0000011111,001F;
rt:可读可写。为第2个源操作数寄存器,或目的操作数寄存器,寄存器地址(同上);
rd:只写。为目的操作数寄存器,寄存器地址(同上);
sa:为位移量(shift amt),移位指令用于指定移多少位;
funct:为功能码,在寄存器类型指令中(R类型)用来指定指令的功能与操作码配合使用;
immediate:为16位立即数,用作无符号的逻辑操作数、有符号的算术操作数、数据加载(Load)/数据保存(Store)指令的数据地址字节偏移量和分支指令中相对程序计数器(PC)的有符号偏移量;
address:为地址。

图2是一个简单的基本上能够在单周期CPU上完成所要求设计的指令功能的数据通路和必要的控制线路图。其中指令和数据各存储在不同存储器中,即有指令存储器和数据存储器。访问存储器时,先给出内存地址,然后由读或写信号控制操作。对于寄存器组,先给出寄存器地址,读操作时,输出端就直接输出相应数据;而在写操作时,在 WE使能信号为1时,在时钟边沿触发将数据写入寄存器。图中控制信号作用如表1所示,表2是ALU运算功能表。
表1 控制信号的作用
| 控制信号名 | 状态“0” | 状态“1” |
|---|---|---|
| Reset | 初始化PC为0 | PC接收新地址 |
| PCWre | PC不更改,相关指令:halt | PC更改,相关指令:除指令halt外 |
| ALUSrcA | 来自寄存器堆data1输出,相关指令:add、sub、addi、or、and、ori、beq、bne、slti、sw、lw | 来自移位数sa,同时,进行(zero-extend)sa,即 {{27{0}},sa},相关指令:sll |
| ALUSrcB | 来自寄存器堆data2输出,相关指令:add、sub、or、and、sll、beq、bne | 来自sign或zero扩展的立即数,相关指令:addi、ori、slti、sw、lw |
| DBDataSrc | 来自ALU运算结果的输出,相关指令:add、addi、sub、ori、or、and、slti、sll | 来自数据存储器(Data MEM)的输出,相关指令:lw |
| RegWre | 无写寄存器组寄存器,相关指令: | beq、bne、sw、halt、j 寄存器组写使能,相关指令:add、addi、sub、ori、or、and、slti、sll、lw |
| InsMemRW | 写指令存储器 | 读指令存储器(Ins. Data) |
| mRD | 输出高阻态 | 读数据存储器,相关指令:lw |
| mWR | 无操作 | 写数据存储器,相关指令:sw |
| RegDst | 写寄存器组寄存器的地址,来自rt字段,相关指令:addi、ori、lw、slti | 写寄存器组寄存器的地址,来自rd字段,相关指令:add、sub、and、or、sll |
| ExtSel | (zero-extend)immediate(0扩展),相关指令:ori | (sign-extend)immediate(符号扩展),相关指令:addi、slti、sw、lw、beq、bne |
| PCSrc[1…0] | 00:pc<-pc+4,相关指令:add、addi、sub、or、ori、and、slti、sll、sw、lw、beq(zero=0)、bne(zero=1);01:pc<-pc+4+(sign-extend)immediate,相关指令:beq(zero=1)、bne(zero=0); | 10:pc<-{(pc+4)[31:28],addr[27:2],2{0}},相关指令:j;11:未用 |
| ALUOp[2…0] | ALU 8种运算功能选择(000-111),看功能表 |
相关部件及引脚说明:
- Instruction Memory:指令存储器,
- Iaddr,指令存储器地址输入端口
- IDataIn,指令存储器数据输入端口(指令代码输入端口)
- IDataOut,指令存储器数据输出端口(指令代码输出端口)
- RW,指令存储器读写控制信号,为0写,为1读
- Data Memory:数据存储器,
- Daddr,数据存储器地址输入端口
- DataIn,数据存储器数据输入端口
- DataOut,数据存储器数据输出端口
- /RD,数据存储器读控制信号,为0读
- /WR,数据存储器写控制信号,为0写
- Register File:寄存器组
- Read Reg1,rs寄存器地址输入端口
- Read Reg2,rt寄存器地址输入端口
- Write Reg,将数据写入的寄存器端口,其地址来源rt或rd字段
- Write Data,写入寄存器的数据输入端口
- Read Data1,rs寄存器数据输出端口
- Read Data2,rt寄存器数据输出端口
- WE,写使能信号,为1时,在时钟边沿触发写入
- ALU: 算术逻辑单元
- result,ALU运算结果
- zero,运算结果标志,结果为0,则zero=1;否则zero=0
表2 ALU运算功能表

需要说明的是以上数据通路图是根据要实现的指令功能的要求画出来的,同时,还必须确定ALU的运算功能(当然,以上指令没有完全用到提供的ALU所有功能,但至少必须能实现以上指令功能操作)。从数据通路图上可以看出控制单元部分需要产生各种控制信号,当然,也有些信号必须要传送给控制单元。从指令功能要求和数据通路图的关系得出以上表1,这样,从表1可以看出各控制信号与相应指令之间的相互关系,根据这种关系就可以得出控制信号与指令之间的关系表(留给学生完成),再根据关系表可以写出各控制信号的逻辑表达式,这样控制单元部分就可实现了。
指令执行的结果总是在时钟下降沿保存到寄存器和存储器中,PC的改变是在时钟上升沿进行的,这样稳定性较好。另外,值得注意的问题,设计时,用模块化、层次化的思想方法设计,关于如何划分模块、如何整合成一个系统等等,是必须认真考虑的问题。
实验器材
电脑一台,Xilinx Vivado 软件一套,Basys3板一块。
实验分析
1. CPU的设计,主要是依照实验原理中的数据通路图以及控制信号的表格进行坟墓快设计的。其中分为十个底层模块以及一个顶层模块,具体的模块内容及作用如下:
顶层模块(1个):
(1) Main
作用:负责统筹11个模块的输入输出参数,通过设置多个wire类型的变量,及时拿到各个模块的输出,并传入到需要改输入参数的模块中去。
关键代码:
1. module Main(
2. input CLK, //时钟
3. input Reset, //重置信号
4. output zero,pcWre, //ALU结果是否为0, PC更改信号
5. output[1:0] pcSrc, //PC四选一选择器的控制信号
6. output[2:0] aluop, //ALU的执行信号
7. output[5:0] op, //指令操作的代码
8. output[31:0] readData1, readData2, extendData, writeData, o_p, currentAdd, Result //寄存器1读取的值,寄存器2读取的值,拓展符号信号,写入寄存器的数据, 32位的整条指令, 当前指令的地址, ALU输出的结果
9. );
底层模块(10个):
(1) PC
作用:根据传入的PCWre控制信号,进行地址移位操作。当PCWre为0时,指令地址保持不变;当PCWre为1时,指令地址变更为新地址。
代码:
1. module PC(
2. input CLK,
3. input Reset,
4. input PCWre,//值为0时不更改,代表停机指令;值为1的时候进行更改
5. input [31:0] NewAdd,
6. output reg[31:0] CurrentAdd
7. );
8.
9. initial begin
10. CurrentAdd <= -8;
11. end
12.
13. always@(posedge CLK or posedge Reset)
14. begin
15. if(Reset == 0) CurrentAdd <= 0;
16. else
17. begin
18. if(PCWre == 0) CurrentAdd <= CurrentAdd;
19. else CurrentAdd <= NewAdd;
20. end
21. end
22. endmodule
(2) ROM(指令存储器)
作用:通过从文件中读取相关的指令,并按照实验要求存储在8位的寄存器中,并根据传入的地址,输出对应地址的指令。
代码:
1. module ROM ( rd, addr, dataOut); // 存储器模块
2. input rd; // 读使能信号
3. input [ 31:0] addr; // 存储器地址
4. output reg [31:0] dataOut; // 输出的数据
5.
6. reg [7:0] rom [99:0]; // 存储器定义必须用reg类型, 存储器存储单元8位长度, 共100个存储单元
7.
8. initial // 加载数据到存储器rom。 注意: 必须使用绝对路径, 如: E:/Xlinx/VivadoProject/ROM/(自己定)
9. begin
10. $readmemb ("D:/Xlinx/VivadoProject/CPU/rom_data.txt", rom); // 数据文件rom_data(.coe或.txt) 。 未指定, 就从0地址开始存放。
11. //rom[addr][7:0] = 1'b00000100;
12. dataOut = 0;
13. end
14.
15. always @( rd or addr ) begin
16. if (rd==1) begin // 为0, 读存储器。 大端数据存储模式
17. dataOut[31:24] = rom[addr];
18. dataOut[23:16] = rom[addr+1];
19. dataOut[15:8] = rom[addr+2];
20. dataOut[7:0] = rom[addr+3];
21. end
22. end
23. endmodule
(3) ControlUnit
作用:根据PC传出的指令,设置相关的控制信号,相关信号的设置,详见实验原理中的控制信号作用表
代码:
1. module ControlUnit(
2. input [5:0] op,
3. input zero,
4. output reg Reset,
5. output reg PCWre,
6. output reg ALUSrcA,
7. output reg ALUSrcB,
8. output reg DBDataSrc,
9. output reg RegWre,
10. output reg InsMemRW,
11. output reg mRD,
12. output reg mWR,
13. output reg RegDst,
14. output reg ExtSel,
15. output reg [1:0] PCSrc,
16. output reg [2:0] ALUOp
17. );
(4) RegFile(寄存器组)
作用:暂时存储指令操作过程中产生的数据。按照实验的要求,设置成8位的寄存器。而且根据输入的读取数据的地址,读取对应寄存器的数据,并根据输入信号RegWre,确定是否能够对寄存器进行写入操作。当RegWre为0时,无法进行写入操作,当RegWre为1时,进行写入操作
代码:
1. module RegFile(CLK,RST,RegWre,ReadReg1,ReadReg2,WriteReg,WriteData,
2. ReadData1,ReadData2);
3. input CLK;
4. input RST;
5. input RegWre;
6. input [4:0] ReadReg1,ReadReg2,WriteReg;
7. input [31:0] WriteData;
8. output [31:0] ReadData1,ReadData2;
9.
10. reg [31:0] regFile[1:31]; // 寄存器定义必须用reg类型
11.
12. initial begin
13. for(i=1;i<32;i=i+1)
14. regFile[i] <= 0;
15. end
16. integer i;
17. assign ReadData1 = (ReadReg1 == 0) ? 0 : regFile[ReadReg1]; // 读寄存器数据
18. assign ReadData2 = (ReadReg2 == 0) ? 0 : regFile[ReadReg2];
19.
20. always @ (negedge CLK or negedge RST) begin // 必须用时钟边沿触发
21. if (RST==0) begin
22. for(i=1;i<32;i=i+1)
23. regFile[i] <= 0;
24. end
25. else if(RegWre == 1 && WriteReg != 0) // WriteReg != 0, $0寄存器不能修改
26. regFile[WriteReg] <= WriteData; // 写寄存器
27. end
28.
29. endmodule
(5) ALU
作用:根据传入的控制信号,对传入的两个值进行相关的算术运算或逻辑运算,除了返回结果外,还有一个输出信号记录结果是否为0。
代码:
1. module ALU(
2. input [2:0] ALUopcode,
3. input [31:0] rega,
4. input [31:0] regb,
5. output reg [31:0] result,
6. output zero
7. );
8. initial
9. begin
10. result = 0;
11. end
12. assign zero = (result==0)?1:0;
13. always @( ALUopcode or rega or regb ) begin
14. case (ALUopcode)
15. 3'b000 : result = rega + regb;
16. 3'b001 : result = rega - regb;
17. 3'b010 : result = regb << rega;
18. 3'b011 : result = rega | regb;
19. 3'b100 : result = rega & regb;
20. 3'b101 : result = (rega < regb)?1:0; // 不带符号比较
21. 3'b110 : begin // 带符号比较
22. if(rega < regb && (rega[31] == regb[31]))result = 1;
23. else if (rega[31] == 1 && regb[31] == 0) result = 1;
24. else result = 0;
25. end
26. 3'b111 : result = rega ^ regb;
27. default : begin
28. result = 32'h00000000;
29. $display (" no match");
30. end
31. endcase
32. end
33. endmodule
(6) RAM(数据存储器)
作用:按照要求,利用8位的寄存器来存储数据。根据传入的控制信号来进行读写操作。当nRD为1时,进行读取操作,当为0时,不进行读取操作,并输出高阻态;当nWR为0时,进行写入操作,当为1时,不进行写入操作。
代码:
1. module RAM(
2. input clk,
3. input [31:0] address,
4. input [31:0] writeData, // [31:24], [23:16], [15:8], [7:0]
5. input nRD, // 为0, 正常读; 为1,输出高组态
6. input nWR, // 为1, 写; 为0, 无操作
7. output [31:0] Dataout
8. );
9.
10. reg [7:0] ram [0:60]; // 存储器定义必须用reg类型
11.
12. // 读
13. //assign是随时赋值语句,Data有变化,随时写进到ram中去
14. assign Dataout[7:0] = (nRD==1)?ram[address + 3]:8'bz; // z 为高阻态
15. assign Dataout[15:8] = (nRD==1)?ram[address + 2]:8'bz;
16. assign Dataout[23:16] = (nRD==1)?ram[address + 1]:8'bz;
17. assign Dataout[31:24] = (nRD==1)?ram[address ]:8'bz;
18. // 写
19. always@( negedge clk ) begin // 用时钟下降沿触发写存储器, 个例
20. if( nWR==0 ) begin
21. ram[address] <= writeData[31:24];
22. ram[address+1] <= writeData[23:16];
23. ram[address+2] <= writeData[15:8];
24. ram[address+3] <= writeData[7:0];
25. end
26. end
27. endmodule
(7) Pccounter
作用:根据传入的信号,进行传入PC的新地址。当PCSrc为0时,新地址将读取下一条指令,即地址加4;当PCSrc为1时,在原有地址的基础上,跳转立即数的指令数目;当PCSrc为2时,跳转到j指令所指向的指令地址。
代码:
1. module PCcounter(
2. input [1:0] PCSrc,
3. input [31:0] currentAddress,
4. output reg [31:0] newAddress,
5. input [31:0] outData,
6. input [25:0] jAddress
7. );
8.
9. wire [31:0] temp_one, temp_two, temp_three;
10. assign temp_one = currentAddress + 4;
11. assign temp_two[25:0] = jAddress[25:0];
12. assign temp_three = temp_two << 2;
13. always@(PCSrc or currentAddress or outData or jAddress or temp_one)
14. begin
15. case(PCSrc)
16. 2'b00: newAddress = currentAddress+4;
17. 2'b01:
18. begin
19. newAddress = (currentAddress+4)+ (outData << 2);
20. newAddress[1:0] = 1'b00;
21. end
22.
23. 2'b10:
24. begin
25. newAddress[31:28] = temp_one[31:28];
26. newAddress[27:0] = temp_three[27:0];
27. end
28. endcase
29. end
30. endmodule
(8) Sign、zero extend
作用:根据传入的控制信号,对出入的数据进行相对应的拓展。当ExtSel为0时,对传入的立即数进行零拓展;当ExtSel为1时,对传入的立即数进行信号拓展。
代码:
1. module Extend(
2. input [15:0] immediate,
3. input ExtSel,
4. output reg[31:0] outData
5. );
6.
7. always@(immediate or ExtSel)
8. begin
9. case(ExtSel)
10. 1'b0:
11. begin
12. outData[15:0] = immediate;
13. outData[31:16] = 16'h0000;
14. end
15. 1'b1:
16. begin
17. outData[15:0] = immediate;
18. outData[31:16] = (immediate[15])? 16'hffff : 16'h0000;
19. end
20. endcase
21. end
22. endmodule
(9) 5bit_selecter
作用:根据传入的控制信号,对两个传入的5位数据进行二选一操作。具体应用在选择rt或者rs作为写入地址。
代码:
1. module select_5_bit(
2. input [4:0] select_one,
3. input [4:0] select_two,
4. input control,
5. output [4:0] result
6. );
7.
8. assign result = (control == 1'b0 ? select_one : select_two);
9. endmodule
(10) 32bit_selecter
作用:根据传入的控制信号,对两个传入的32位数据进行二选一操作。具体应用在传入ALU的数据A的选择、传入ALU的数据B的选择以及写入寄存器中数据的选择。
代码:
1. module select_32_bit(
2. input [31:0] select_one,
3. input [31:0] select_two,
4. input control,
5. output [31:0] result
6. );
7.
8. assign result = (control == 1'b0 ? select_one : select_two);
9. endmodule
2. CPU正确性的验证
为验证所设计CPU的正确性,通过输入以下指令,观察结果来确认
| 地址 | 指令 | op(6) | rs(5) | rt(5) | rd(5)/immediate (16) | 16进制数代码 |
|---|---|---|---|---|---|---|
| 0x00000000 | addi 1, 1 , 1,0,8 | 000001 | 00000 | 00001 | 0000 0000 0000 1000 | = 04010008 |
| 0x00000004 | ori 2, 2 , 2,0,2 | 010000 | 00000 | 00010 | 0000 0000 0000 0010 | 40400002 |
| 0x00000008 | add 3, 3 , 3,2,$1 | 000000 | 00010 | 00001 | 0001 1000 0000 0000 | 00411800 |
| 0x0000000C | sub 5, 5 , 5,3,$2 | 000010 | 00011 | 00010 | 0010 1000 0000 0000 | 08622800 |
| 0x00000010 | and 4, 4 , 4,5,$2 | 010001 | 00101 | 00010 | 0010 0000 0000 0000 | 44A22000 |
| 0x00000014 | or 8, 8 , 8,4,$2 | 010010 | 00100 | 00010 | 0100 0000 0000 0000 | 48824000 |
| 0x00000018 | sll 8, 8 , 8,8,1 | 011000 | 00000 | 01000 | 0100 0000 0100 0000 | 60084040 |
| 0x0000001C | bne 8, 8 , 8,1,-2 (≠,转18) | 110001 | 01000 | 00001 | 1111 1111 1111 1110 | C501FFF2 |
| 0x00000020 | slti 6, 6 , 6,2,8 | 011011 | 00010 | 00110 | 0000 0000 0000 1000 | 6C460008 |
| 0x00000024 | slti 7, 7 , 7,6,0 | 011011 | 00110 | 00111 | 0000 0000 0000 0000 | 6CC70000 |
| 0x00000028 | addi 7, 7 , 7,7,8 | 000001 | 00111 | 00111 | 0000 0000 0000 1000 | 04E70008 |
| 0x0000002C | beq 7, 7 , 7,1,-2 (=,转28) | 110000 | 00111 | 00001 | 1111 1111 1111 1110 | C0E1FFFE |
| 0x00000030 | sw 2,4( 2 , 4 ( 2,4(1) | 100110 | 00001 | 00010 | 0000 0000 0000 0100 | 98220004 |
| 0x00000034 | lw 9,4( 9 , 4 ( 9,4(1) | 100111 | 00001 | 01001 | 0000 0000 0000 0100 | 9C290004 |
| 0x00000038 | j 0x00000040 | 111000 | 00000 | 00000 | 0000 0000 0001 0000 | E0000010 |
| 0x0000003C | addi 10, 10 , 10,0,10 | 000001 | 00000 | 01010 | 0000 0000 0000 1010 | 040A000A |
| 0x00000040 | halt | 111111 | 00000 | 00000 | 0000000000000000 = | FC000000 |
| 0x00000044 | ||||||
| 0x00000048 | ||||||
| 0x0000004C |
测试代码跟其他的配置文件见文章开头的优快云下载
这两年,IT行业面临经济周期波动与AI产业结构调整的双重压力,确实有很多运维与网络工程师因企业缩编或技术迭代而暂时失业。
很多人都在提运维网工失业后就只能去跑滴滴送外卖了,但我想分享的是,对于运维人员来说,即便失业以后仍然有很多副业可以尝试。
网工/运维/测试副业方向
运维网工,千万不要再错过这些副业机会!
第一个是知识付费类副业:输出经验打造个人IP
在线教育平台讲师
操作路径:在慕课网、极客时间等平台开设《CCNA实战》《Linux运维从入门到精通》等课程,或与培训机构合作录制专题课。
收益模式:课程销售分成、企业内训。
技术博客与公众号运营
操作路径:撰写网络协议解析、故障排查案例、设备评测等深度文章,通过公众号广告、付费专栏及企业合作变现。
收益关键:每周更新2-3篇原创,结合SEO优化与社群运营。
第二个是技术类副业:深耕专业领域变现
企业网络设备配置与优化服务
操作路径:为中小型企业提供路由器、交换机、防火墙等设备的配置调试、性能优化及故障排查服务。可通过本地IT服务公司合作或自建线上接单平台获客。
收益模式:按项目收费或签订年度维护合同。
远程IT基础设施代维
操作路径:通过承接服务器监控、日志分析、备份恢复等远程代维任务。适合熟悉Zabbix、ELK等技术栈的工程师。
收益模式:按工时计费或包月服务。
网络安全顾问与渗透测试
操作路径:利用OWASP Top 10漏洞分析、Nmap/BurpSuite等工具,为企业提供漏洞扫描、渗透测试及安全加固方案。需考取CISP等认证提升资质。
收益模式:单次渗透测试报告收费;长期安全顾问年费。
比如不久前跟我一起聊天的一个粉丝,他自己之前是大四实习的时候做的运维,发现运维7*24小时待命受不了,就准备转网安,学了差不多2个月,然后开始挖漏洞,光是补天的漏洞奖励也有个四五千,他说自己每个月的房租和饭钱就够了。

为什么我会推荐你网安是运维和网工测试人员的绝佳副业&转型方向?
1.你的经验是巨大优势: 你比任何人都懂系统、网络和架构。漏洞挖掘、内网渗透、应急响应,这些核心安全能力本质上是“攻击视角下的运维”。你的运维背景不是从零开始,而是降维打击。
2.越老越吃香,规避年龄危机: 安全行业极度依赖经验。你的排查思路、风险意识和对复杂系统的理解能力,会随着项目积累而愈发珍贵,真正做到“姜还是老的辣”。
3.职业选择极其灵活: 你可以加入企业成为安全专家,可以兼职“挖洞“获取丰厚奖金,甚至可以成为自由顾问。这种多样性为你提供了前所未有的抗风险能力。
4.市场需求爆发,前景广阔: 在国家级政策的推动下,从一线城市到二三线地区,安全人才缺口正在急剧扩大。现在布局,正是抢占未来先机的黄金时刻。

网工运维测试转行学习网络安全路线

(一)第一阶段:网络安全筑基
1. 阶段目标
你已经有运维经验了,所以操作系统、网络协议这些你不是零基础。但要学安全,得重新过一遍——只不过这次我们是带着“安全视角”去学。
2. 学习内容
**操作系统强化:**你需要重点学习 Windows、Linux 操作系统安全配置,对比运维工作中常规配置与安全配置的差异,深化系统安全认知(比如说日志审计配置,为应急响应日志分析打基础)。
**网络协议深化:**结合过往网络协议应用经验,聚焦 TCP/IP 协议簇中的安全漏洞及防护机制,如 ARP 欺骗、TCP 三次握手漏洞等(为 SRC 漏扫中协议层漏洞识别铺垫)。
**Web 与数据库基础:**补充 Web 架构、HTTP 协议及 MySQL、SQL Server 等数据库安全相关知识,了解 Web 应用与数据库在网安中的作用。
**编程语言入门:**学习 Python 基础语法,掌握简单脚本编写,为后续 SRC 漏扫自动化脚本开发及应急响应工具使用打基础。
**工具实战:**集中训练抓包工具(Wireshark)、渗透测试工具(Nmap)、漏洞扫描工具(Nessus 基础版)的使用,结合模拟场景练习工具应用(掌握基础扫描逻辑,为 SRC 漏扫工具进阶做准备)。
(二)第二阶段:漏洞挖掘与 SRC 漏扫实战
1. 阶段目标
这阶段是真正开始“动手”了。信息收集、漏洞分析、工具联动,一样不能少。
熟练运用漏洞挖掘及 SRC 漏扫工具,具备独立挖掘常见漏洞及 SRC 平台漏扫实战能力,尝试通过 SRC 挖洞搞钱,不管是低危漏洞还是高危漏洞,先挖到一个。
2. 学习内容
信息收集实战:结合运维中对网络拓扑、设备信息的了解,强化基本信息收集、网络空间搜索引擎(Shodan、ZoomEye)、域名及端口信息收集技巧,针对企业级网络场景开展信息收集练习(为 SRC 漏扫目标筛选提供支撑)。
漏洞原理与分析:深入学习 SQL 注入、CSRF、文件上传等常见漏洞的原理、危害及利用方法,结合运维工作中遇到的类似问题进行关联分析(明确 SRC 漏扫重点漏洞类型)。
工具进阶与 SRC 漏扫应用:
-
系统学习 SQLMap、BurpSuite、AWVS 等工具的高级功能,开展工具联用实战训练;
-
专项学习 SRC 漏扫流程:包括 SRC 平台规则解读(如漏洞提交规范、奖励机制)、漏扫目标范围界定、漏扫策略制定(全量扫描 vs 定向扫描)、漏扫结果验证与复现;
-
实战训练:使用 AWVS+BurpSuite 组合开展 SRC 平台目标漏扫,练习 “扫描 - 验证 - 漏洞报告撰写 - 平台提交” 全流程。
SRC 实战演练:选择合适的 SRC 平台(如补天、CNVD)进行漏洞挖掘与漏扫实战,积累实战经验,尝试获取挖洞收益。
恭喜你,如果学到这里,你基本可以下班搞搞副业创收了,并且具备渗透测试工程师必备的「渗透技巧」、「溯源能力」,让你在黑客盛行的年代别背锅,工作实现升职加薪的同时也能开创副业创收!
如果你想要入坑黑客&网络安全,笔者给大家准备了一份:全网最全的网络安全资料包需要保存下方图片,微信扫码即可前往获取!
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
(三)第三阶段:渗透测试技能学习
1. 阶段目标
全面掌握渗透测试理论与实战技能,能够独立完成渗透测试项目,编写规范的渗透测试报告,具备渗透测试工程师岗位能力,为护网红蓝对抗及应急响应提供技术支撑。
2. 学习内容
渗透测试核心理论:系统学习渗透测试流程、方法论及法律法规知识,明确渗透测试边界与规范(与红蓝对抗攻击边界要求一致)。
实战技能训练:开展漏洞扫描、漏洞利用、电商系统渗透测试、内网渗透、权限提升(Windows、Linux)、代码审计等实战训练,结合运维中熟悉的系统环境设计测试场景(强化红蓝对抗攻击端技术能力)。
工具开发实践:基于 Python 编程基础,学习渗透测试工具开发技巧,开发简单的自动化测试脚本(可拓展用于 SRC 漏扫自动化及应急响应辅助工具)。
报告编写指导:学习渗透测试报告的结构与编写规范,完成多个不同场景的渗透测试报告撰写练习(与 SRC 漏洞报告、应急响应报告撰写逻辑互通)。
(四)第四阶段:企业级安全攻防(含红蓝对抗)、应急响应
1. 阶段目标
掌握企业级安全攻防、护网红蓝对抗及应急响应核心技能,考取网安行业相关证书。
2. 学习内容
护网红蓝对抗专项:
-
红蓝对抗基础:学习护网行动背景、红蓝对抗规则(攻击范围、禁止行为)、红蓝双方角色职责(红队:模拟攻击;蓝队:防御检测与应急处置);
-
红队实战技能:强化内网渗透、横向移动、权限维持、免杀攻击等高级技巧,模拟护网中常见攻击场景;
-
蓝队实战技能:学习安全设备(防火墙、IDS/IPS、WAF)联动防御配置、安全监控平台(SOC)使用、攻击行为研判与溯源方法;
-
模拟护网演练:参与团队式红蓝对抗演练,完整体验 “攻击 - 检测 - 防御 - 处置” 全流程。
应急响应专项: -
应急响应流程:学习应急响应 6 步流程(准备 - 检测 - 遏制 - 根除 - 恢复 - 总结),掌握各环节核心任务;
-
实战技能:开展操作系统入侵响应(如病毒木马清除、异常进程终止)、数据泄露应急处置、漏洞应急修补等实战训练;
-
工具应用:学习应急响应工具(如 Autoruns、Process Monitor、病毒分析工具)的使用,提升处置效率;
-
案例复盘:分析真实网络安全事件应急响应案例(如勒索病毒事件),总结处置经验。
其他企业级攻防技能:学习社工与钓鱼、CTF 夺旗赛解析等内容,结合运维中企业安全防护需求深化理解。
证书备考:针对网安行业相关证书考试内容(含红蓝对抗、应急响应考点)进行专项复习,参加模拟考试,查漏补缺。
运维网工测试转行网络攻防知识库分享
网络安全这行,不是会几个工具就能搞定的。你得有体系,懂原理,能实战。尤其是从运维转过来的,别浪费你原来的经验——你比纯新人强多了。
但也要沉得住气,别学了两天Web安全就觉得自己是黑客了。内网、域渗透、代码审计、应急响应,要学的还多着呢。
如果你真的想转,按这个路子一步步走,没问题。如果你只是好奇,我劝你再想想——这行要持续学习,挺累的,但也是真有意思。
关于如何学习网络安全,笔者也给大家整理好了全套网络安全知识库,需要的可以扫码获取!
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
1、网络安全意识

2、Linux操作系统

3、WEB架构基础与HTTP协议

4、Web渗透测试

5、渗透测试案例分享

6、渗透测试实战技巧

7、攻防对战实战

8、CTF之MISC实战讲解

关于如何学习网络安全,笔者也给大家整理好了全套网络安全知识库,需要的可以扫码获取!
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

1321

被折叠的 条评论
为什么被折叠?



