经历了N天几近抓狂的调试,终于做出了结果。在这里非常非常之感谢帮助我的Tom同学,没有他的耐心帮助,这个程序基本上要流产了。梳理一下,记录下来,让自己理解的更好些。
一 DCT变换算法简介
DCT算法是应用在图像处理中的一个变化算法,具体的应用我不知道。可能是为了存储的要求吧。算法的具体流程是这样的:对于给定的N*N规模的矩阵A,应用下列公式求系数矩阵B
//求系数矩阵
for(y=0;y coff[0][y]=1/sqrt(N);
for(x=1;x {
for(y=0;y coff[x][y]=(sqrt(2.0)/sqrt(N))*cos((2*y+1)*x*PI/(2*N));
}
记C为系数矩阵的转置矩阵,D为结果矩阵
则D=B*A*C(A为输入矩阵,B为系数矩阵,C为B的转置矩阵,D为输出结果)
二 汇编实现的矩阵转置
;矩阵的转置
LDR R0,=xishu_array ;系数矩阵的首地址
LDR R1,=xishu_array_t ;转置矩阵的首地址
MOV R3,#0 ;x
loopx
MOV R4,#0 ;y
loopy
MOV R5,R4,LSL #6 ;计算xishu_array[y][x]
ADD R6,R5,R3
LDRSB R7,[R0,R6] ;将计算结果保存在R7中
MOV R8,R3,LSL #6 ;计算xishu_array_t[x][y]
ADD R9,R8,R4
STRB R7,[R1,R9] ;将R7的内容传回内存实现转置
ADD R4,R4,#1 ;y的计数器
CMP R4,#64
BNE loopy
ADD R3,R3,#1 ;x的计数器
CMP R3,#64
BNE loopx
三 汇编实现的矩阵相乘
;系数矩阵与源矩阵相乘
LDR R0,=xishu_array ;系数矩阵的首地址
LDR R1,=origin_array ;输入原始矩阵的首地址
LDR R2,=middle_array ;相乘结果的首地址
MOV R3,#0 ;i
row1
MOV R4,#0 ;l
colum1
MOV R11,#0 ;保存结果矩阵的每个元素值
MOV R5,#0 ;j
mul1
MOV R6,R3,LSL #6 ;保存第一个数组的元素
ADD R6,R6,R5
LDRSB R7,[R0,R6]
MOV R8,R5,LSL #6 ;保存第二个数组的元素
ADD R8,R8,R4
LDRB R9,[R1,R8]
MUL R10,R7,R9 ;每个元素相乘,保存到R9中
ADD R11,R11,R10
ADD R5,R5,#1
CMP R5,#64
BNE mul1
STR R11,[R2],#4 ;保存求得第一个元素值
ADD R4,R4,#1
CMP R4,#64
BNE colum1
ADD R3,R3,#1
CMP R3,#64
BNE row1
四 将第三步中求得的结果再和系数的转置矩阵相乘
由于相乘的算法和上一步中相同,在此就不再列出。
到此为止,幸运的话,是可以有结果的。列举实现过程中遇到的一些问题。
一 浮点数的存储
由于现在在ARM中,不会处理和存储浮点数。系数矩阵的运算是放在C语言中,以Load Memory的方式加载到汇编程序中的。由于精度的考虑,要把系数矩阵中的数据乘以一个相对大些的数。我这里用的是128。然后在汇编中,不要忘记对最后的结果做相应的处理。由于我乘以的是128,所以对最后的数据要算数右移14位(因为还有一次与系数的转置矩阵相乘,扩大了128*128)。
二 加载和存储数据
根据定义的矩阵大小,采用相应的加载和存储指令。
定义矩阵中的一个数据元素占一个字节时,指令是LDRB,STRB。地址的变换是加减一
定义矩阵中的一个数据元素占一个字,即四个字节时,指令是LDR,STR。地址的变化是加减四。
当处理的数据是有符号的。指令后要有S。即LDRSB或LDRS。
这几个地方非常容易错。要非常小心。
就这样吧,终于完成了。虽然是在同学的帮助下,还是很高兴的。在此还是要感谢Tom同学!