16位间接绝对远调用

16位间接绝对远调用

Content #

这也属于段间调用,被调用过程位于另一个代码段内,而且,被调用过程所在的段地址和偏移地址是间接给出的。还有,这里的“16 位”同样是用来限定偏移地址的。

下面是这种调用方式的几个例子:

call far [0x2000]
call far [proc_1]
call far [bx]
call far [bx+si]

间接远调用必须使用关键字“far”,这一点务必牢记。

因为是远调用,也就是段间调用,所以,必须给出被调用过程的段地址和偏移地址。但是,段地址和偏移地址在内存中的其他位置,指令中仅仅给出的是该位置的偏移地址,需要处理器在执行指令的时候自行按图索骥,找到它们。

以上,前两条指令是等效的,不同之处仅仅在于,第一条指令直接给出的是数值,而第二条指令用的是标号。但这无关紧要,在编译后,标号也会变成数值。

下面是一个实例。假如在数据段内声明了标号proc_1 并初始化了两个字:

proc_1 dw 0x0102, 0x2000

这两个字分别是某个过程的段地址和偏移地址。按处理器的要求,偏移地址在前,段地址在后。也就是说,0x0102 是偏移地址; 0x2000 是段地址。

那么,为了调用该过程,可以在代码段内使用这条指令:

call far [proc_1]

这条指令执行过程如下:

  1. 访问由段寄存器DS 指向的数据段,从指令中指定的偏移地址(由标号proc_1 提供)处取得两个字(分别是段地址0x2000 和偏移地址0x0102);
  2. 将代码段寄存器CS 和指令指针寄存器IP 的当前内容分别压栈;
  3. 用刚才取得的段地址和偏移地址分别取代CS 和IP 的原值。

From #