TI官网文档:
http://www.ti.com/product/tms320c6745/technicaldocuments
里面资料非常详细,可以对着里面一个个看,用的比较多的两个文档:
TMS320C674x指令格式:TMS320C674x DSP CPU and Instruction Set User's Guide .pdf
芯片相关的接口地址可以到这里找: TMS320C6745, TMS320C6747 Fixed- and Floating-Point Digital Signal Processor (Rev. F)
下面是网上收集的C6000的反汇编实例,C674x与之大致类似。
1、C6000汇编实例详解1
void tsk_test5(void)
{
unsigned int i,j;
unsigned char a,b;
unsigned long l;
i=0xAA55;
j=0x55AA;
a=0x88;
b=0x99;
l=0x11223344;
while(1){
iprintf("haha5\n");
TSK_time();
iprintf("test5 time = %d,count = %d",TSK_time(),count++);
funtionarg(i,b,l);
}
}
void tsk_test5(void)
{
8000AEB0 STW.D2T2 B3,*SP--[10] //SP=SP-4*10;*(SP)=B3;SP向下增长,
8000AEB4 NOP 2
i=0xAA55;
8000AEB8 MVK.S1 0xffffaa55,A3 //A3=0xffffaa55
8000AEBC .fphead p, l, W, BU, nobr, nosat, 0000010 //不知道,好像是个系统调用
8000AEC0 MVKH.S1 0x0000,A3 //把0x0000赋值给A3的高16,A3=0x0000AA55
8000AEC4 STW.D2T1 A3,*B15[5] //i是局部变量,压入栈中,*(B15+4*5)=A3(B15==SP).
8000AEC6 NOP 2
j=0x55AA;
8000AEC8 MVK.S2 0x55aa,B4 //B5=0x55aa
8000AECC STW.D2T2 B4,*B15[6] //*(B15+4*6)=B4(B15==SP).
8000AECE NOP 2
a=0x88;
8000AED0 MVK.S1 0x0088,A3
8000AED4 STB.D2T1 A3,*+SP[28] //*(SP+28)=A3
8000AED8 NOP 2
b=0x99;
8000AEDA MVK.S2 153,B4
8000AEDC .fphead n, l, W, BU, nobr, nosat, 1001010
8000AEE0 STB.D2T2 B4,*+SP[29] //*(SP+29)=B4
8000AEE4 NOP 2
l=0x11223344;
8000AEE8 MVK.S2 0x3344,B4
8000AEEC MVKH.S2 0x11220000,B4
8000AEF0 || MVK.L2 0,B5
8000AEF4 STDW.D2T2 B5:B4,*+SP[4] //长整型,8字节,*(SP+4×4)=B5:B4
8000AEF8 NOP
iprintf("haha5\n");
8000AEFC C$DW$L$_tsk_test5$2$B, C$L4:
8000AEFC MVK.S2 0x187c,B4
8000AF00 MVKH.S2 0x80010000,B4
8000AF04 CALLP.S2 iprintf (PC-9212 = 0x80008b04),B3
8000AF08 || STW.D2T2 B4,*+SP[1] //这块要注意,指令前有“||”表示和上面一条指令同时执行,可变参数函数,参数压栈。
TSK_time();
8000AF0C C$RL2:
8000AF0C LDW.D2T2 *+B14[162],B4 //B14: 存放全局变量的基地址,也就是BSS段的基地址。*+B14[162]这个应该是TSK_time()的地址。
8000AF10 NOP 4
iprintf("test5 time = %d,count = %d",TSK_time(),count++);
8000AF14 LDHU.D2T2 *+B14[437],B4 //B4=*(B14+4×437)将全局变量count的值放入B4中
8000AF18 LDW.D2T2 *+B14[162],B5 //将TSK_time()的返回值放入B5中
8000AF1C MVK.S1 0x1883,A3
8000AF20 MVKH.S1 0x80010000,A3
8000AF24 STW.D2T1 A3,*B15[1] //第一个参数(也就是字符串地址)压栈。
8000AF26 STW.D2T2 B4,*B15[3] //第三个压栈
8000AF28 ADD.L2 B4,1,B4 //count++
8000AF2A STW.D2T2 B5,*B15[2] //第二个压栈。
8000AF2C CALLP.S2 0x80008AE4 (PC-9244 = 0x80008ae4),B3
8000AF30 || STH.D2T2 B4,*+B14[437] //count=B4;
funtionarg(i,b,l);
8000AF34 C$RL3:
8000AF34 LDW.D2T1 *+SP[5],A4 //A4=*(SP+4*5)=i;第一个参数用A4传递
8000AF38 LDBU.D2T2 *+SP[29],B4 //B4=*(SP+4*29)=b;第二个参数用B4传递
8000AF3C .fphead n, l, W, BU, nobr, nosat, 0000110
8000AF40 LDDW.D2T1 *+SP[4],A7:A6 //第三个参数用A7:A6传递。long型数据。
8000AF44 || CALLP.S2 funtionarg (PC-268 = 0x8000ae34),B3
8000AF46 C$RL4:
8000AF46 BNOP.S1 C$L4 (PC-68 = 0x8000aefc),5 //while循环
}
2、C6000汇编实例详解2
//固定参数一般函数 反汇编
unsigned int funtionarg(unsigned int m,unsigned char k,unsigned long l)
{
unsigned int i,j;
unsigned char a,b;
unsigned long ll=0;
j=0x55aa;
i=m+j;
a=0x88;
b=a+0x11+k;
ll=l+1;
my_delay(100);
return i;
}
unsigned int funtionarg(unsigned int m,unsigned char k,unsigned long l)
{
8000AE34 C$DW$L$_tsk_main$2$E, funtionarg:
8000AE34 STW.D2T2 B3,*SP--[12] //压栈函数返回地址并分配48个字节
8000AE38 NOP 2
8000AE3C .fphead n, l, W, BU, br, nosat, 0000101
8000AE40 STDW.D2T1 A7:A6,*+SP[2] //压栈第三而参数
8000AE44 STB.D2T2 B4,*+SP[8] //压栈第二个参数
8000AE48 STW.D2T1 A4,*B15[1] //压栈第一个参数
8000AE4A NOP 2
unsigned int i,j;
unsigned char a,b;
unsigned long ll=0;
8000AE4C ZERO.L1 A5:A4 //A5:A4 = 0
8000AE50 STDW.D2T1 A5:A4,*+SP[5] //ll=*(SP+4*5)=A5:A4
8000AE54 NOP 2
j=0x55aa;
8000AE58 MVK.S2 0x55aa,B4 //B4=0x55aa
8000AE5C .fphead n, l, W, BU, nobr, nosat, 0000100
8000AE60 STW.D2T2 B4,*B15[7] //j=*(SP+4*7)=B4=0x55AA
8000AE62 NOP 2
i=m+j;
8000AE64 LDW.D2T2 *B15[7],B5 //B5=*(SP+4*7)=j
8000AE66 LDW.D2T2 *B15[1],B4 //B4=*(SP+4)=m
8000AE68 NOP 4
8000AE6A ADD.L2 B5,B4,B4 //B4=B4+B5
8000AE6C STW.D2T2 B4,*B15[6] //i=*(SP+4*6)=B4
8000AE6E NOP 2
a=0x88;
8000AE70 MVK.S2 0x0088,B4
8000AE74 STB.D2T2 B4,*+B15[32]
8000AE78 NOP 2
8000AE7C .fphead n, l, W, BU, nobr, nosat, 0001111
b=a+0x11+k;
8000AE80 LDBU.D2T2 *+B15[32],B4
8000AE84 LDBU.D2T2 *+SP[8],B5
8000AE88 NOP 4
8000AE8A ADD.L2 B5,B4,B4
8000AE8C ADDK.S2 17,B4
8000AE90 STB.D2T2 B4,*+B15[33]
8000AE94 NOP 2
ll=l+1;
8000AE98 LDDW.D2T2 *+SP[2],B5:B4
8000AE9C .fphead n, l, W, BU, nobr, nosat, 0000100
8000AEA0 MVK.L2 1,B6
8000AEA2 NOP 3
8000AEA4 ADDU.L2 B6,B5:B4,B5:B4
8000AEA8 STDW.D2T2 B5:B4,*+SP[5]
8000AEAC NOP 2
my_delay(100);
8000AEAE CALLP.S2 my_delay (PC-220 = 0x8000adc4),B3
8000AEB0 || MVK.S1 100,A4 //参数为100,用A4传参
return i;
8000AEB2 C$RL2:
8000AEB2 LDW.D2T1 *B15[6],A4 //A4=*(SP+4*6)=i;A4是返回值
8000AEB4 LDW.D2T2 *++SP[12],B3 //B3 程序返回地址
8000AEB8 BNOP.S2 B3,5
8000AEBC .fphead p, l, W, BU, br, nosat, 0011001
}
3、C6000汇编实例详解3
//可变参数函数反汇编
int iprintf(const char *pbFmt,...)
{
va_list pArg;
char abString[256];
va_start(pArg,pbFmt);
vsprintf(abString,pbFmt,pArg);
UARTSendData(abString);
va_end(pArg);
return 0;
}
int iprintf(const char *pbFmt,...)
{
80008B04 OR.L1X 0,SP,A15 //A15=SP
80008B08 || STW.D2T1 A15,*B15--[2] //SP=SP-4*2,开辟空间8字节
80008B0A NOP 2
80008B0C ADDK.S2 -264,SP //SP=SP-264,开辟空间264字节
80008B10 STW.D2T2 B3,*+B15[67] //函数返回地址压栈。
80008B14 NOP 2
va_list pArg;
char abString[256];
va_start(pArg,pbFmt);
80008B18 ADD.L1 8,A15,A3 //通过A15(原来的SP值)取得第一个参数的值。
80008B1C .fphead n, l, W, BU, nobr, nosat, 0000100
80008B20 STW.D2T1 A3,*B15[1] //通过A15(原来的SP值)取得第一个参数的值。
80008B22 NOP 2
vsprintf(abString,pbFmt,pArg);
80008B24 CALLP.S2 vsprintf (PC+16320 = 0x8000cae0),B3
80008B28 || LDW.D1T2 *+A15[1],B4
80008B2C || ADD.L1X 8,SP,A4 //同过B4 A4和A6传递参数
80008B30 || MV.S1 A3,A6 //以上4条语句同时执行
UARTSendData(abString);
80008B32 C$RL0:
80008B32 CALLP.S2 UARTSendData (PC+48 = 0x80008b50),B3
80008B34 || ADD.L1X 8,SP,A4 //通过A4传递参数
va_end(pArg);
return 0;
80008B38 C$RL1:
80008B38 MVK.L1 0,A4
80008B3C .fphead n, l, W, BU, br, nosat, 0010001
80008B40 LDW.D2T2 *+B15[67],B3 //取得返回地址
80008B44 OR.L2X 0,A15,SP
80008B48 || LDW.D1T1 *+A15[0],A15
80008B4C BNOP.S2 B3,5 //通过B3返回