assembly 如何在SuperH汇编中进行多次分支?

xtupzzrd  于 2023-02-16  发布在  其他
关注(0)|答案(1)|浏览(111)

我编写了一个SuperH汇编子例程,用于将像素绘制到屏幕上:

# r3: x coord
# r4: y coord
# r5: pixel color
draw_pixel:
  mov.l frame_buffer_address, r0
  mov.l screen_width, r6
  mul.l r6, r4
  sts macl, r4
  add r4, r3
  add r3, r0

  mov r5, r1
  mov.b r1, @r0 

  rts 
  nop

然后我可以从我的程序分支如下:

mov #20, r3
  mov #50, r4
  mov #10, r5
  bsr draw_pixel
  nop

这工作得很完美,我可以用不同的参数做多次,这一切都工作得很好。
当我试图从另一个子例程分支到draw_pixel时,我开始遇到麻烦。(我想画一个矩形,但现在我只画一个像素,直到它正确工作)

draw_rect:
  mov #50, r3
  mov #20, r4
  mov #4, r5
  bsr draw_pixel
  nop

  rts
  nop

我试着从我的程序中调用它:

bsr draw_rect
  nop

这不起作用。我怀疑这与分支到draw_rect到draw_pixel有关,因为代码与起作用的代码相同,唯一改变的只是混合中的一个额外子例程/分支。
我觉得在做嵌套分支的时候有一些额外的东西需要考虑,但是我不确定是什么,或者我在这里犯了一个不同的错误。
还请注意,我使用立即值只是为了测试,我将使用变量,一旦我得到它的工作。
编辑:
解决方案是在分支到draw_pixel之前保存pr:

sts pr, r9

然后在从draw_rect返回之前恢复pr:

lds r9, pr
eit6fx6z

eit6fx6z1#

根据the manualbsr指令执行以下操作:
延迟分支,PC +4 → PR,disp × 2 + PC +4 → PC
换句话说,它首先将返回地址保存在过程寄存器(PR)中,然后将程序计数器(PC)设置为过程的地址。
等效地,rts指令执行以下操作:
延迟分支,PR → PC
也就是说,它恢复先前由bsr保存的程序计数器值。
问题是这样的:第一次使用bsr指令(bsr draw_rect)时,处理器将下一条指令的地址保存在PR中,因此它知道如何从过程返回。然后再次使用bsrbsr draw_pixel),它将再次执行此操作。因此,实际上丢失了PR的原始值。
draw_pixel返回时,它将返回到bsr draw_pixel之后的nop,正如预期的那样,但是,当draw_rect返回时,它也将返回到相同的位置,因为PR指向那里。
要解决这个问题,需要将PR保存到其他地方(另一个寄存器或堆栈),然后在返回之前恢复它。

相关问题