第10章 call和ret指令

引言:

call和ret都是转移指令,他们都修改ip,或同时修改cs和ip。

他们经常被共同用来实现程序的设计

10.1  ret和retf

ret指令用栈中的数据,修改ip的内容,从而实现近转移。

retf指令用栈中的数据,修改cs和ip的内容,从而实现远转移;

可以看出,如果我们用汇编语法来解释ret和retf指令,则

cpu执行ret指令时,相当于进行:

pop  ip

cpu执行retf指令时,相当于进行:

pop  ip

pop  cs

 

10.2  call指令

cpu执行call指令,进行两步操作:

1)将当前的ip或cs和ip压入栈中;

2)转移

call指令不能实现短转移,除此之外,call指令实现转移的方法和jmp指令的原理相同,下面的几个小节中,我们以给出转移目的地址的不同方法为主线,讲解call指令的主要应用格式

 

10.3   依据位移进行转移的call指令

call标号(将当前的ip压入栈后,转到标号处执行指令)

cpu执行此种格式的call指令时,进行如下的操作:

1)sp=sp-2

2)ip=ip+16位位移

call标号

16位位移=标号处的地址--call指令后的第一个字节的地址;

16位位移的范围为-32768~32767,用补码表示

16位位移由编译程序在编译时算出。

从上面的描述中,可以看出,如果我们用汇编语法来解释此种格式的call指令,则:

cpu执行指令call标号时,相当于进行:

push  ip

jmp  near  ptr  标号

 

10.4   转移的目的地址在指令中的call指令

前面讲解的call指令,其对应的机器指令中并没有转移的目的地址,而是相对于当前ip的转移位移。

指令call  far  ptr  标号  实现的是段间转移

cpu执行call fat  ptr  标号这种格式的call指令时的操作:

1)sp=sp-2

ssx16+sp=cs

sp=sp-2

ssx16+sp=ip

2)cs=标号所在的段地址

ip=标号所在的偏移地址

 

cpu执行指令call  far  ptr  标号时,相当于进行:

push  cs

push  ip

jmp  far  ptr  标号

 

10.5   转移地址在寄存器中的call指令

指令格式:call  16位寄存器

功能:

sp=sp-2

ss*16+sp=ip

ip=(16位寄存器)

 

汇编语法解释此种格式的call指令,cpu执行call16位reg时,相当于进行:

push  ip

jmp   16位寄存器

 

10.6  转移地址在内存中的call指令

转移地址在内存中的call指令有两种格式:

1)call word   ptr  内存单元地址

汇编语法解释:

push  ip

jmp  word   ptr  内存单元地址

 

例如:

mov   sp,10h

mov ax,0123h

mov ds:[0],ax

call word ptr ds:[0]

执行后,ip=0123h,sp=0eh

 

2)call  dword  ptr  内存单元地址

汇编语法解释:

push  cs

push   ip

jmp   dword   ptr   内存单元地址

 

例如:

mov  sp,10h

mov ax,0123h

mov ds:[0],ax

mov word ptr ds:[2],0

call dword  ptr  ds:[0]

执行后,cs=0,ip=0123h,sp=0ch

 

10.7  call和ret的配合使用

我们看一下call和ret如何配合使用来实现子程序的机制

 

 

我们来看以下cpu执行这个程序的主要过程:

1)cpu将call s指令的机器码读入,ip指向了call  s后的指令mov  bx, ax,然后cpu执行call  s指令,将当前的ip值(指令mov  bx,ax的偏移地址)压栈,并将ip的值改变为标号s处的偏移地址。

2)cpu从标号s处开始执行指令,loop循环完毕,ax=8

3)cpu将ret指令的机器码读入,ip指向了ret指令后的内存单元,然后cpu执行ret指令,从栈中弹出一个值(即call先前压入栈的mov  bx, ax指令的偏移地址)送入ip中。则cs:ip指向指令mov  bx ,ax

4)cpu从mov  bx ,ax开始执行指令,直至完成。

 

10.8  mul指令

mul是乘法指令,使用mul做乘法的时候:

1)相乘的两个数,要么都是8位,要么都是16位

8位:al中的8位寄存器或内存字节单元中

16位:ax中的16位寄存器或内存字单元中。

2)结果

8位:ax中

16位:dx(高位)和ax(低位)中

格式如下:

mul  reg

mul   内存单元

 

内存单元可以用不同的寻址方式给出,比如:

mul  byte ptr  ds:[0]

含义为:ax=al*(ds*16+0)

 

mul  word  ptr  [bx+si+8]

含义为:

ax=al*(ds*16+bx+si+8)结果的低16位

dx=al*(dx*16+bx+si+8)结果的高16位

 

例如:

1)计算100*10

100和10小于255,可以做8位乘法,程序如下:

mov  al,100

mov  bl,10

mul  bl

结果ax=1000

 

2)计算100*10000

100小于255,可10000大于255,所以必须做16位乘法,程序如下:

mov  ax,100

mov bx,10000

mul bx

结果  ax=4240h,dx=000fh

(f4240h=1000000)

 

10.11批量数据的传递

当参数过多时,如何实现参数传递?

在这种时候,我们将批量数据放到内存中,然后将他们所在内存空间的首地址放在寄存器中,传递给需要的子程序。

对于具有批量数据的返回结果,也可用同样的方法。

 

posted @ 2020-05-23 21:07  ice--cream  阅读(511)  评论(0编辑  收藏  举报