|
楼主 |
发表于 2020-11-10 13:32:49
|
显示全部楼层
本帖最后由 szhm 于 2020-11-12 09:02 编辑
7.点亮TFT
参考本站链接http://www.openloongson.org/foru ... =116&extra=page%3D1
本人早期的拙作<龙芯1C智龙主板如何驱动LCD>,本章节移植该文
仍是ILI9341芯片的TFT液晶屏,与LS1C101实验板接线可参考上文
1)源码
// tft_start.S
.set noreorder
nop
/* 0xa000_1000+1024=0xA0001400 作为栈空间开始地址,使用了片上内存(0xa000_1000~0xa000_1fff 数据RAM,不可取指) */
la $sp, 0xA0001400
/* 跳转到C程序main函数 */
jal main
nop
// tft1c101.h
// size:240*320,格式:RGB565(16位,2字节),转换图片工具见https://sourceforge.net/projects ... es/version%200.6.2/
static const unsigned char imgBuffer[153600]={ // 240*320*2=153600=150K
24,195,24,196,24,196,24,195,24,195,
24,195,24,163,16,163,16,163,24,162,
33,3,41,68,57,165,74,6,98,168,
...略
222,219,222,219,222,219,222,219,214,187,
214,187,214,154,214,187,214,187,206,154,
206,154,214,154,206,154,214,154,214,187
};
// tft1c101.c
// GPIO模拟SPI(3线)
#include "tft1c101.h"
#define watchdog 0xbfeb0030 //看门狗
//引脚GPIO位访问端口地址
#define SPI_RST 0xbfeb00A3 //gpio35
#define SPI_SDA 0xbfeb00A4 //gpio36
#define SPI_SCL 0xbfeb00A5 //gpio37
#define SPI_CS 0xbfeb00A6 //gpio38
void s_send(unsigned char X)
{
int j=8;
do
{
if(X&0x80) // 0x80= 10000000
*(volatile unsigned char*)(SPI_SDA)=3 ; // 输出 1
else
*(volatile unsigned char*)(SPI_SDA)=2 ; // 输出 0
*(volatile unsigned char*)(SPI_SCL)=2 ; // 0
*(volatile unsigned char*)(SPI_SCL)=3 ; // 1
--j;
X<<=1;
}while(j);
}
void s_com(unsigned char X) //写命令
{
*(volatile unsigned char*)(SPI_CS)=2 ; // 0
*(volatile unsigned char*)(SPI_SDA)=2 ; // 0 : 3线,先发一位: 命令 -- 0
*(volatile unsigned char*)(SPI_SCL)=2 ; // 0
*(volatile unsigned char*)(SPI_SCL)=3 ; // 1
s_send(X);
*(volatile unsigned char*)(SPI_CS)=3 ; // 1
}
void s_data(unsigned char X) //写数据
{
*(volatile unsigned char*)(SPI_CS)=2 ; // 0
*(volatile unsigned char*)(SPI_SDA)=3 ; // 1 : 3线,先发一位: 数据 -- 1
*(volatile unsigned char*)(SPI_SCL)=2 ; // 0
*(volatile unsigned char*)(SPI_SCL)=3 ; // 1
s_send(X);
*(volatile unsigned char*)(SPI_CS)=3 ; // 1
}
void coordinate(unsigned int col,unsigned int page)
{
s_com(0x2a); //Column Address Set
s_data(0x00);
s_data(col);
s_data(0x00);
s_data(0xef);
s_com(0x2b); //Row Address Set
s_data((page&0xff00)>>8);
s_data(page&0x00ff);
s_data(0x01);
s_data(0x3f);
s_com(0x2c); //Memory Write
}
void main (void)
{
*(volatile unsigned int*)(watchdog)=0xFBFF0400 ; //设置看门狗复位等待时间长为0x400秒
// LCD Reset
*(volatile unsigned char*)(SPI_RST)=2 ; // 0
*(volatile unsigned char*)(SPI_RST)=2 ; // 0
int i;
// LS1C101主频只8MHz,以下的延时功能可能不需要
for (i=9;i>0;i--);//延时
*(volatile unsigned char*)(SPI_RST)=3 ; // 1
*(volatile unsigned char*)(SPI_RST)=3 ; // 1
for (i=9;i>0;i--);//延时
//--v-- ILI9341初始化
s_com(0xCF);
s_data(0x00);
s_data(0x81);
s_data(0x30);
s_com(0xED);
s_data(0x64);
s_data(0x03);
s_data(0x12);
s_data(0x81);
s_com(0xE8);
s_data(0x85);
s_data(0x10);
s_data(0x78);
s_com(0xCB);
s_data(0x39);
s_data(0x2C);
s_data(0x00);
s_data(0x34);
s_data(0x02);
s_com(0xF7);
s_data(0x20);
s_com(0xEA);
s_data(0x00);
s_data(0x00);
s_com(0xB1);
s_data(0x00);
s_data(0x13);
s_com(0xB6); // Display Function Control
s_data(0x0A);
s_data(0xA2);
s_com(0xC0); //Power control
s_data(0x21); //VRH[5:0]
s_com(0xC1); //Power control
s_data(0x11); //SAP[2:0];BT[3:0]
s_com(0xC5); //VCM control
s_data(0x3F);
s_data(0x3C);
s_com(0xC7); //VCM control2
s_data(0xa4);
s_com(0x36); // Memory Access Control
s_data(0x08);
s_com(0x3A); // Pixel Format Set
s_data(0x55);
s_com(0xF2); // 3Gamma Function Disable
s_data(0x00);
s_com(0x26); //Gamma curve selected
s_data(0x01);
s_com(0xE0); //Set Gamma
s_data(0x0F);
s_data(0x26);
s_data(0x24);
s_data(0x0B);
s_data(0x0E);
s_data(0x09);
s_data(0x54);
s_data(0xA8);
s_data(0x46);
s_data(0x0C);
s_data(0x17);
s_data(0x09);
s_data(0x0F);
s_data(0x07);
s_data(0x00);
s_com(0xE1); //Set Gamma
s_data(0x00);
s_data(0x19);
s_data(0x1B);
s_data(0x04);
s_data(0x10);
s_data(0x07);
s_data(0x2A);
s_data(0x47);
s_data(0x39);
s_data(0x03);
s_data(0x06);
s_data(0x06);
s_data(0x30);
s_data(0x38);
s_data(0x0F);
s_com(0x11); //Exit Sleep
for (i=9;i>0;i--);//延时
s_com(0x29); //Display on
s_com(0x22);
s_data(0x00);
for (i=9;i>0;i--);//延时
//--^-- ILI9341
coordinate(0,0); //窗口坐标
// 显示完图像约 4分钟
for (i=0;i<240*320*2-1;i++)
s_data(imgBuffer);
}
以上源文件放在/home/linlin/loongson/myls1c/下
2)编译
linlin@debian:~/loongson/myls1c$ /home/linlin/loongson/opt/gcc-4.4.7-gnu/bin/mipsel-linux-gcc -O2 -fno-builtin -mips32 -fno-pic -mno-abicalls -g -I include -I . -c tft1c101.c -nostdinc -nostdlib
linlin@debian:~/loongson/myls1c$ /home/linlin/loongson/opt/gcc-4.4.7-gnu/bin/mipsel-linux-as -o tft_start.o tft_start.S
linlin@debian:~/loongson/myls1c$
3)链接
指定链接开始地址0xbfc00000
linlin@debian:~/loongson/myls1c$ /home/linlin/loongson/opt/gcc-4.4.7-gnu/bin/mipsel-linux-ld -g -T bin.lds -o tft1c101.elf tft_start.o tft1c101.o -Ttext 0xbfc00000
/home/linlin/loongson/opt/gcc-4.4.7-gnu/bin/mipsel-linux-ld: warning: cannot find entry symbol _start; defaulting to 00000000bfc00000
linlin@debian:~/loongson/myls1c$
注意tft_start.o在tft1c101.o之前
4)转换为二进制格式
linlin@debian:~/loongson/myls1c$ /home/linlin/loongson/opt/gcc-4.4.7-gnu/bin/mipsel-linux-objcopy -O binary tft1c101.elf tft1c101.bin
5)烧写
root@debian:/home/linlin/loongson/myls1c# /usr/sbin/flashrom -p ch341a_spi -c W25Q64.V -w tft1c101.bin
...
Error: Image size (155664 B) doesn't match the flash chip's size (8388608 B)!
root@debian:/home/linlin/loongson/myls1c#
按烧写失败提示计算填充大小
8388608-155664=8232944
用dd命令填满到8M
root@debian:/home/linlin/loongson/myls1c# dd if=/dev/zero bs=1 count=8232944 >> tft1c101.bin
记录了8232944+0 的读入
记录了8232944+0 的写出
8232944 bytes (8.2 MB, 7.9 MiB) copied, 25.2647 s, 326 kB/s
root@debian:/home/linlin/loongson/myls1c#
重新烧录已成功
root@debian:/home/linlin/loongson/myls1c# /usr/sbin/flashrom -p ch341a_spi -c W25Q64.V -w tft1c101.bin
...
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.
root@debian:/home/linlin/loongson/myls1c#
成功输出图像
6)反汇编
见反汇编结果调用函数是j开头的跳转指令,j系列指令使用绝对地址,所以链接时必须指定地址为0xbfc00000(闪存开始运行处)
linlin@debian:~/loongson/myls1c$ /home/linlin/loongson/opt/gcc-4.4.7-gnu/bin/mipsel-linux-objdump -d tft1c101.elf |more
tft1c101.elf: file format elf32-tradlittlemips
Disassembly of section .text:
bfc00000 <_ftext>:
bfc00000: 00000000 nop
bfc00004: 3c1da000 lui sp,0xa000
bfc00008: 37bd1400 ori sp,sp,0x1400
bfc0000c: 0ff0009a jal bfc00268 <main> //跳转指令jal会自动保存返回地址到ra,这里ra值应为bfc0000c+8=bfc00014
//查找有关文档有说是该条跳转指令的地址+8,但文档常说的是PC+4,具体怎区分我不太明白?
bfc00010: 00000000 nop //延迟槽,紧跟分支跳转指令后面.跳转指令未完成,本条指令就执行了
...反汇编没见到bfc00014、bfc00018、bfc0001c,不知main返回到bfc00014会出现什么状况?
bfc00020 <s_send>: //本函数是叶子函数(没有调用其它函数),无需保存ra到栈中
bfc00020: 3c02bfeb lui v0,0xbfeb
bfc00024: 344500a5 ori a1,v0,0xa5
bfc00028: 308400ff andi a0,a0,0xff
bfc0002c: 24030008 li v1,8
bfc00030: 344200a4 ori v0,v0,0xa4
bfc00034: 24090002 li t1,2
bfc00038: 24070003 li a3,3
bfc0003c: 0bf00018 j bfc00060 <s_send+0x40> //反汇编显示绝对地址,j系列指令指定不同链接地址链接结果指令机器码是不相同的
bfc00040: 24080002 li t0,2
bfc00044: 2463ffff addiu v1,v1,-1
bfc00048: a0490000 sb t1,0(v0)
bfc0004c: 00042040 sll a0,a0,0x1
bfc00050: a0a80000 sb t0,0(a1)
bfc00054: a0a70000 sb a3,0(a1)
bfc00058: 1060000c beqz v1,bfc0008c <s_send+0x6c> //b开头的分支指令,b系列指令使用相对地址,指定不同链接地址链接结果指令机器码是相同的
bfc0005c: 308400ff andi a0,a0,0xff
bfc00060: 00043600 sll a2,a0,0x18
bfc00064: 00063603 sra a2,a2,0x18
bfc00068: 04c1fff6 bgez a2,bfc00044 <s_send+0x24> //反汇编显示绝对地址,仅方便阅读,指令机器码不含绝对地址
bfc0006c: 00000000 nop
bfc00070: 2463ffff addiu v1,v1,-1
bfc00074: a0470000 sb a3,0(v0)
bfc00078: 00042040 sll a0,a0,0x1
bfc0007c: a0a80000 sb t0,0(a1)
bfc00080: a0a70000 sb a3,0(a1)
bfc00084: 1460fff6 bnez v1,bfc00060 <s_send+0x40>
bfc00088: 308400ff andi a0,a0,0xff
bfc0008c: 03e00008 jr ra //ra为函数返回的地址
bfc00090: 00000000 nop //延迟槽,填充空操作nop指令
bfc00094 <s_com>: // C程序调用了s_send函数,汇编代码没见到跳转到<s_send>,可能编译时指定了-O2给优化了(如内联函数,好像只有-O3级别才优化内联?)
bfc00094: 3c05bfeb lui a1,0xbfeb
bfc00098: 24030002 li v1,2
bfc0009c: 34a200a5 ori v0,a1,0xa5
bfc000a0: 34a600a4 ori a2,a1,0xa4
bfc000a4: 34a500a6 ori a1,a1,0xa6
bfc000a8: a0a30000 sb v1,0(a1)
bfc000ac: a0c30000 sb v1,0(a2)
bfc000b0: a0430000 sb v1,0(v0)
bfc000b4: 24030003 li v1,3
bfc000b8: a0430000 sb v1,0(v0)
bfc000bc: 308400ff andi a0,a0,0xff
bfc000c0: 24030008 li v1,8
bfc000c4: 24090002 li t1,2
bfc000c8: 24070003 li a3,3
bfc000cc: 0bf0003d j bfc000f4 <s_com+0x60>
bfc000d0: 24080002 li t0,2
bfc000d4: 00042040 sll a0,a0,0x1
bfc000d8: 2463ffff addiu v1,v1,-1
bfc000dc: a0c90000 sb t1,0(a2)
bfc000e0: 308400ff andi a0,a0,0xff
bfc000e4: a0480000 sb t0,0(v0)
bfc000e8: a0470000 sb a3,0(v0)
bfc000ec: 1060000d beqz v1,bfc00124 <s_com+0x90>
bfc000f0: 00000000 nop
bfc000f4: 00042e00 sll a1,a0,0x18
bfc000f8: 00052e03 sra a1,a1,0x18
bfc000fc: 04a1fff5 bgez a1,bfc000d4 <s_com+0x40>
bfc00100: 00000000 nop
bfc00104: 00042040 sll a0,a0,0x1
bfc00108: 2463ffff addiu v1,v1,-1
bfc0010c: a0c70000 sb a3,0(a2)
bfc00110: 308400ff andi a0,a0,0xff
bfc00114: a0480000 sb t0,0(v0)
bfc00118: a0470000 sb a3,0(v0)
bfc0011c: 1460fff6 bnez v1,bfc000f8 <s_com+0x64>
bfc00120: 00042e00 sll a1,a0,0x18
bfc00124: 3c02bfeb lui v0,0xbfeb
bfc00128: 344200a6 ori v0,v0,0xa6
bfc0012c: 24030003 li v1,3
bfc00130: a0430000 sb v1,0(v0)
bfc00134: 03e00008 jr ra //跳转到返回地址
bfc00138: 00000000 nop
bfc0013c <s_data>:
bfc0013c: 3c03bfeb lui v1,0xbfeb
bfc00140: 346200a5 ori v0,v1,0xa5
bfc00144: 24070002 li a3,2
bfc00148: 346500a4 ori a1,v1,0xa4
bfc0014c: 24060003 li a2,3
bfc00150: 346300a6 ori v1,v1,0xa6
bfc00154: a0670000 sb a3,0(v1)
bfc00158: 308400ff andi a0,a0,0xff
bfc0015c: a0a60000 sb a2,0(a1)
bfc00160: 24030008 li v1,8
bfc00164: a0470000 sb a3,0(v0)
bfc00168: 24090002 li t1,2
bfc0016c: a0460000 sb a2,0(v0)
bfc00170: 24070003 li a3,3
bfc00174: 0bf00067 j bfc0019c <s_data+0x60>
bfc00178: 24080002 li t0,2
bfc0017c: 00042040 sll a0,a0,0x1
bfc00180: 2463ffff addiu v1,v1,-1
bfc00184: a0a90000 sb t1,0(a1)
bfc00188: 308400ff andi a0,a0,0xff
bfc0018c: a0480000 sb t0,0(v0)
bfc00190: a0470000 sb a3,0(v0)
bfc00194: 1060000d beqz v1,bfc001cc <s_data+0x90>
bfc00198: 00000000 nop
bfc0019c: 00043600 sll a2,a0,0x18
bfc001a0: 00063603 sra a2,a2,0x18
bfc001a4: 04c1fff5 bgez a2,bfc0017c <s_data+0x40>
bfc001a8: 00000000 nop
bfc001ac: 00042040 sll a0,a0,0x1
bfc001b0: 2463ffff addiu v1,v1,-1
bfc001b4: a0a70000 sb a3,0(a1)
bfc001b8: 308400ff andi a0,a0,0xff
bfc001bc: a0480000 sb t0,0(v0)
bfc001c0: a0470000 sb a3,0(v0)
bfc001c4: 1460fff6 bnez v1,bfc001a0 <s_data+0x64>
bfc001c8: 00043600 sll a2,a0,0x18
bfc001cc: 3c02bfeb lui v0,0xbfeb
bfc001d0: 344200a6 ori v0,v0,0xa6
bfc001d4: 24030003 li v1,3
bfc001d8: a0430000 sb v1,0(v0)
bfc001dc: 03e00008 jr ra
bfc001e0: 00000000 nop
//MIPS约定:a0、a1等为入参,s0、s1等为变量(函数必需先保存和返回之前恢复它们),t0、t1等为临时变量(函数无需保存和恢复)
bfc001e4 <coordinate>: //本函数是非叶子函数(调用了其它函数),需保存ra到栈中
bfc001e4: 27bdffe0 addiu sp,sp,-32 //入栈,栈是从高地址往低地址增长了32(MIPS C语言规范),加操作指令,负数就是减小地址
bfc001e8: afb00014 sw s0,20(sp) //保存寄存器的值到栈,<coordinate>里共只保存3个寄存器,3*4=12个字节
bfc001ec: 00808021 move s0,a0 //传入到coordinate(col,page)的入参a0先存放到变量s0(因为见注7会先用到a0),s0见注8会用到
bfc001f0: 2404002a li a0,42 //42=0x2a => a0,见注7会用到
bfc001f4: afbf001c sw ra,28(sp) //保存ra(返回地址)到栈中,相对sp偏移28(MIPS C语言规范),-32+28=-4
bfc001f8: afb10018 sw s1,24(sp)
bfc001fc: 0ff00025 jal bfc00094 <s_com> //注7:对应C代码s_com(0x2a)
bfc00200: 00a08821 move s1,a1 //入参a1 => 变量s1 ,为何不用t1 ?因为t1可能会被下面子函数用到而改变,而按规范s1会被子函数返回之前恢复
bfc00204: 0ff0004f jal bfc0013c <s_data>
bfc00208: 00002021 move a0,zero
//--v--
bfc0020c: 0ff0004f jal bfc0013c <s_data> //----->对应C代码s_data(col)
bfc00210: 320400ff andi a0,s0,0xff //---/ 注8:即s0 => a0 => col (unsigned char) ,a0传参给<s_data>
//--^-- 因延迟槽,不方便顺序阅读理解,延迟槽改为放置nop空操作调整次序就好理解多了 [ andi a0,s0,0xff ] --> [ jal bfc0013c <s_data> ] --> [ nop ]
bfc00214: 0ff0004f jal bfc0013c <s_data>
bfc00218: 00002021 move a0,zero
bfc0021c: 0ff0004f jal bfc0013c <s_data>
bfc00220: 240400ef li a0,239
bfc00224: 0ff00025 jal bfc00094 <s_com>
bfc00228: 2404002b li a0,43
bfc0022c: 3224ff00 andi a0,s1,0xff00
bfc00230: 0ff0004f jal bfc0013c <s_data>
bfc00234: 00042202 srl a0,a0,0x8
bfc00238: 0ff0004f jal bfc0013c <s_data>
bfc0023c: 322400ff andi a0,s1,0xff
bfc00240: 0ff0004f jal bfc0013c <s_data>
bfc00244: 24040001 li a0,1
bfc00248: 0ff0004f jal bfc0013c <s_data> //好像只有jal、jalr才会同时自动保存返回地址到ra
bfc0024c: 2404003f li a0,63
//--v--
bfc00250: 8fbf001c lw ra,28(sp) //因上面调用了<s_data>等,ra值被改变,所以需从栈中恢复返回地址到ra
bfc00254: 8fb10018 lw s1,24(sp) //恢复
bfc00258: 8fb00014 lw s0,20(sp)
bfc0025c: 2404002c li a0,44 //44=0x2c,<s_com>入参
bfc00260: 0bf00025 j bfc00094 <s_com> //指令j、jr应不会自动保存返回地址到ra,不会改变ra值
//--^--
//C代码<coordinate>函数里最后一行是s_com(0x2c),汇编代码<coordinate>里最后不见用jr ra 跳转到返回地址,应该是优化了
//如果不优化的话,应该是 jal <s_com> --> lw ra,28(sp) --> jr ra
//而优化结果是 lw ra,28(sp) --> j <s_com> ,由<s_com>里最后返回到ra
bfc00264: 27bd0020 addiu sp,sp,32 //出栈
bfc00268 <main>:
bfc00268: 3c06bfeb lui a2,0xbfeb
bfc0026c: 3c07fbff lui a3,0xfbff
bfc00270: 27bdffe0 addiu sp,sp,-32
bfc00274: 34c200a3 ori v0,a2,0xa3
bfc00278: 24050002 li a1,2
bfc0027c: 24030003 li v1,3
bfc00280: 34c60030 ori a2,a2,0x30
bfc00284: 34e70400 ori a3,a3,0x400
bfc00288: afbf001c sw ra,28(sp)
bfc0028c: acc70000 sw a3,0(a2)
bfc00290: afb10018 sw s1,24(sp)
bfc00294: afb00014 sw s0,20(sp)
bfc00298: 240400cf li a0,207
bfc0029c: a0450000 sb a1,0(v0)
bfc002a0: a0450000 sb a1,0(v0)
bfc002a4: a0430000 sb v1,0(v0)
bfc002a8: a0430000 sb v1,0(v0)
bfc002ac: 0ff00025 jal bfc00094 <s_com>
bfc002b0: 3c10bfc0 lui s0,0xbfc0 //立即数加载到高位,存放在闪存的图片开始位置(bfc0XXXX)
bfc002b4: 0ff0004f jal bfc0013c <s_data>
bfc002b8: 00002021 move a0,zero
bfc002bc: 0ff0004f jal bfc0013c <s_data>
bfc002c0: 24040081 li a0,129
bfc002c4: 0ff0004f jal bfc0013c <s_data>
bfc002c8: 24040030 li a0,48
bfc002cc: 0ff00025 jal bfc00094 <s_com>
bfc002d0: 240400ed li a0,237 //237=0xED,C代码的s_com(0xED)语句,函数调用的参数
...略
bfc0037c: 0ff0004f jal bfc0013c <s_data>
bfc00380: 24040013 li a0,19 //这里的0xbfc00380本应是中断入口,本程序没用中断,没问题
bfc00384: 0ff00025 jal bfc00094 <s_com>
bfc00388: 240400b6 li a0,182
...
bfc0051c: 0ff0004f jal bfc0013c <s_data>
bfc00520: 2404000f li a0,15
bfc00524: 0ff00025 jal bfc00094 <s_com> // C代码for (i=9;i>0;i--)语句给优化没了
bfc00528: 24040011 li a0,17
bfc0052c: 0ff00025 jal bfc00094 <s_com>
bfc00530: 24040029 li a0,41
bfc00534: 0ff00025 jal bfc00094 <s_com>
bfc00538: 24040022 li a0,34
bfc0053c: 0ff0004f jal bfc0013c <s_data>
bfc00540: 00002021 move a0,zero //延迟槽,应该对应C代码s_data(0x00)
bfc00544: 00002021 move a0,zero //两个入参a0、a1,对应C代码coordinate(0,0)语句
bfc00548: 00002821 move a1,zero
bfc0054c: 0ff00079 jal bfc001e4 <coordinate> //自动填入返回地址到ra=bfc0054c+8=bfc00554
bfc00550: 3c11bfc2 lui s1,0xbfc2 //延迟槽,立即数加载到高位,图片存放在闪存的位置(bfc0XXXX~bfc2XXXX),C代码的i变量给优化为图片地址
bfc00554: 26100580 addiu s0,s0,1408 // 1408=0x0580,s0=0xbfc00580
bfc00558: 26315d7f addiu s1,s1,23935 //23935=0x5D7F,s1=0xBFC25D7F=0xBFC25D80-1,图片的最后地址
//--v--对应C代码for (i=0;i<240*320*2-1;i++)
bfc0055c: 92040000 lbu a0,0(s0)
bfc00560: 0ff0004f jal bfc0013c <s_data>
bfc00564: 26100001 addiu s0,s0,1 //增加1
bfc00568: 1611fffc bne s0,s1,bfc0055c <main+0x2f4> //比较0xBFC25D80-1的值,变量i给优化
//--^--
bfc0056c: 8fbf001c lw ra,28(sp) //从栈中恢复返回地址到ra
bfc00570: 8fb10018 lw s1,24(sp)
bfc00574: 8fb00014 lw s0,20(sp)
bfc00578: 03e00008 jr ra //跳转到返回地址
bfc0057c: 27bd0020 addiu sp,sp,32
bfc00580 <imgBuffer>: //图片数据 0xbfc00580+153600=0xBFC25D80
bfc00580: c418c318 c318c418 c318c318 a310a318 ................
bfc00590: a218a310 44290321 064aa539 e86aa862 ....!.)D9.J.b.j.
bfc005a0: 0873c86a 09730973 49732973 6a736973 j.s.s.s.s)sIsisj
...略
bfc25d40: 38c659ce 79ce38c6 bad6bad6 fbdedad6 .Y.8.8.y........
bfc25d50: fbdebad6 9ad6bad6 fcdedbd6 bbd6dbd6 ................
bfc25d60: dbdebbd6 dbdedbde bbd6dbde 9ad6bbd6 ................
bfc25d70: bbd6bbd6 9ace9ace 9ace9ad6 bbd69ad6 ................
bfc25d80: a0000000 00000000 00000000 00000000 ................
...
linlin@debian:~/loongson/myls1c$
7)小结
通过反汇编,可见C编译器通过栈保证了MIPS规范要求的ra、s0~s7进入子函数保存和恢复.如果手工写汇编不按规范,可能导致不可预料的后果
|
|