CPU采用流水线设计,跳转时的运行周期更长,则写代码时要尽量减少跳转(跳转断流水线)

流水线设计思想
设计的处理器是五级流水处理器,取指,译码,执行,访存,回写。
(1)取指: 取出指令存储器中的指令,PC值递增,准备取下一条指令。
(2)译码:对指令进行译码,依据译码结果,从32个通用寄存器中取出源操作数,有的 指令要求两个源操作数都是寄存器的值,比如or指令,有的指令要求其中一 个源操作数是指令中立即数的扩展,比如ori指令,所以这里有两个复用器, 用于依据指令要求,确定参与运算的操作数,最终确定的两个操作数会送到执 行阶段。
(3)执行:依据译码阶段送入的源操作数、操作码,进行运算,对于ori指令而言, 就是进行逻辑“或”运算,运算结果传递到访存阶段。
(4)访存:对于ori指令,在访存阶段没有任何操作,直接将运算结果向下传递到回写阶 段。
(5)回写:将运算结果保存到目的寄存器。

在程序指令依次执行的情况下,CPU流水线条数和CPU性能成正比。但当程序指令出现跳转或分支结构时就要另当别论了。比如当指令是jmp (无条件的转移到指令指定的地址去执行从该地址开始的命令)指令时,jmp指令会直接修改指令指针寄存器IP中的指令地址,所以当jmp指令执行时,指令指针寄存器IP中的指令地址会被更新,下一条指令应该是更新后新地址的第一条指令,之前流水线中的指令二到指令十都是无效指令了,这个时候就需要清空流水线中的指令,就意味着清空所有的独立电路以及相关寄存器,这个过程显然流水线越多 耗时越多 代价越大。

示例:

这种代码可读性较强,但跳转较多,程序运行周期较长

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
MyStack segment stack      
db 256 dup(?)
MyStack ends

MyData segment
MSG1 db "Hello World!",0dh,0ah,'$'
MyData ends

MyCode segment
MAIN:
mov ax,MyData
mov ds,ax
mov es,ax

;if(ax>1) bx=0
cmp ax,1
jg IF1 ;ax>1
jmp IF_END1 ;ax<=1
IF1:
mov bx,0

IF_END1:
mov ax,4c00h
int 21h
MyCode ends

end MAIN

这种代码更简洁,且跳转较少,效率更高,由此可知将if中判断的内容取反可使程序更加高效

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
MyStack segment stack      
db 256 dup(?)
MyStack ends

MyData segment
MSG1 db "Hello World!",0dh,0ah,'$'
MyData ends

MyCode segment
MAIN:
mov ax,MyData
mov ds,ax
mov es,ax

;if(ax>1) bx=0 条件取反
cmp ax,1
jle IF_END1 ;小于等于时再跳转
mov bx,0

IF_END1:
mov ax,4c00h
int 21h
MyCode ends

end MAIN

双分支常规写法

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
MyStack segment stack      
db 256 dup(?)
MyStack ends

MyData segment
MSG1 db "Hello World!",0dh,0ah,'$'
MyData ends

MyCode segment
MAIN:
mov ax,MyData
mov ds,ax
mov es,ax

;if(ax>1) bx=0 else bx=1
cmp ax,1
jle IF_ELSE1 ;ax<=1
mov bx,0 ;ax>1
jmp IF_ELSE_END1
IF_ELSE1:
mov bx,1
IF_ELSE_END1:
mov ax,4c00h
int 21h
MyCode ends

end MAIN

这种写法在判断条件成立时可以不用跳转,但在不成立时需要跳转两次,故建议在判断条件成立的概率较大时采用这种写法

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
MyStack segment stack      
db 256 dup(?)
MyStack ends

MyData segment
MSG1 db "Hello World!",0dh,0ah,'$'
MyData ends

MyCode segment
MAIN:
mov ax,MyData
mov ds,ax
mov es,ax

;if(ax>1) bx=0 else bx=1
cmp ax,1
jle IF_ELSE1 ;ax<=1
mov bx,0 ;ax>1

IF_ELSE_END1
mov ax,4c00h
int 21h

IF_ELSE1:
mov bx,1
jmp IF_ELSE_END1
MyCode ends

end MAIN

多分支

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
30
31
32
33
34
35
MyStack segment stack      
db 256 dup(?)
MyStack ends

MyData segment
MSG1 db "Hello World!",0dh,0ah,'$'
MyData ends

MyCode segment
MAIN:
mov ax,MyData
mov ds,ax
mov es,ax

;if(ax>1) bx=0 else if(ax==-2) bx=1 else bx=2
cmp ax,1
jle IF_ELSE1 ;ax<=1
mov bx,0 ;ax>1
jmp IF_ELSE_END1

IF_ELSE1:
cmp ax,-2
jne IF_ELSE2 ;ax!=-2
mov bx,1 ;ax==-2
jmp IF_ELSE_END1
IF_ELSE2:
mov bx,2

IF_ELSE_END1
mov ax,4c00h
int 21h

MyCode ends

end MAIN

switch

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
30
31
32
33
34
35
36
37
38
39
40
MyStack segment stack      
db 256 dup(?)
MyStack ends

MyData segment
MSG1 db "Hello World!",0dh,0ah,'$'
MyData ends

MyCode segment
MAIN:
mov ax,MyData
mov ds,ax
mov es,ax

;switch 1 2 3
cmp ax,1
je CASE1
cmp ax,2
je CASE2
cmp ax,3
je CASE3
jmp CASE_END1
CASE1:
mov bx,1
jmp CASE_END1
CASE2:
mov bx,2
jmp CASE_END1
CASE3:
mov bx,3
jmp CASE_END1
DEFAULT1:
mov bx,4
CASE_END1:
mov ax,4c00h
int 21h

MyCode ends

end MAIN