TI官网文档:
http://www.ti.com/product/tms320c6745/technicaldocuments
里面资料非常详细,可以对着里面一个个看,用的比较多的两个文档:
TMS320C674x指令格式:
芯片相关的接口地址可以到这里找:
下面是转载C6000的反汇编实例,C674x与之大致类似。原创应该来自于http://blog.chinaunix.net/uid-2282111-id-2113264.html:
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返回 }