Raspberry Pi Screen02

实验目标

用产生伪随机数的方式画出线条和其它的一些东西。


代码分析

我们希望通过在任意两点确定一条直线的方式画线,所以我们需要SetPixel函数来确定两个点。

drawing.s

.section .data
.align 1
foreColour:
.hword 0xFFFF

.align 2
graphicsAddress:
.int 0

.section .text
.globl SetForeColour
SetForeColour:
cmp r0,#0x10000
movhs pc,lr
ldr r1,=foreColour
strh r0,[r1]
mov pc,lr

.globl SetGraphicsAddress
SetGraphicsAddress:
ldr r1,=graphicsAddress
str r0,[r1]
mov pc,lr

这些函数写在drawing.s文件中方便调用,可以用在不同的memory中。

SetPixel

  1. 加载地址 graphicsAddress
  2. 确定x和y数值的合法性
  3. 计算每个像素点的地址(frameBufferAddress + (x + y * width) * pixel size)
  4. 加载颜色信息foreColor
  5. 将颜色foreColor保存到相应地址中
.globl DrawPixel
DrawPixel:
px .req r0
py .req r1
addr .req r2
ldr addr,=graphicsAddress
ldr addr,[addr]

px(r0寄存器),py(r1寄存器),addr(r2寄存器)

height .req r3
ldr height,[addr,#4]
sub height,#1
cmp py,height
movhi pc,lr
.unreq height

width .req r3
ldr width,[addr,#0]
sub width,#1
cmp px,width
movhi pc,lr

根据上个实验中定义的数据格式,Physical height和Physical width分别在偏移地址4和0上,然后再确认我们定义的px和py是否符合height和width的范围。

ldr addr,[addr,#32]
add width,#1
mla px,py,width,px
.unreq width
.unreq py
add addr, px,lsl #1
.unreq px

[addr,#32] 是数据格式中的指向特定图像的指针; mla 指令是带累加的相乘,完成的是px = py*width+px,地址还需要乘上每个像素的大小,add addr, px,lsl #1 得到的地址就是特定像素的地址了。

fore .req r3
ldr fore,=foreColour
ldrh fore,[fore]

strh fore,[addr]
.unreq fore
.unreq addr
mov pc,lr

所以从foreColor中取出特定的颜色信息再传入到上面计算好的addr地址中,就是这个特定地址的像素信息了。

线

在汇编语言中使用除法是一件比较麻烦的事情,所以计算倾角来画线是不明智的选择,在这里介绍一种布雷森汉算法(Bresenham's line algorithm),可以画直线,并且只用到了加减与移位运算。

实际上Bresenham's Algorithm是将我们现实中连续的直线离散化,因为我们实际上不可能有足够高的精度去描述一条准确的直线,毕竟计算机本身就是离散的,图形描述的离散也是情理之中。

算法的流程图如下,有关各式的推导可以在维基百科中得到。

随机数生成

一种迭代的随机数生成算法,xn就是种子。

  1. a是偶数
  2. b = a + 1 mod 4
  3. c是奇数

实际上我们知道最简单的随机数数学公式可以用

这样一个最简单的公式表达,也的确能生成的一个数字序列,但是随机性也是非常低的,我们用二次函数来代替一次函数在某些程度上可以增加他的随机性,但是这些依然是伪随机生成。

将算法与随机数生成程序都用汇编实现。然后接下来就是按照实验步骤一步一步实现一个随机数画图程序了。

实验过程

  1. 使用SetGraphicsAddress, 并用r0传入帧缓冲区的地址。
  2. 初始化4个寄存器,一个保存随机数,一个保存颜色信息,还有一对是x,y坐标信息。
  3. 在现有的坐标上,利用随机数生成下一个x轴坐标
  4. 利用x坐标生成下一个y坐标
  5. 迭代更新,用随机数代表y
  6. 使用SetForeColour函数和颜色寄存器去设置颜色。
  7. 由于我们的像素都是小于1024的,然而寄存器却能保存32位,远大于1024,所以要将寄存器值逻辑右移22位,以满足要求。
  8. 检查y寄存器是否小于等于767,否则回到步骤3.
  9. 利用布雷森汉算法在两点之间画线。
  10. 用生成的x和y坐标更新现有的坐标。
  11. 回到步骤三,画下一条线。

结果展示