51 单片机汇编语言:利用 RET 指令实现多路分支

在百度知道上有这样一个问题:
------------------------------
已知程序执行前有 A = 02H,SP = 52H,(51H) = FFH,(52H) = FFH。
执行下列程序:
  POP  DPH
  POP  DPL
  MOV  DPTR, #4000H 
  RL  A
  MOV  B, A
  MOVC A, @A + DPTR
  PUSH A
  MOV  A, B
  INC  A
  MOVC A, @A + DPTR
  PUSH A
  RET
  ORG  4000H
  DB  10H, 80H, 30H, 50H, 30H, 50H
求程序执行后:
A=( )H、SP=( )H、(51H) =( )H、(52H)=( )H、PC=(  )H。
------------------------------

这个问题,在百度知道出现过很多次,搜一下,就会出来几十个链接。
但是回答正确的,确实不多。

有的提问者,好像是说,这是什么学校教材上的习题。
但是,在这个程序中,写错了两条指令:

非法指令:PUSH  A
应该写成:PUSH  ACC
做为教材来说,这可是一个 BUG 啊,呵呵

这个程序,是利用 RET 指令来进行多路分支。
程序中,有两条查表指令:MOVC A, @A + DPTR,
 当 A = 0 时,将从 4000H 处,先后读出 10H、80H;
 当 A = 1 时,将从 4000H 处,先后读出 30H、50H;
 当 A = 2 时,将从 4000H 处,先后读出 30H、50H。
本题目的条件已经给出:A = 02H,那么就是读出了 30H、50H。
读出数据后,先后压栈,再执行 RET。
RET 指令,就是把堆栈中的两个字节,送到 PC。
那么,PC = 5030H,就是这么来的。
全部的空格,填写如下:
A=(50)H、SP=(50)H、(51H) =(30)H、(52H)=(50)H、PC=(5030)H。
------------------------------
本程序,是个子程序结构,应该用 CALL 指令来调用。
在本程序开始处,用 POP 指令,抛弃了 CALL 自动保存的返回地址。
腾出了两个字节的堆栈空间,又压入两字节数据,然后,再返回。
RET 返回指令,就会用刚刚压入两字节数据,当做返回地址。
本程序,是属于偷梁换柱,还是移花接木 ?
------------------------------
下面逐条解释一下:
  POP  DPH
  POP  DPL      ;弹出两次,SP = SP - 2 = 50H
  MOV  DPTR, #4000H 
  RL  A       ;乘以 2
  MOV  B, A     ;B = 04H
  MOVC A, @A + DPTR ;取出第 4 个字节 30H
  PUSH ACC     ;SP = SP + 1 = 51H, (51H) = 30H
  MOV  A, B
  INC  A       ;A = 05H
  MOVC A, @A + DPTR ;取出第 5 个字节 50H
  PUSH ACC     ;SP = SP + 1 = 52H, (52H) = 50H
  RET         ;子程序返回, SP = SP - 2 = 50H
执行 RET 指令时,是从堆栈中弹出两个字节到 PC 的高、低八位。
即:
  (SP) → PCH,然后 SP - 1 → SP;
  (SP) → PCL,然后 SP - 1 → SP。
即:
  (52H) = 50H → PCH,SP = 51H;
  (51H) = 30H → PCL,SP = 50H。
那么,PC = 5030H,就是这么来的。
------------------------------
进行多路分支,还有简单一点的方法。
如,利用指令:JMP @A + DPTR,就可以。
那么,前面的程序,可以改为:
  MOV  DPTR, #4000H 
  RL  A
  MOV  B, A
  MOVC A, @A + DPTR 
  XCH  A, B
  INC  A
  MOVC A, @A + DPTR ;先后读出两字节
  MOV  DPH, A    ;把读出数据送到 DPTR
  MOV  DPL, B
  CLR  A      ;A=0
  JMP  @A + DPTR  ;以 DPTR 内容为目的地,转移
  ORG  4000H
  DB  10H, 80H, 30H, 50H, 30H, 50H
程序这样写,就不涉及堆栈了,也就没有前一个程序那么复杂的推导。
理解起来,可以轻松些。
这个程序中,没有使用 RET 指令,所以,就不要用 CALL 来调用了。
应该用 JMP 指令来应用本程序。

------------------------------
题目链接:

 http://zhidao.baidu.com/question/62813244.html

 http://zhidao.baidu.com/question/508425830.html

 http://zhidao.baidu.com/question/586060870.html

 http://zhidao.baidu.com/question/205965529.html
------------------------------

--本文完--

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值