Assemby VS C (In-depth)
วันนี้ลองมาวัดกันระหว่าง ASM และ C เริ่มกันที่โจทย์ ง่ายๆ แบบนี้ (ตามรูป) เปิดฉากด้วย ASM:
org 0x000 jmp start DISP_CODE: DB 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F org 0x0100 start: mov r0,#0 mov a,#DISP_CODE loop: clr a movc a,@a+dptr inc dptr mov p0,a call delay_100ms inc r0; mov a,#10 subb a,r0 jnz loop sjmp start delay_100ms: mov r6,#200 d_100ms: mov r7,#248 djnz r7,$ djnz r6,d_100ms mov r7,#97 djnz r7,$ ret end
ตามติดๆ มาด้วย C:
#include <reg52.h> char DISP_CODE[]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; void delay_100mS(void); void main(void){ char k; while(1){ P0=DISP_CODE[k]; delay_100mS(); k++; if(k>9)k=0; } }
void delay_100mS(void){ unsigned char x,y; for(x=105;x>0;x--){ for(y=245;y>0;y--){ y=y; } } }
ทั้งสองแบบเขียนกันอย่างไม่เข้าข้างใดข้างหนึ่ง นั่นคือตัดเรื่อง optimization ออกไป หรือเขียนแบบจรงไปตรงมานั่นเอง (ด้วยความรู้สึกของผมเอง)
คราวนี้มาดู output กัน:
ของ ASM :0C00000021003F065B4F666D7D077F6F9F :1001000078007402E493A3F580311308740A9870A0 :10011000F380ED7EC87FF8DFFEDEFA7F61DFFE222E :00000001FF ของ C :0C00B8000A083F065B4F666D7D077F6FF6 :10008F0074082512F8E6F5801200AA0512D3E512BE :0B009F006480948A40EAE4F51280E5DA :0D00AA007F697EF51EEED3940050F9DFF55E :0100B7002226 :03000000020003F8 :0C000300787FE4F6D8FD75811202004AF7 :10000F0002008FE493A3F8E493A34003F68001F278 :10001F0008DFF48029E493A3F85407240CC8C333F2 :10002F00C4540F4420C8834004F456800146F6DFC1 :10003F00E4800B01020408102040809000B8E47E99 :10004F00019360BCA3FF543F30E509541FFEE493B6 :10005F00A360010ECF54C025E060A840B8E493A37D :10006F00FAE493A3F8E493A3C8C582C8CAC583CAA8 :10007F00F0A3C8C582C8CAC583CADFE9DEE780BE60 :0100C400003B :00000001FF ทั้งของ ASM และ ของ C ไม่มีการใช้ code ในส่วนของ startup ใดๆ มาเกี่ยวข้องทั้งสิ้น หลีกเลี่ยงการใช้ตัวแปลที่ใหญ่กว่า 8 บิต (ใน C) มองที่การใช้ RAM (มองรีจิสเตอร์เป็น RAM ด้วย) ASM ใช้ไป 2 ไบต์ C ใช้ไป 20 ไบต์
มองที่ใช้เวลาในการเขียน (วัดเวลาที่ผมเขียนเอง และโปรแกรมถูกวางแผนไว้ในใจมาก่อนแล้ว) ASM ใช้เวลาประมาณ 5 นาที C ใช้เวลาประมาณ 3 นาที
แล้วจะเลือกอะไรดี? อย่าตกใจไปครับ จริงๆ C Compiler เขามีอะไรที่ต้องทำอีกมายมายก่อนที่จะวิ่งเข้าส่วนของโปรแกรมที่เราเขียนขึ้น Code ส่วนนี้จะถูกสร้างขึ้นมาโดยอัตโนมัติ เป็น code ที่ว่าด้วยกำกำหนดค่าเริ่มของ Stack รวมไปถึงส่วนอื่นๆ ที่จำเป็น code ส่วนนี้ C Programmer จะไม่ค่อยสนใจ
หมายรวมไปถึง ASM Programmer บางส่วนด้วยเช่นกัน
C:0x0000 020003 LJMP C:0003 C:0x0003 787F MOV R0,#0x7F C:0x0005 E4 CLR A C:0x0006 F6 MOV @R0,A C:0x0007 D8FD DJNZ R0,C:0006 C:0x0009 758112 MOV SP(0x81),#0x12 C:0x000C 02004A LJMP C:004A C:0x000F 02008F LJMP main(C:008F) C:0x0012 E4 CLR A C:0x0013 93 MOVC A,@A+DPTR C:0x0014 A3 INC DPTR C:0x0015 F8 MOV R0,A C:0x0016 E4 CLR A C:0x0017 93 MOVC A,@A+DPTR C:0x0018 A3 INC DPTR C:0x0019 4003 JC C:001E C:0x001B F6 MOV @R0,A C:0x001C 8001 SJMP C:001F C:0x001E F2 MOVX @R0,A C:0x001F 08 INC R0 C:0x0020 DFF4 DJNZ R7,C:0016 C:0x0022 8029 SJMP C:004D C:0x0024 E4 CLR A C:0x0025 93 MOVC A,@A+DPTR C:0x0026 A3 INC DPTR C:0x0027 F8 MOV R0,A C:0x0028 5407 ANL A,#0x07 C:0x002A 240C ADD A,#0x0C C:0x002C C8 XCH A,R0 C:0x002D C3 CLR C C:0x002E 33 RLC A C:0x002F C4 SWAP A C:0x0030 540F ANL A,#0x0F C:0x0032 4420 ORL A,#0x20 C:0x0034 C8 XCH A,R0 C:0x0035 83 MOVC A,@A+PC C:0x0036 4004 JC C:003C C:0x0038 F4 CPL A C:0x0039 56 ANL A,@R0 C:0x003A 8001 SJMP C:003D C:0x003C 46 ORL A,@R0 C:0x003D F6 MOV @R0,A C:0x003E DFE4 DJNZ R7,C:0024 C:0x0040 800B SJMP C:004D C:0x0042 0102 AJMP C:0002 C:0x0044 04 INC A C:0x0045 08 INC R0 C:0x0046 102040 JBC 0x24.0,C:0089 C:0x0049 8090 SJMP C:FFDB C:0x004B 00 NOP C:0x004C B8E47E CJNE R0,#0xE4,C:00CD C:0x004F 0193 AJMP C:0093 C:0x0051 60BC JZ C:000F C:0x0053 A3 INC DPTR C:0x0054 FF MOV R7,A C:0x0055 543F ANL A,#0x3F C:0x0057 30E509 JNB 0xE0.5,C:0063 C:0x005A 541F ANL A,#0x1F C:0x005C FE MOV R6,A C:0x005D E4 CLR A C:0x005E 93 MOVC A,@A+DPTR C:0x005F A3 INC DPTR C:0x0060 6001 JZ C:0063 C:0x0062 0E INC R6 C:0x0063 CF XCH A,R7 C:0x0064 54C0 ANL A,#0xC0 C:0x0066 25E0 ADD A,ACC(0xE0) C:0x0068 60A8 JZ C:0012 C:0x006A 40B8 JC C:0024 C:0x006C E4 CLR A C:0x006D 93 MOVC A,@A+DPTR C:0x006E A3 INC DPTR C:0x006F FA MOV R2,A C:0x0070 E4 CLR A C:0x0071 93 MOVC A,@A+DPTR C:0x0072 A3 INC DPTR C:0x0073 F8 MOV R0,A C:0x0074 E4 CLR A C:0x0075 93 MOVC A,@A+DPTR C:0x0076 A3 INC DPTR C:0x0077 C8 XCH A,R0 C:0x0078 C582 XCH A,DPL(0x82) C:0x007A C8 XCH A,R0 C:0x007B CA XCH A,R2 C:0x007C C583 XCH A,DPH(0x83) C:0x007E CA XCH A,R2 C:0x007F F0 MOVX @DPTR,A C:0x0080 A3 INC DPTR C:0x0081 C8 XCH A,R0 C:0x0082 C582 XCH A,DPL(0x82) C:0x0084 C8 XCH A,R0 C:0x0085 CA XCH A,R2 C:0x0086 C583 XCH A,DPH(0x83) C:0x0088 CA XCH A,R2 C:0x0089 DFE9 DJNZ R7,C:0074 C:0x008B DEE7 DJNZ R6,C:0074 C:0x008D 80BE SJMP C:004D
ต่อไปลองมาดูในส่วนที่เราเขียนขึ้นบ้าง
4: void main(void){ 5: char k; 6: while(1){ 7: P0=DISP_CODE[k]; C:0x008F 7408 MOV A,#DISP_CODE(0x08) C:0x0091 2512 ADD A,0x12 C:0x0093 F8 MOV R0,A C:0x0094 E6 MOV A,@R0 C:0x0095 F580 MOV P0(0x80),A 8: delay_100mS(); C:0x0097 1200AA LCALL delay_100mS(C:00AA) 9: k++; C:0x009A 0512 INC 0x12 10: if(k>10)k=0; C:0x009C D3 SETB C C:0x009D E512 MOV A,0x12 C:0x009F 6480 XRL A,#P0(0x80) C:0x00A1 948A SUBB A,#TL0(0x8A) C:0x00A3 40EA JC main(C:008F) C:0x00A5 E4 CLR A C:0x00A6 F512 MOV 0x12,A 11: } 12: } 13: C:0x00A8 80E5 SJMP main(C:008F) 14: void delay_100mS(void){ 15: unsigned char x,y; 16: for(x=105;x>0;x--){ C:0x00AA 7F69 MOV R7,#0x69 17: for(y=245;y>0;y--){ C:0x00AC 7EF5 MOV R6,#0xF5 18: y=y; 19: } C:0x00AE 1E DEC R6 C:0x00AF EE MOV A,R6 C:0x00B0 D3 SETB C C:0x00B1 9400 SUBB A,#0x00 C:0x00B3 50F9 JNC C:00AE 20: } C:0x00B5 DFF5 DJNZ R7,C:00AC 21: }
เอาหละ... เริ่มหวั่น แล้วตกลงมันยังไงกันล่ะทีนี้
งั้นเข้าไปเจาะให้ลึกลงไปอีก เอาที่แบบเป็น Machine code จริงๆ เลย (ตัดความเป็น Intel Format ออกไป)
ของ ASM 210078007402E493A3F580311308740A9870A0F380ED7EC87FF8DFFEDEFA7F61DFFE22 ของ C 02008F74082521F8E6F5801200AA0512D3Ed126480948A40EAE4F51280E57F697EF51EEED3940050F9DFF5 ชัดเจนครับ ตอนนี้ว่ากันที่เนื้อแท้ของ Machine code จะเห็นว่า C ยาวกว่าไป 7 ไบต์ (ย้ำนะครับ ทั้งหมดเขียนแบบตรงไปตรงไปตรงมาไม่มีการ optimize ทั้งใน ASM และ C) ความคิดของโปรแกรมเมอร์ยุคเก่า (ที่เก๋าพอตัว) ยังคงเป็นจริงต่อไปว่า C ไม่มีทางจะสู้ ASM ได้เลย ตรงนี้ก็ต้องพิจารณากันเอาเองครับ ผมไม่มีความเห็นใดๆ
แต่.... อย่างไรก็คุณผู้อ่านอย่าได้ไปท้าทายกับมือฉมังด้าน ASM หรือ C เพื่อจะวัดอะไรบางอย่างเป็นอันขาด เพราะการเขียน Code ในระดับ Optimization ทั้งใน ASM และ C มันมีอะไรน่ากลัวและน่าทึ่งมากกว่าที่เราๆ ท่านๆรู้จักกันมากนัก แต่ถ้าวัดกันจริงๆ การ Optimize ของผู้เชี่ยวชาญด้าน ASM นั้น C Programmer และ C Compiler ที่ดีที่สุดในโลกก็ไม่มีทางจะสู้ได้ทั้งในแง่ของความเร็ว และขนาดของ Machine code แต่...เวลาในการเขียนโปรแกรมขนาดใหญ่ๆ ASM แพ้ไม่เป็นท่าแน่นอน
จะยังไงก็ตาม ด้วยข้อด้อยและข้อดี ของทั้งสองตัว มันก็เลยทำให้ผม และใครๆ หลายต่อหลายคน ไม่สามารถละได้ทั้ง ASM และ C ออกไปจากชีวิตได้ !! โดยเฉพาะเมื่ออยู่ในโลกของ Embedded System บทความนี้สรุปว่า รักพี่เสียดายน้อง
By Santi; //www.shadowwares.com
Create Date : 31 มีนาคม 2554 |
|
0 comments |
Last Update : 31 มีนาคม 2554 9:41:58 น. |
Counter : 1026 Pageviews. |
|
|
|