ฉันมีคำถามเกี่ยวกับแนวคิด: ความหนาแน่นของรหัส "สูง" หมายถึงอะไร และทำไมมันถึงสำคัญ?
ฉันมีคำถามเกี่ยวกับแนวคิด: ความหนาแน่นของรหัส "สูง" หมายถึงอะไร และทำไมมันถึงสำคัญ?
คำตอบ:
ความหนาแน่นของรหัสหมายถึงจำนวนไมโครโปรเซสเซอร์ที่แนะนำในการดำเนินการตามที่ร้องขอและจำนวนช่องว่างที่แต่ละคำสั่งใช้ โดยทั่วไปแล้วการสอนที่น้อยลงต้องใช้เวลามากขึ้นและยิ่งทำงานได้มากขึ้นต่อการสอนที่ไมโครโปรเซสเซอร์สามารถทำได้ยิ่งรหัสของมันมีความหนาแน่นมากขึ้นเท่านั้น
ฉันสังเกตเห็นว่าคุณติดแท็กคำถามของคุณด้วยแท็ก 'arm' ฉันสามารถอธิบายความหนาแน่นของรหัสโดยใช้คำสั่ง ARM
สมมติว่าคุณต้องการคัดลอกบล็อกข้อมูลจากที่หนึ่งไปยังอีกที่หนึ่งในหน่วยความจำ แนวคิดรหัสระดับสูงของคุณจะเป็นดังนี้:
void memcpy(void *dest, void *source, int count_bytes)
{
char *s, *d;
s = source; d = dest;
while(count_bytes--) { *d++ = *s++; }
}
ตอนนี้คอมไพเลอร์อย่างง่ายสำหรับไมโครโปรเซสเซอร์อย่างง่ายอาจแปลงสิ่งนี้เป็นสิ่งต่อไปนี้:
movl r0, count_bytes
movl r1, s
movl r2, d
loop: ldrb r3, [r1]
strb [r2], r3
movl r3, 1
add r1, r3
add r2, r3
sub r0, r3
cmp r0, 0
bne loop
(แขนของฉันเป็นสนิมเล็กน้อย แต่คุณได้รับความคิด)
ตอนนี้จะเป็นคอมไพเลอร์ที่ง่ายมากและไมโครโปรเซสเซอร์ที่ง่ายมาก แต่คุณสามารถดูได้จากตัวอย่างที่เรากำลังดู 8 คำสั่งต่อการวนซ้ำของลูป (7 ถ้าเราย้าย '1' ไปยังรีจิสเตอร์อื่นและย้ายโหลด นอกวง) นั่นไม่หนาแน่นเลย ความหนาแน่นของรหัสยังส่งผลต่อประสิทธิภาพ หากลูปของคุณยาวขึ้นเนื่องจากรหัสไม่หนาแน่นคุณอาจต้องใช้แคชคำสั่งเพิ่มเติมเพื่อเก็บลูป แคชมากขึ้นหมายถึงโปรเซสเซอร์ที่มีราคาแพงกว่า แต่จากนั้นการถอดรหัสคำสั่งที่ซับซ้อนอีกครั้งทำให้ทรานซิสเตอร์มากขึ้นในการถอดรหัสคำสั่งที่ร้องขอดังนั้นจึงเป็นปัญหาทางวิศวกรรมแบบดั้งเดิม
ARM นั้นค่อนข้างดีในแง่นี้ ทุกคำสั่งสามารถมีเงื่อนไขคำสั่งส่วนใหญ่สามารถเพิ่มหรือลดค่าของการลงทะเบียนและคำแนะนำส่วนใหญ่สามารถเลือกที่จะปรับปรุงธงโปรเซสเซอร์ บน ARM และคอมไพเลอร์ที่มีประโยชน์พอสมควรลูปเดียวกันอาจมีหน้าตาดังนี้:
movl r0, count_bytes
movl r1, s
movl r2, d
loop: ldrb r3, [r1++]
strb [r2++], r3
subs r0, r0, 1
bne loop
อย่างที่คุณเห็นวงวนหลักคือ 4 คำสั่ง รหัสมีความหนาแน่นมากกว่าเนื่องจากคำสั่งแต่ละคำสั่งในลูปหลักทำได้มากกว่า โดยทั่วไปหมายความว่าคุณสามารถทำอะไรได้มากขึ้นด้วยจำนวนหน่วยความจำที่กำหนดเนื่องจากมีหน่วยความจำน้อยกว่าที่ใช้เพื่ออธิบายวิธีการทำงาน
ตอนนี้รหัส ARM เนทีฟมักจะมีการร้องเรียนว่ามันไม่ได้หนาแน่นมาก นี่เป็นเพราะเหตุผลหลักสองข้อ: อันดับแรก 32 บิตเป็นคำสั่ง "ยาว" ที่ยอดเยี่ยมดังนั้นบิตจำนวนมากดูเหมือนจะสูญเปล่าสำหรับคำแนะนำที่ง่ายขึ้นและที่สองรหัสได้ป่องเนื่องจากธรรมชาติของ ARM: แต่ละคำสั่งคือ 32 บิตยาวโดยไม่มีข้อยกเว้น ซึ่งหมายความว่ามีค่าตัวอักษร 32 บิตจำนวนมากที่คุณไม่สามารถโหลดลงทะเบียนได้ ถ้าฉันต้องการโหลด "0x12345678" ลงใน r0 ฉันจะรหัสคำสั่งที่ไม่เพียง แต่มี 0x12345678 อยู่ในนั้น แต่ยังอธิบายถึง "load literal to r0" ด้วย? ไม่มีบิตเหลือที่จะเขียนโค้ดการทำงานจริง คำสั่งการโหลดตัวอักษร ARM เป็นสัตว์ตัวเล็กที่น่าสนใจและแอสเซมเบลอร์ ARM จะต้องฉลาดกว่าแอสเซมบลีปกติเล็กน้อยเนื่องจากต้อง "จับ"
อย่างไรก็ตามเพื่อตอบข้อร้องเรียนเหล่านี้ ARM ก็มาพร้อมกับโหมดนิ้วหัวแม่มือ แทนที่จะเป็น 32 บิตต่อคำสั่งความยาวของคำสั่งตอนนี้คือ 16 บิตสำหรับคำสั่งเกือบทั้งหมดและ 32 บิตสำหรับกิ่ง มีการเสียสละเพียงเล็กน้อยในโหมด Thumb แต่โดยส่วนใหญ่การเสียสละเหล่านี้ง่ายต่อการทำเพราะ Thumb ทำให้คุณมีความหนาแน่นของรหัสเพิ่มขึ้น 40% เพียงแค่ลดความยาวของคำสั่ง
"ความหนาแน่นของรหัส" ของชุดคำสั่งเป็นการวัดว่าคุณสามารถรับหน่วยความจำของโปรแกรมจำนวนเท่าใดหรือหน่วยความจำของโปรแกรมจำนวนไบต์ที่คุณต้องใช้เพื่อเก็บฟังก์ชันการทำงาน
ดังที่ Andrew Kohlsmith ชี้ให้เห็นถึงแม้กระทั่งบน MCU ตัวเดียวกันคอมไพเลอร์ที่แตกต่างกันก็สามารถรับรหัสที่ต่างกันได้
คุณอาจเพลิดเพลินกับการอ่าน "แมลงในโลกคอมพิวเตอร์"โดย Miro Samek ซึ่งเปรียบเทียบ MCU ที่หลากหลาย