|
|
我按8位单片机编译后,看汇编对比,得出如下结论(32位结果不同):
1,main里没有while循环,跑完main后,继续跑出main外,因为flash其他的地方是nop或FF, 跑一定时间后,跑飞(重启),
不过这里不讨论这个。
2, for(i=50000;i>0;i--); 与for(i=0;i<50000;i++);
加法中的50000被编译器当成了有符号long, 进行long比较,8位里的long比较花费了较多时间,所以比减法慢。
如果加法改为for(i=0;i<50000u;i++); 即明确指定无符号16位。
结果与减法基本一样。
下面上汇编:
1,减法的汇编,只给出一半,下半一样。
10: for(i=50000;i>0;i--);
C:0x0802 7508C3 MOV i(0x08),#0xC3 //这句与下句是i=50000(0xc350);
C:0x0805 750950 MOV 0x09,#0x50
C:0x0808 E509 MOV A,0x09 //读取i低字节
C:0x080A 1509 DEC 0x09 //i低字节减1
C:0x080C 7002 JNZ C:0810 //非0跳到,下第二行
C:0x080E 1508 DEC i(0x08) //i高字节减1, 这句与上2句是 i--;
C:0x0810 E509 MOV A,0x09 //读取i的低字节到a
C:0x0812 4508 ORL A,i(0x08) //或上 i的高字节到a
C:0x0814 70F2 JNZ C:0808 //非0则跳转到上面(循环); 这句与上2句是判断 i>0
11: led=1;
C:0x0816 D2A0 SETB led(0xA0.0)
12: for(i=50000;i>0;i--);
2,加法的汇编,只给出一半,下半一样。
20: for(i=0;i<50000;i++);
C:0x0802 E4 CLR A
C:0x0803 F508 MOV i(0x08),A //这句与下句: i=0;
C:0x0805 F509 MOV 0x09,A
C:0x0807 AE08 MOV R6,i(0x08) //这句与下4句: R4~R7=i;
C:0x0809 AF09 MOV R7,0x09
C:0x080B E4 CLR A
C:0x080C FC MOV R4,A //高2字节=0;
C:0x080D FD MOV R5,A
C:0x080E 7B50 MOV R3,#0x50 //这句与下4句: R0~R3=50000;
C:0x0810 7AC3 MOV R2,#0xC3
C:0x0812 F9 MOV R1,A
C:0x0813 F8 MOV R0,A //高2字节=0;
C:0x0814 D3 SETB C //c=1
C:0x0815 120849 LCALL C?SLCMP(C:0849) //调用SLCMP(), 有符号long比较,比较R0~R3与R4~R7, 见下面,时间比较耗时;
C:0x0818 400A JC C:0824 //i-50000为负,则结束循环。
C:0x081A 0509 INC 0x09 //i低字节加1 (这句与下面是i加1);
C:0x081C E509 MOV A,0x09 //读取i低字节到a
C:0x081E 70E7 JNZ C:0807 //a非0,跳到循环开头。
C:0x0820 0508 INC i(0x08) //i高字节加1(低字节进位了)
C:0x0822 80E3 SJMP C:0807 //跳到循环开头。
21: led=1;
C:0x0824 D2A0 SETB led(0xA0.0)
22: for(i=0;i<50000;i++);
有符号long比较, (R0~R3) - (R4~R7);
C?SLCMP:
C:0x0849 EB MOV A,R3
C:0x084A 9F SUBB A,R7 //R3 - R7
C:0x084B F5F0 MOV B(0xF0),A //结果存B
C:0x084D EA MOV A,R2
C:0x084E 9E SUBB A,R6 //R2 - R6
C:0x084F 42F0 ORL B(0xF0),A //结果或存到B
C:0x0851 E9 MOV A,R1
C:0x0852 9D SUBB A,R5 //R1 - R5
C:0x0853 42F0 ORL B(0xF0),A //结果或存到B
C:0x0855 EC MOV A,R4
C:0x0856 6480 XRL A,#P0(0x80) //A=R4, A去掉符号位
C:0x0858 C8 XCH A,R0 //A与R0交换
C:0x0859 6480 XRL A,#P0(0x80) //A=R0, A去掉符号位
C:0x085B 98 SUBB A,R0 //A-R0 == 原R0-原R4(去掉符号位的)
C:0x085C 45F0 ORL A,B(0xF0) //A或上B
C:0x085E 22 RET //返回
3,加法的汇编-加"u"指定无符号16位,只给出一半,下半一样。
20: for(i=0;i<50000u;i++);
C:0x0802 E4 CLR A
C:0x0803 F508 MOV i(0x08),A //这句与下句: i=0
C:0x0805 F509 MOV 0x09,A
C:0x0807 0509 INC 0x09 //i低字节加1, (这句与下3句是 i加1)
C:0x0809 E509 MOV A,0x09 //i低字节读进A
C:0x080B 7002 JNZ C:080F //A非0则跳到下第二句
C:0x080D 0508 INC i(0x08) //i高字节加1(低字节进位)
C:0x080F B450F5 CJNE A,#0x50,C:0807 //比较A-0x50(50000的低字节),不等则跳转到循环开头。
C:0x0812 E508 MOV A,i(0x08) //i高字节读进A
C:0x0814 B4C3F0 CJNE A,#0xC3,C:0807 //比较A-0xC3(50000的高字节),不等则跳转到循环开头。
21: led=1;
C:0x0817 D2A0 SETB led(0xA0.0)
|
|