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