還真是ADS1.2的BUG![build 805]的BUG,還在使ADS1.2的兄弟注意升級
(2011/10/16 9:09:00)
編譯環(huán)境:ADS1.2
調(diào)試環(huán)境:AXDArmulate
發(fā)現(xiàn)問題:同一條語句,不同的編譯選項編譯,執(zhí)行結(jié)果不同。
語句:
if((d&0x0fffffff)==0x05555550)
選用-O1選項編譯時生成代碼:(armcc–O1–g+-S–fs–cpuARM7TDMI–ooutO1.stest.c)
000004e1a00200MOVr0,r0,LSL#4
000008e1500221CMPr0,r1,LSR#4
00000c1a000001BNE|L1.24|
其中
r0為0xA5555550
r1為0x05555550
執(zhí)行結(jié)果為假:
;r0中為0xA5555550
MOVr0,r0,LSL#4
;r0中為0x55555500,r1中為0x05555550,r1,LSR#4為0x00555555
CMPr0,r1,LSR#4;不相等,為假
BNE|L1.24|
選用-O0選項編譯時生成代碼:(armcc–O0–g+-S–fs–cpuARM7TDMI–ooutO0.stest.c)
000000e1a01000MOVr1,r0
000004e1a00201MOVr0,r1,LSL#4
000008e59f202cLDRr2,|L1.60|
00000ce1520220CMPr2,r0,LSR#4
其中
r0為0xA5555550
執(zhí)行結(jié)果為真:
;r0中為0xA5555550
MOVr1,r0
;r0和r1中都為0xA5555550
MOVr0,r1,LSL#4
;r0中為0x55555500
LDRr2,|L1.60|
;r2中為0x05555550
CMPr2,r0,LSR#4;r0,LSR#4為0x05555550,與r2相等,為真
源程序:
inttest(unsignedintd)
{
if((d&0x0fffffff)==0x05555550)
return1;
else
return0;
}
intmain(void)
{
intd;
d=test(0xA5555550);
returnd;
}
使用-O1選項生成的匯編代碼:
(armcc–O1–g+-S–fs–cpuARM7TDMI–ooutO1.stest.c)
;generatedbyARMCCompiler,ADS1.2[Build805]
;commandline[-O1-S-g+-fs"-IC:ProgramFilesARMADSv1_2INCLUDE"]
CODE32
AREA||.text||,CODE,READONLY
testPROC
;;;1inttest(unsignedintd)
;;;2{
000000e59f1020LDRr1,|L1.40|
;;;3//unsignedintbak;
;;;4
;;;5if((d&0x0fffffff)==0x05555550)
000004e1a00200MOVr0,r0,LSL#4
000008e1500221CMPr0,r1,LSR#4
00000c1a000001BNE|L1.24|
;;;6return1;
000010e3a00001MOVr0,#1
;;;7else
;;;8return0;
;;;9}
|L1.20|
000014e1a0f00eMOVpc,lr
|L1.24|
000018e3a00000MOVr0,#0;8
00001ceafffffcB|L1.20|;8
ENDP
mainPROC
;;;11intmain(void)
;;;12{
000020e59f0004LDRr0,|L1.44|
;;;13unsignedintd;
;;;14
;;;15d=test(0xA5555550);
000024eafffffeBtest
|L1.40|
00002805555550DCD0x05555550
|L1.44|
00002ca5555550DCD0xa5555550
;;;16
;;;17returnd;
;;;18}ENDP
END
使用-O0選項生成的匯編代碼:
(armcc–O0–g+-S–fs–cpuARM7TDMI–ooutO0.stest.c)
;generatedbyARMCCompiler,ADS1.2[Build805]
;commandline[-O0-S-g+-fs"-IC:ProgramFilesARMADSv1_2INCLUDE"]
CODE32
AREA||.text||,CODE,READONLY
testPROC
;;;1inttest(unsignedintd)
;;;2{
000000e1a01000MOVr1,r0
;;;3//unsignedintbak;
;;;4
;;;5if((d&0x0fffffff)==0x05555550)
000004e1a00201MOVr0,r1,LSL#4
000008e59f202cLDRr2,|L1.60|
00000ce1520220CMPr2,r0,LSR#4
0000101a000001BNE|L1.28|
;;;6return1;
000014e3a00001MOVr0,#1
;;;7else
;;;8return0;
;;;9}
|L1.24|
000018e1a0f00eMOVpc,lr
|L1.28|
00001ce3a00000MOVr0,#0;8
000020eafffffcB|L1.24|;8
ENDP
mainPROC
;;;11intmain(void)
;;;12{
000024e52de004STRlr,[sp,#-4]!
;;;13unsignedintd;
;;;14
;;;15d=test(0xA5555550);
000028e59f0010LDRr0,|L1.64|
00002cebfffffeBLtest
000030e1a03000MOVr3,r0
;;;16
;;;17returnd;
000034e1a00003MOVr0,r3
;;;18}000038e49df004LDRpc,[sp],#4
|L1.60|
00003c05555550DCD0x05555550
|L1.64|
000040a5555550DCD0xa5555550
ENDP
END
網(wǎng)友評論:將上述程序用-O1選項編譯,運(yùn)行結(jié)果正確:
Inputanewvalue:2773833040
Yourinput:2773833040
intest():d=2773833040
Result:d=1c=2
產(chǎn)生的代碼也可以理解:
其中if((d&0x0fffffff)==0x05555550)產(chǎn)生的代碼為:
[0xe59f102c]ldrr1,0x00008124;=#0x05555550
[0xe1a00204]movr0,r4,lsl#4
[0xe1510220]cmpr1,r0,lsr#4/****注意****/
與13樓中使用-O0產(chǎn)生的代碼相似,即把0xA5555550左移4位,再右移4位與0x05555550比較。
而13樓中使用-O1選項產(chǎn)生的代碼為
[0xe59f1050]ldrr1,0x00008100;=#0x05555550
[0xe1a00200]movr0,r0,lsl#4
[0xe1500221]cmpr0,r1,lsr#4/****注意****/
/*改為cmpr1,r0,lsr#4就對了*/
是將0xA5555550左移4位,與0x05555550右移4位比較,好象有問題。
做了一些測試,對于test函數(shù)稍作一點改動,其產(chǎn)生的代碼就沒有問題了。將代碼改為:
unsignedintbak;
if((bak=d&0x0fffffff)==0x05555550)
用什么選項優(yōu)化都不出問題了。
把代碼改為:
unsignedinttest(unsignedintd)
{
if((d&0x0fffffff)==0x05555550)
{
printf("return1,intest():d=%u
",d);
return1;
}
else
{
printf("return0,intest():d=%u
",d);
return0;
}
}
也沒問題,用-O1選項生成代碼為:
[0xe59f2030]ldrr2,0x00008118;=#0x05555550
[0xe1a01200]movr1,r0,lsl#4
[0xe1520221]cmpr2,r1,lsr#4
把代碼改為
unsignedinttest(unsignedintd)
{
unsignedintret;
if((d&0x0fffffff)==0x05555550)
ret=1;
else
ret=0;
printf("ret=%u",ret);
returnret;
}
也沒問題,用-O1選項生成代碼為:
[0xe59f1028]ldrr1,0x00008110;=#0x05555550
[0xe1a00200]movr0,r0,lsl#4
[0xe1510220]cmpr1,r0,lsr#4
與代碼
[0xe59f1050]ldrr1,0x00008100;=#0x05555550
[0xe1a00200]movr0,r0,lsl#4
[0xe1500221]cmpr0,r1,lsr#4/****注意****/
比較,僅有cmp一行不同(12樓test函數(shù)-O1選項生成的代碼)
將代碼改為
unsignedinttest(unsignedintd)
{
unsignedintret;
if((d&0x0fffffff)==0x05555550)
ret=1;
else
ret=0;
returnret;
}
運(yùn)行正確,-O1選項產(chǎn)生的代碼為
[0xe59f105c]ldrr1,0x00008140;=#0x05555550
[0xe1a00200]movr0,r0,lsl#4
[0xe1510220]cmpr1,r0,lsr#4
/***************************************************/
補(bǔ)充說明:
上述測試在build848版本上測試的。
剛才在build805版本上又測了一下,輸出為
Inputanewvalue:2773833040
Yourinput:2773833040
intest():d=2773833040
Result:d=0c=0
Inputanewvalue:3
的確是build805版編譯器的bug了。
網(wǎng)友評論:用ADS1.2也試了一下,但沒看到匯編代碼,所有不好說。
不過個人相信ADS1.2不會如此的笨吧!
用RVCT3.0X怎樣編譯都沒問題!
;generatedbyARM/ThumbC/C++Compilerwith,RVCT3.0[Build951]foruVision
;commandlineArmCC[--thumb--debug-c--asm--interleave-opro_entry.o--device=DARMP--apcs=interwork-O3-IC:KeilARMINCPhilipspro_entry.c]
THUMB
AREA||.text.7||,CODE,READONLY,ALIGN=2
testPROC
;;;38{
;;;39if((d&0x0fffffff)==0x05555550)
0000004907LDRr1,|L1.32|
0000020100LSLSr0,r0,#4
0000044288CMPr0,r1
000006d101BNE|L1.12|
;;;40return1;
0000082001MOVSr0,#1
;;;41else
;;;42return0;
;;;43}
00000a4770BXlr
|L1.12|
00000c2000MOVSr0,#0;42
00000e4770BXlr
ENDP
mainPROC
;;;8intmain(void)
;;;9{
000010b500PUSH{lr}
;;;10
;;;13staticlongtmp;
;;;14
;;;15intx,y;
;;;27x=test(0xA5555550);
0000124804LDRr0,|L1.36|
000014f7fffffeBLtest
;;;28
;;;29y=2*x;
;;;30tmp=y;
0000184903LDRr1,|L1.40|
00001a0040LSLSr0,r0,#1;29
00001c6008STRr0,[r1,#0];tmp@main_0
;;;31
;;;32while(1);
|L1.30|
00001ee7feB|L1.30|
|L1.32|
00002055555500DCD0x55555500
|L1.36|
000024a5555550DCD0xa5555550
|L1.40|
00002800000000DCD||.data||
;;;33
;;;34
;;;35}
ENDP
AREA||.data||,DATA,ALIGN=2
||tmp@main_0||
DCD0x00000000
網(wǎng)友評論:非常感謝27樓的回復(fù)!找3.0找了半天也沒找到。
上面生成的是THUMB代碼,能再試一下生成ARM代碼是什么樣子嗎?
|L1.32|
00002055555500DCD0x55555500
可見優(yōu)化時把0x05555550優(yōu)化時改為0x55555500,直接忽略高4位。
在比較時,
0000004907LDRr1,|L1.32|
0000020100LSLSr0,r0,#4
0000044288CMPr0,r1
000006d101BNE|L1.12|
直接把d(0xA5555550)左移4位(也直接忽略高4位)相比較就可以了。
網(wǎng)友評論:到ARM公司網(wǎng)站上下一個848版的補(bǔ)丁就好了!是805版編譯器的一個BUG!
做了以下兩程序的測試:
程序1
文件名test1.c
inttest(unsignedintd)
{
if((d&0x0fffffff)==0x05555550)
return1;
else
return0;
}
intmain(void)
{
volatileintd;
d=test(0xA5555550);
returnd;
}
在805版編譯器下編譯,生成test1b805.s:
(armcc-O1-S-fs-cpuARM7TDMI-otest1b805.stest1.c)
;generatedbyARMCCompiler,ADS1.2[Build805]
;commandline[-O1-S-fs"-IC:ProgramFilesARMADSv1_2INCLUDE"]
CODE32
AREA||.text||,CODE,READONLY
testPROC
;;;1inttest(unsignedintd)
;;;2{
000000e59f1020LDRr1,|L1.40|
;;;3if((d&0x0fffffff)==0x05555550)
000004e1a00200MOVr0,r0,LSL#4
000008e1500221CMPr0,r1,LSR#4
00000c1a000001BNE|L1.24|
;;;4return1;
000010e3a00001MOVr0,#1
|L1.20|
000014e1a0f00eMOVpc,lr
;;;5else
;;;6return0;
|L1.24|
000018e3a00000MOVr0,#0
00001ceafffffcB|L1.20|
;;;7}
ENDP
mainPROC
;;;9intmain(void)
;;;10{
000020e59f0004LDRr0,|L1.44|
;;;11volatileintd;
;;;12
;;;13d=test(0xA5555550);
000024eafffffeBtest
|L1.40|
00002805555550DCD0x05555550
|L1.44|
00002ca5555550DCD0xa5555550
;;;14
;;;15returnd;
;;;16}
ENDP
END
在848版下編譯生成test1b848.s
(armcc-O1-S-fs-cpuARM7TDMI-otest1b848.stest1.c)
;generatedbyARMCCompiler,ADS1.2[Build848]
;commandline[-O1-S-fs"-IC:ProgramFilesARMADSv1_2INCLUDE"]
CODE32
AREA||.text||,CODE,READONLY
testPROC
;;;1inttest(unsignedintd)
;;;2{
000000e59f1020LDRr1,|L1.40|
;;;3if((d&0x0fffffff)==0x05555550)
000004e1a00200MOVr0,r0,LSL#4
000008e1510220CMPr1,r0,LSR#4
00000c1a000001BNE|L1.24|
;;;4return1;
000010e3a00001MOVr0,#1
|L1.20|
000014e1a0f00eMOVpc,lr
;;;5else
;;;6return0;
|L1.24|
000018e3a00000MOVr0,#0
00001ceafffffcB|L1.20|
;;;7}
ENDP
mainPROC
;;;9intmain(void)
;;;10{
000020e59f0004LDRr0,|L1.44|
;;;11volatileintd;
;;;12
;;;13d=test(0xA5555550);
000024eafffffeBtest
|L1.40|
00002805555550DCD0x05555550
|L1.44|
00002ca5555550DCD0xa5555550
;;;14
;;;15returnd;
;;;16}
ENDP
END
用UEDIT比較一下兩個文件,生成的代碼除一行不同外,其它的都一樣(包括地址也一樣),不同的一行是
000008e1500221CMPr0,r1,LSR#4;805版
000008e1510220CMPr1,r0,LSR#4;848版
第二個測試程序:
文件名:test2.c
#include"stdio.h"
inttest(unsignedintd)
{
if((d&0x0fffffff)==0x05555550)
return1;
else
return0;
}
intmain(void)
{
volatileintd,c;
scanf("%d",&d);
d=test(d);
c=2*d;
printf("
d=%d
c=%d
",d,c);
returnc;
}
在805版編譯器下編譯,生成test1b805.s:
(armcc-O1-S-fs-cpuARM7TDMI-otest2b805.stest2.c)
;generatedbyARMCCompiler,ADS1.2[Build805]
;commandline[-O1-S-fs"-IC:ProgramFilesARMADSv1_2INCLUDE"]
CODE32
AREA||.text||,CODE,READONLY
testPROC
;;;3inttest(unsignedintd)
;;;4{
000000e59f1054LDRr1,|L1.92|
;;;5if((d&0x0fffffff)==0x05555550)
000004e1a00200MOVr0,r0,LSL#4
000008e1500221CMPr0,r1,LSR#4
00000c1a000001BNE|L1.24|
;;;6return1;
000010e3a00001MOVr0,#1
|L1.20|
000014e1a0f00eMOVpc,lr
;;;7else
;;;8return0;
|L1.24|
000018e3a00000MOVr0,#0
00001ceafffffcB|L1.20|
;;;9}
ENDP
mainPROC
;;;11intmain(void)
;;;12{
000020e92d401cSTMFDsp!,{r2-r4,lr}
;;;13volatileintd,c;
;;;14
;;;15scanf("%d",&d);
000024e28d1004ADDr1,sp,#4
000028e28f0030ADRr0,|L1.96|
00002cebfffffeBL_scanf
;;;16d=test(d);
000030e59d0004LDRr0,[sp,#4]
000034ebfffffeBLtest
000038e58d0004STRr0,[sp,#4]
;;;17
;;;18c=2*d;
00003ce59d0004LDRr0,[sp,#4]
000040e1a04080MOVr4,r0,LSL#1
;;;19printf("
d=%d
c=%d
",d,c);
000044e1a02004MOVr2,r4
000048e59d1004LDRr1,[sp,#4]
00004ce28f0010ADRr0,|L1.100|
000050ebfffffeBL_printf
;;;20
;;;21returnc;
000054e1a00004MOVr0,r4
000058e8bd801cLDMFDsp!,{r2-r4,pc}
|L1.92|
00005c05555550DCD0x05555550
|L1.96|
00006000006425DCB"%d"
|L1.100|
000064253d640aDCB"
d=%"
000068630a2064DCB"d
c"
00006c0a64253dDCB"=%d
"
00007000000000DCB""
;;;22}ENDP
END
在848版下編譯生成test2b848.s
(armcc-O1-S-fs-cpuARM7TDMI-otest2b848.stest2.c)
;generatedbyARMCCompiler,ADS1.2[Build848]
;commandline[-O1-S-fs"-IC:ProgramFilesARMADSv1_2INCLUDE"]
CODE32
AREA||.text||,CODE,READONLY
testPROC
;;;3inttest(unsignedintd)
;;;4{
000000e59f1054LDRr1,|L1.92|
;;;5if((d&0x0fffffff)==0x05555550)
000004e1a00200MOVr0,r0,LSL#4
000008e1510220CMPr1,r0,LSR#4
00000c1a000001BNE|L1.24|
;;;6return1;
000010e3a00001MOVr0,#1
|L1.20|
000014e1a0f00eMOVpc,lr
;;;7else
;;;8return0;
|L1.24|
000018e3a00000MOVr0,#0
00001ceafffffcB|L1.20|
;;;9}
ENDP
mainPROC
;;;11intmain(void)
;;;12{
000020e92d401cSTMFDsp!,{r2-r4,lr}
;;;13volatileintd,c;
;;;14
;;;15scanf("%d",&d);
000024e28d1004ADDr1,sp,#4
000028e28f0030ADRr0,|L1.96|
00002cebfffffeBL_scanf
;;;16d=test(d);
000030e59d0004LDRr0,[sp,#4]
000034ebfffffeBLtest
000038e58d0004STRr0,[sp,#4]
;;;17
;;;18c=2*d;
00003ce59d0004LDRr0,[sp,#4]
000040e1a04080MOVr4,r0,LSL#1
;;;19printf("
d=%d
c=%d
",d,c);
000044e1a02004MOVr2,r4
000048e59d1004LDRr1,[sp,#4]
00004ce28f0010ADRr0,|L1.100|
000050ebfffffeBL_printf
;;;20
;;;21returnc;
000054e1a00004MOVr0,r4
000058e8bd801cLDMFDsp!,{r2-r4,pc}
|L1.92|
00005c05555550DCD0x05555550
|L1.96|
00006000006425DCB"%d"
|L1.100|
000064253d640aDCB"
d=%"
000068630a2064DCB"d
c"
00006c0a64253dDCB"=%d
"
00007000000000DCB""
;;;22}ENDP
END
用UEDIT比較一下兩個文件,生成的代碼除一行不同外,其它的都一樣(包括地址也一樣),不同的一行是
000008e1500221CMPr0,r1,LSR#4;805版
000008e1510220CMPr1,r0,LSR#4;848版
折騰了好幾天,原來是版本太老了。
不過還好,學(xué)了不少東西,也感謝各位的指導(dǎo)!
還在使ADS1.2的要注意升級了!
補(bǔ)丁下載地址:
http://www.arm.com/support/downloads/info/4554.html
看版本號的方法:
在命令提示符下輸入
armcc
輸出
ARMCCompiler,ADS1.2[Build848]
...
網(wǎng)友評論:2.2的在RVDS2.2里有,
3.0的在keilforarm3.0x里有