计算机系统-寻址

阅读本笔记之前确保已经了解了CPU指令的概念
寻址包含两种,指令寻址和操作数寻址,相对来说,任何CPU,指令寻址都要比操作数寻址简单,注意,以下讨论中以80x86为例,并且讨论中不包括四地址这种情况

一.指令寻址

1.1顺序寻址
这是最基本的寻址方式,当一条指令执行完毕之后,程序计数器(PC)自动增加,于是就形成了下一条指令的地址,这样CPU就可以顺序的执行下一条指令地址了

1.2跳跃寻址

1.2.1无条件跳跃寻址
C语言中的goto就是跳跃寻址,说白了就是不需要任何条件,直接跳转到其他分支

int main()
{
	printf("A");
	goto C;
	printf("B");
	C:
	printf("C");
}

这段代码就是执行了跳跃寻址,正常情况下应该打印出“B”的,但是由于goto关键词的存在,所以跳过了B,直接打印出了C,下面是上述C代码的反汇编代码片段,我们可以看到jmp指令就是跳跃指令

000718A3  call        @__CheckForDebuggerJustMyCode@4 (071217h)  
	printf("A\n");
000718A8  push        offset string "A\n" (077B30h)  
000718AD  call        _printf (07104Bh)  
000718B2  add         esp,4  
	goto C;
000718B5  jmp         C (0718C6h)  //表示跳转到0718C6地址执行
000718B7  jmp         C (0718C6h)  //表示跳转到0718C6地址执行
	printf("B\n");
000718B9  push        offset string "B\n" (077BD0h)  
000718BE  call        _printf (07104Bh)  
000718C3  add         esp,4  
	C:
	printf("C\n");
// 会跳转到这里执行代码
000718C6  push        offset string "C\n" (077BD4h)  
000718CB  call        _printf (07104Bh)  
000718D0  add         esp,4 

1.2.2有条件跳跃寻址
很多高级语言都有if关键字,if就是有条件跳跃寻址,比如下面的代码

int main()
{
	int a = 3;
	if (a==0) {
		a == 1;
	}
}

汇编指令如下

	int a = 3;
00B917B8  mov         dword ptr [a],3  
	if (a==0) {
00B917BF  cmp         dword ptr [a],0  // 注意此处cmp操作ZF标志位
00B917C3  jne         main+3Ch (0B917CCh)  
		a = 1;
00B917C5  mov         dword ptr [a],1  
	}
}

上述代码首先,if(a==0)会执行cmp操作,用a减0,将结果存放到ZF标志位中,然后下一条指令去读取ZF标志位,由ZF标志位决定是否跳转,而不是CPU判断a是否等于0,来决定跳转,切记
我们可以简单的理解成,无论a是否==于0,都会进入到if里,至于是否再继续执行,则是CPU去判断ZF标志位来决定的了

下面介绍if,else语句,很有意义,希望仔细阅读

int main()
{
	int a = 3;
	if (a==0) {
		a = 1;
	}
	else {
		a = 2;
	}
}

其对应的汇编如下

	int a = 3;
00BD17B8  mov         dword ptr [a],3  
	if (a==0) {
00BD17BF  cmp         dword ptr [a],0  
00BD17C3  jne         main+3Eh (0BD17CEh)  
		a = 1;
00BD17C5  mov         dword ptr [a],1  
	}
	else {
00BD17CC  jmp         main+45h (0BD17D5h)  
		a = 2;
00BD17CE  mov         dword ptr [a],2  
	}
0BD17D5

首先执行cmp命令,将比较结果存到ZF,如果CPU判断ZF为1则相等,那么jne指令则无法满足,则不跳转,执行代码a=1,执行完代码a=1之后,你以为不进入else了????其实代码会进入到else的,但是,else里面的第一条指令就是jmp,直接跳转到0BD17D5位置了,也就是说没有执行else里的其他代码

如果CPU根据ZF标志位加上一些其他标志位判断出a不等于0,则触发jne这个跳转命令,跳转到0BD17CE位置,这个位置就是执行了mov操作,也就是代码里的a=2

循环语句也会导致有条件跳跃寻址

还有一个我们大家每天都在用的,函数调用(方法调用),也会导致有条件跳跃寻址,博客里就不写了,内容太多也不爱看,他们的本质都是与if相同的

二.操作数寻址

2.1立即寻址
操作数里面装的内容就是该值本身,比如代码

a=1+2

那么操作数寻址就是add 1 2,当然,add是我臆想出来的指令,不过只是举例,就是说,add后面接的两个操作数,是1和2两个值本身
2.2直接寻址
还是上述代码a=1+2
那么直接寻址就是add 0x1234 0x5678,然后再通过0x1234找到值1,通过0x5678找到值2,之后再相加
2.3间接寻址
还是上述代码a=1+2
简介寻址就是add 0x1234 0x5678,然后通过0x1234找到值0x4444(注意此处是根据地址又找到了一个地址,理论上可以无限往复循环找地址),然后在根据0x4444继续往下找,一直找到真正的值1,这就叫间接寻址
2.4寄存器寻址
只的是操作数里装的是地址,但是这个地址不是主存的地址,而是某个寄存器的地址
寄存器直接寻址:假设有个操作是op a,表示对a进行op操作,那么这a其实是某个寄存器的地址,通过a,在某个寄存器中找到a真正的值
寄存器间接寻址:假设有个操作是op a,表示对a进行op操作,那么这a其实是某个寄存器的地址,通过a,在某个寄存器中找到a在主存中的地址,然后在根据这个主存中的地址,去主存中拿到a真正的值
2.5偏移寻址
对于偏移寻址,此处我不太明白,待以后再研究吧
偏移寻址包括相对寻址,基址寄存器寻址,变址寻址;
相对寻址:经常被用在跳转指令中,跳转后的目标地址与当前地址有一定的距离,这个距离就叫做相对偏移量。
基址寄存器寻址:
变址寻址:
2.6堆栈寻址
现代计算机完成函数调用时所使用的寻址方式
首先计算机必须提供堆栈结构,堆栈结构是现代数据结构中的一个概念,堆栈可以使用寄存器来实现,这叫做硬堆栈,堆栈也可是使用主存来实现,这叫做软堆栈,它是一种先进后出的读数读写顺序模型

代码揭秘P181

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章