汇编语言子例程

时间:2011-11-01 03:50:29

标签: assembly stack subroutine

这部分让我彻底迷茫。我有一个示例问题,我希望有人可以为我分解步骤,以便我可以吸收如何应用于其他问题。

mc:   call subr
mr:   mov  [val],ax
subr: push ax
      push bx
      push cx
      add  ax,dx
      pop  ax
      pop bx
      pop cx
      ret

本书询问当代码从子例程返回并到达指令mr: mov [val],ax时,sp和ax寄存器中的十六进制值将是什么。 sp=0100 ax=0002,但我不知道如何得出这些答案。

指令mc: call subr将下一个顺序指令mr: mov [val],ax的地址保存在堆栈中,以便子程序可以正确返回。保存返回地址的内存中的绝对地址为1120E。任何人都可以详细说明这个吗?

registers given:
ax = 0000  bx = 0001  cx = 0002  dx = 0004
si = 0000  di = FFFF  bp = 0080  sp = 0100
cs = 1000  ds = 1100  es = 1110  ss = 1111

1 个答案:

答案 0 :(得分:1)

mc:处的来电将保存当前地址,因此当subr:返回时,控制权将再次从mr:开始。

由于subr:按顺序推送ax,bx和cx。然后它按顺序弹出ax,bx和cx,因此从cx推送的内容会弹出到ax(反之亦然)。这些效果是交换ax和cx。 add ax, dx对产生的结果没有实际影响,因为在将dx添加到ax之后立即将其从堆栈中弹出。 add确实会影响标志,但这里没有任何内容可以根据标志做任何事情,所以至少在您显示的代码中,这并不意味着什么。

控制返回mr:后,它将ax中的值写入内存,然后流回subr:,从而将ax和cx交换回它们开始的位置。

IOW,整体来说这是一种非常缓慢,迂回的方式,可以达到与以下几乎相同的效果:

mc: mov [val], cx
    ret

就绝对地址而言,没有太多可说的。特别值得一提的是,如果再次运行相同的代码,它可能会被加载到不同的地址,o堆栈中保存的地址可能完全不同。