รหัสการประกอบเทียบกับรหัสเครื่องกับรหัสวัตถุ?


227

รหัสวัตถุรหัสเครื่องจักรและรหัสการประกอบต่างกันอย่างไร

คุณสามารถยกตัวอย่างที่เป็นภาพเกี่ยวกับความแตกต่างได้หรือไม่?


ฉันยังอยากรู้ว่าชื่อ "รหัสวัตถุ" นั้นมาจากไหน? คำว่า "วัตถุ" ควรจะหมายถึงอะไรในนั้น? มันเกี่ยวข้องกับการเขียนโปรแกรมเชิงวัตถุหรือเป็นเรื่องบังเอิญของชื่อหรือไม่?
SasQ

@SasQ: รหัสวัตถุ
Jesse Good

ฉันไม่ได้ถามว่าโค้ดออบเจคคือ Captain Obืออะไร ฉันถามว่าชื่อมาจากไหนและทำไมเรียกว่ารหัส "วัตถุ"
BarbaraKwarc

คำตอบ:


296

รหัสเครื่องเป็นรหัสไบนารี่ (1 และ 0) ที่สามารถเรียกใช้งานได้โดยตรงจาก CPU หากคุณกำลังจะเปิดแฟ้มรหัสเครื่องในโปรแกรมแก้ไขข้อความที่คุณจะเห็นขยะรวมทั้งตัวละคร unprintable (ไม่มีไม่ผู้อักขระ unprintable;))

รหัสวัตถุเป็นส่วนหนึ่งของรหัสเครื่องที่ยังไม่ได้เชื่อมโยงกับโปรแกรมที่สมบูรณ์ เป็นรหัสเครื่องสำหรับห้องสมุดหรือโมดูลหนึ่งที่จะสร้างผลิตภัณฑ์ที่สมบูรณ์ นอกจากนี้ยังอาจมีตัวยึดตำแหน่งหรือออฟเซ็ตที่ไม่พบในรหัสเครื่องของโปรแกรมที่เสร็จสมบูรณ์ ลิงเกอร์จะใช้ตัวยึดตำแหน่งเหล่านี้และชดเชยการร่วมกันทุกอย่างเชื่อมต่อ

รหัสแอสเซมบลีเป็นข้อความธรรมดาและ (ค่อนข้าง) ซอร์สโค้ดที่มนุษย์สามารถอ่านได้ซึ่งส่วนใหญ่มีแอนะล็อกโดยตรง 1: 1 พร้อมคำแนะนำเครื่อง สิ่งนี้สามารถทำได้โดยใช้ตัวช่วยจำสำหรับคำแนะนำจริงการลงทะเบียนหรือทรัพยากรอื่น ๆ ตัวอย่างรวมถึงJMPและMULTสำหรับคำแนะนำการกระโดดและการคูณของ CPU ซีพียูไม่เข้าใจรหัสการประกอบต่างจากรหัสเครื่อง คุณแปลงแอสเซมบลีโค้ดเป็นเครื่องด้วยการใช้แอสเซมเบลอร์หรือคอมไพเลอร์แม้ว่าเรามักจะคิดถึงคอมไพเลอร์ร่วมกับภาษาการเขียนโปรแกรมระดับสูงที่แยกออกจากคำสั่ง CPU

การสร้างโปรแกรมที่สมบูรณ์เกี่ยวข้องกับการเขียนซอร์สโค้ดของโปรแกรมในชุดประกอบหรือภาษาระดับสูงกว่าเช่น C ++ ซอร์สโค้ดถูกประกอบ (สำหรับรหัสแอสเซมบลี) หรือคอมไพล์ (สำหรับภาษาระดับสูงกว่า) ไปยังรหัสวัตถุและแต่ละโมดูลจะถูกเชื่อมโยงเข้าด้วยกันเพื่อให้กลายเป็นรหัสเครื่องสำหรับโปรแกรมสุดท้าย ในกรณีของโปรแกรมอย่างง่ายขั้นตอนการเชื่อมโยงอาจไม่จำเป็น ในกรณีอื่นเช่นเช่น IDE (สภาพแวดล้อมการพัฒนาแบบรวม) ตัวเชื่อมโยงและคอมไพเลอร์อาจถูกเรียกเข้าด้วยกัน ในกรณีอื่น ๆ ที่มีความซับซ้อนทำให้สคริปต์หรือวิธีการแก้ปัญหาไฟล์อาจถูกใช้เพื่อบอกสภาพแวดล้อมวิธีการสร้างแอพลิเคชันสุดท้าย

นอกจากนี้ยังมีภาษาตีความที่ทำงานแตกต่างกัน ภาษาที่แปลขึ้นอยู่กับรหัสเครื่องของโปรแกรมล่ามพิเศษ ในระดับพื้นฐานล่ามจะวิเคราะห์รหัสต้นฉบับและแปลงคำสั่งเป็นรหัสเครื่องใหม่ทันทีและดำเนินการคำสั่งเหล่านั้น ล่ามสมัยใหม่บางครั้งเรียกว่าสภาพแวดล้อมรันไทม์หรือเครื่องเสมือนมีความซับซ้อนมากขึ้น: การประเมินส่วนทั้งหมดของซอร์สโค้ดครั้งการแคชและการเพิ่มประสิทธิภาพที่เป็นไปได้และการจัดการงานการจัดการหน่วยความจำที่ซับซ้อน ภาษาที่แปลอาจรวบรวมไว้ล่วงหน้าเป็นภาษากลางระดับต่ำหรือ bytecode คล้ายกับรหัสแอสเซมบลี


24
+1: คำตอบที่ดี แต่ค่อนข้างง่าย - ไม่ใช่คำสั่งประกอบทั้งหมดแปล 1: 1 เป็นคำสั่งเครื่องและไฟล์ออบเจ็กต์อาจมีข้อมูลอื่น (ข้อมูลการย้ายตำแหน่งตารางสัญลักษณ์ ... )
Christoph

5
เพิ่มคำพังพอนสำหรับปัญหาแรกของคุณแก้ไขเพื่อให้ชัดเจนขึ้น
Joel Coehoorn

2
@Christoph: คุณพูดว่า "คำแนะนำการประกอบไม่ได้แปล 1: 1 ไปยังคำแนะนำเครื่อง" โปรดยกตัวอย่าง
Olof Forshell

5
@Olof: สถาปัตยกรรม RISC บางครั้งมีชุดคำสั่งเสมือนระดับแอสเซมบลี - เช่น MIPS หลอกคำแนะนำ ( en.wikipedia.org/wiki/MIPS_architecture#Pseudo_instructions )
Christoph

3
@Panzercrisis ผู้แต่งไม่มีอะไรเพิ่มเข้ามา เป็นการแปลสิ่งที่คุณเขียนไปยังคำแนะนำเครื่องจริงโดยตรง และฉันจะไม่เรียกรหัสพิเศษที่คอมไพเลอร์ใส่ "ไม่จำเป็น"
Joel Coehoorn

125

คำตอบอื่น ๆ ให้คำอธิบายที่ดีเกี่ยวกับความแตกต่าง แต่คุณขอภาพด้วย นี่คือแผนภาพแสดงให้เห็นว่าพวกเขาเดินทางจากรหัส C ไปสู่การปฏิบัติการ


3
ฉันคิดว่ามันมีประโยชน์จริง ๆ แต่ไม่มีป้ายกำกับ "รหัสเครื่อง"
Alexx Roche

ดังนั้นเมื่ออยู่ในระดับรหัสที่สามารถใช้งานได้เทียบเท่ากับรหัสเครื่องหรือไม่
CMCDragonkai

3
ในบริบทของแผนภาพนี้ "รหัสวัตถุ" คือรหัสเครื่อง
กราฟิก Noob

5
ที่จริงแล้วทั้งรหัสวัตถุและรหัสที่สามารถใช้งานได้คือรหัสเครื่อง ความแตกต่างคือรหัสวัตถุไม่ใช่โปรแกรมที่เสร็จสมบูรณ์ จำเป็นต้องใช้ร่วมกับรหัสไลบรารี / โมดูลตัวช่วยอื่นตามที่ระบุในแผนภาพเพื่อสร้างโปรแกรม / รหัสที่สามารถเรียกทำงานได้อย่างสมบูรณ์
okey_on

@okeyxyz ที่ระดับใดจะถูกต้องหรือไม่ที่จะพูดว่าโปรเซสเซอร์ทำงานโดยตรงหรือไม่ หลังจากแอสเซมเบลอร์หลังจากลิงเกอร์หลังจากโหลดเดอร์แล้วมันถูกแปลงเป็นไมโครคอนโทรลเลอร์?
Celeritas

49

รหัสการประกอบเป็นรหัสที่มนุษย์สามารถอ่านได้ของเครื่อง:

mov eax, 77
jmp anywhere

รหัสเครื่องเป็นรหัสเลขฐานสิบหกบริสุทธิ์:

5F 3A E3 F1

ฉันถือว่าคุณหมายถึงรหัสวัตถุเช่นเดียวกับในวัตถุไฟล์ นี่คือความแตกต่างของรหัสเครื่องโดยมีความแตกต่างที่การกระโดดถูกเรียงลำดับของพารามิเตอร์เพื่อให้ linker สามารถเติมได้

แอสเซมเบลอร์จะใช้ในการแปลงรหัสแอสเซมบลีเป็นรหัสเครื่อง (รหัสวัตถุ) ตัวเชื่อมโยงเชื่อมโยงหลาย ๆ ไฟล์ออบเจ็กต์ (และไลบรารี) เพื่อสร้างไฟล์เรียกทำงาน

ฉันเคยเขียนโปรแกรมแอสเซมเบลอร์ใน hex บริสุทธิ์ (ไม่มีแอสเซมเบลอร์) ที่โชคดีนี่เป็นวิธีย้อนกลับไปสู่ยุคเก่าที่ดี (เก่า) 6502 แต่ฉันดีใจที่มีแอสเซมบลีสำหรับ Pentium opcodes


76
ไม่ไม่ไม่ไม่. รหัสเครื่องไม่ใช่รหัสฐานสิบหก มันเป็นไบนารีบริสุทธิ์ เลขฐานสิบหกเป็นเพียงการแสดงไบนารีที่สะดวก
Breton

56
ถ้าเรากำลังเข้าสู่สุดขั้วไม่ใช่ไบนารีมันคือปริมาณไฟฟ้าที่เก็บไว้ในวงจร ;-)
Toon Krijthe

17
ใช่แน่นอน มีความสัมพันธ์ระหว่างเลขฐานสิบหกและสิ่งที่คุณจะเรียกว่า "รหัสเครื่อง" แต่ก็ไม่ถูกต้องนักที่จะพูดว่าเลขฐานสิบหกคือรหัสเครื่อง นั่นคือทั้งหมดที่ฉันพยายามจะพูด
Breton

9
@Breton ในแง่นั้นไม่มีสิ่งเช่น "hex hex" ใช่ไหม? "Hex code" เป็นเพียงวิธีการดูรหัสเครื่อง คุณสามารถดูรหัสเครื่องในเลขฐานสิบหก, ไบนารี, ฐานแปด, ทศนิยมหรือตามที่คุณต้องการ อีกครั้งในแง่นั้นไม่มี "รหัสไบนารี" เช่นกัน อีกครั้ง "รหัสไบนารี" เป็นเพียงวิธีการดูรหัสเครื่อง
Utku

9
@Breton สิ่งที่คุณพูดไม่สมเหตุสมผลจริงๆ .. Binary เป็นวิธีในการแสดงเช่นเดียวกับฐานสิบหก หากไม่ใช่ฐานสิบหกแสดงว่าไม่ใช่เลขฐานสอง
Koray Tugay

18

8B 5D 32 เป็นรหัสเครื่อง

mov ebx, [ebp+32h] เป็นชุดประกอบ

lmylib.soบรรจุ8B 5D 32คือรหัสวัตถุ


8

ประเด็นหนึ่งที่ยังไม่ได้กล่าวถึงคือมีแอสเซมบลีโค้ดสองสามชนิดที่แตกต่างกัน ในรูปแบบพื้นฐานที่สุดตัวเลขทั้งหมดที่ใช้ในคำแนะนำจะต้องระบุว่าเป็นค่าคงที่ ตัวอย่างเช่น:

$ 1902: BD 37 14: LDA $ 1437, X
$ 1905: 85 03: STA $ 03
$ 1907: 85 09: STA $ 09
$ 1909: CA: DEX
$ 190A: 10: BPL $ 1902

บิตด้านบนของรหัสหากจัดเก็บที่ที่อยู่ $ 1900 ในตลับ Atari 2600 จะแสดงจำนวนบรรทัดในสีต่าง ๆ ที่ดึงมาจากตารางซึ่งเริ่มต้นที่ที่อยู่ $ 1437 ในเครื่องมือบางอย่างการพิมพ์ที่อยู่พร้อมกับส่วนด้านขวาสุดของบรรทัดด้านบนจะเก็บหน่วยความจำค่าที่แสดงในคอลัมน์กลางและเริ่มบรรทัดถัดไปด้วยที่อยู่ต่อไปนี้ การพิมพ์รหัสในรูปแบบนั้นสะดวกกว่าการพิมพ์แบบ hex แต่ต้องรู้ที่อยู่ที่ถูกต้องของทุกสิ่ง

แอสเซมบลีส่วนใหญ่อนุญาตให้หนึ่งเพื่อใช้ที่อยู่เป็นสัญลักษณ์ รหัสข้างต้นจะเขียนเหมือน:

rainbow_lp:
  lda ColorTbl, x
  sta WSYNC
  sta COLUBK
  Dex
  bpl rainbow_lp

แอสเซมเบลอร์จะปรับคำสั่ง LDA โดยอัตโนมัติดังนั้นมันจะอ้างถึงที่อยู่ใด ๆ ที่ถูกแมปกับฉลาก ColorTbl การใช้แอสเซมเบลอร์ลักษณะนี้ทำให้ง่ายต่อการเขียนและแก้ไขโค้ดมากกว่าที่จะเป็นไปได้หากมีการใช้กุญแจมือและบำรุงรักษาที่อยู่ทั้งหมด


1
+1 จุดหนึ่งที่เพิ่มเติม: ยังมีภาษาที่แตกต่างกันประกอบไวยากรณ์ , ความเป็นอยู่ที่มีชื่อเสียงที่สุดของ Intel และ AT & T
informatik01

1
@ informatik01: แล้ว Intel 8080 mnemonics และ Zilog Z80 ล่ะ? ฉันเดาว่าจะนำหน้าสงครามไวยากรณ์ของ Intel vs AT&T มาก่อน
supercat

ไม่เถียงฉันเพิ่งพูดถึงแง่มุมนั้น (ซินแท็กซ์ต่างกัน) และยกตัวอย่างของซินแท็กซ์ที่ได้รับความนิยม / รู้จักกันดี / มีชื่อเสียงมากที่สุดสองรายการ
informatik01

4

ซอร์สโค้ด, รหัสแอสเซมบลี, รหัสเครื่อง, รหัสวัตถุ, รหัสไบต์, ไฟล์เรียกทำงานและไฟล์ Library

เงื่อนไขทั้งหมดเหล่านี้มักจะทำให้เกิดความสับสนมากสำหรับคนส่วนใหญ่ความจริงที่ว่าพวกเขาคิดว่าพวกเขาเป็นพิเศษร่วมกัน ดูแผนภาพเพื่อทำความเข้าใจความสัมพันธ์ของพวกเขา คำอธิบายของแต่ละคำศัพท์ได้รับด้านล่าง


ประเภทของรหัส


รหัสแหล่งที่มา

คำแนะนำในภาษา (การเขียนโปรแกรม) ที่มนุษย์สามารถอ่านได้


รหัสระดับสูง

คำแนะนำในภาษาระดับสูง (การเขียนโปรแกรม)
เช่นโปรแกรม C, C ++ และ Java


รหัสการประกอบ

คำแนะนำที่เขียนในภาษาแอสเซมบลี (ชนิดของภาษาการเขียนโปรแกรมระดับต่ำ) เป็นขั้นตอนแรกของกระบวนการรวบรวมรหัสระดับสูงจะถูกแปลงเป็นแบบฟอร์มนี้ เป็นรหัสชุดประกอบซึ่งจะถูกแปลงเป็นรหัสเครื่องจริง ในระบบส่วนใหญ่ขั้นตอนทั้งสองนี้จะดำเนินการโดยอัตโนมัติในฐานะเป็นส่วนหนึ่งของกระบวนการรวบรวม
เช่น program.asm


รหัสวัตถุ

ผลิตภัณฑ์ของกระบวนการรวบรวม อาจอยู่ในรูปแบบของรหัสเครื่องหรือรหัสไบต์
เช่น file.o


รหัสเครื่อง

คำแนะนำในภาษาเครื่อง
เช่น a.out


รหัสไบต์

การเรียนการสอนในรูปแบบกลางซึ่งสามารถดำเนินการโดยล่ามเช่น JVM
เช่นไฟล์คลาส Java


ไฟล์ที่ปฏิบัติการได้

ผลิตภัณฑ์ของการเชื่อมโยง proccess เป็นรหัสเครื่องที่สามารถใช้งาน CPU โดยตรง
เช่นไฟล์. exe

โปรดทราบว่าในบางบริบทไฟล์ที่มีคำสั่ง byte-code หรือภาษาสคริปต์อาจถูกพิจารณาว่าสามารถเรียกใช้งานได้


ไฟล์ไลบรารี

รหัสบางส่วนถูกรวบรวมในรูปแบบนี้ด้วยเหตุผลที่แตกต่างกันเช่นการใช้งานซ้ำและใช้ในภายหลังโดยไฟล์ปฏิบัติการ


1
ฉันจะยืนยันว่าการชุมนุมไม่ทั้งหมดเป็นแหล่งที่มาอย่างแท้จริงในความหมายที่เข้มงวดที่สุดของรหัสที่เขียนและ / หรือบำรุงรักษาโดยมนุษย์ มักจะเป็นเครื่องที่สร้างขึ้นจากแหล่งที่มาและไม่เคยมีไว้สำหรับการบริโภคของมนุษย์ (เช่น gcc จริงๆไม่สร้างข้อความ asm ว่าฟีดไปประกอบที่แยกจากกันแทนที่จะมีในตัวประกอบภายในcc1ปฏิบัติการ) ฉันคิดว่าวงกลม asm ควรยื่นออกมาทางด้านซ้ายของวงกลม "ซอร์ส" เนื่องจากบาง asm เป็นเพียง asm ไม่ใช่แหล่งที่มา แน่นอนว่ามันไม่เคยมีรหัสวัตถุแต่ asm บางตัวเป็นขั้นตอนระหว่างทางจากซอร์สโค้ดไปยังอ็อบเจ็กต์ไฟล์
Peter Cordes

@PeterCordes ขอบคุณมากสำหรับความคิดเห็น ฉันไม่รู้ว่าคุณพูดอะไรเกี่ยวกับการทำงานของ gcc อย่างไรก็ตามฉันกลัวว่าฉันจะเห็นด้วยกับคุณอย่างสมบูรณ์ สิ่งที่ฉันหมายถึงคือซอร์สโค้ดเป็นสิ่งที่เขียนโดยใช้ภาษาโปรแกรมที่มนุษย์สามารถอ่านได้ มันอาจหรือไม่อาจเขียนหรือดูแลโดยมนุษย์ ฉันแน่ใจว่าคุณจะต้องระวังของ transcompilers จากมุมมองของคุณคุณจะวางผลิตภัณฑ์ประเภทใดในคอมไพเลอร์? ซอร์สโค้ดหรืออย่างอื่น? โปรดแก้ไขฉันหากฉันผิด ความคิดเห็นเพิ่มเติมยินดีต้อนรับเสมอ
Bertram Gilfoyle

1

สมัชชารหัสจะกล่าวถึงที่นี่

"ภาษาแอสเซมบลีเป็นภาษาระดับต่ำสำหรับการเขียนโปรแกรมคอมพิวเตอร์มันใช้การแสดงสัญลักษณ์ของรหัสเครื่องที่เป็นตัวเลขและค่าคงที่อื่น ๆ ที่จำเป็นสำหรับการเขียนโปรแกรมสถาปัตยกรรม CPU เฉพาะ"

รหัสเครื่องจะกล่าวถึงที่นี่

"รหัสเครื่องหรือภาษาเครื่องเป็นระบบของคำสั่งและข้อมูลที่ดำเนินการโดยตรงโดยหน่วยประมวลผลกลางของคอมพิวเตอร์"

โดยทั่วไปรหัสแอสเซมเบลอร์เป็นภาษาและแปลเป็นรหัสวัตถุ (โค้ดเนมที่ซีพียูทำงาน) โดยแอสเซมเบลอร์ (คล้ายกับคอมไพเลอร์)


1

ฉันคิดว่านี่เป็นความแตกต่างที่สำคัญ

  • ความสามารถในการอ่านของรหัส
  • ควบคุมรหัสของคุณกำลังทำอะไรอยู่

ความสามารถในการอ่านทำให้โค้ดปรับปรุงหรือทดแทนได้ 6 เดือนหลังจากสร้างขึ้นด้วยความพยายามน้อยหากประสิทธิภาพมีความสำคัญคุณอาจต้องการใช้ภาษาระดับต่ำเพื่อกำหนดเป้าหมายฮาร์ดแวร์เฉพาะที่คุณจะใช้งาน ดำเนินการเร็วขึ้น

คอมพิวเตอร์ IMO วันนี้เร็วพอที่จะให้โปรแกรมเมอร์ได้รับการดำเนินการอย่างรวดเร็วด้วย OOP


1

การประกอบเป็นคำอธิบายสั้น ๆ ที่มนุษย์สามารถเข้าใจได้ว่าสามารถแปลโดยตรงไปยังรหัสเครื่องที่ CPU ใช้จริง

ในขณะที่มนุษย์ค่อนข้างเข้าใจได้ Assembler ยังอยู่ในระดับต่ำ ใช้รหัสจำนวนมากเพื่อทำสิ่งที่มีประโยชน์

ดังนั้นเราจึงใช้ภาษาระดับสูงกว่าเช่น C, BASIC, FORTAN (ตกลงฉันรู้ว่าฉันลงวันที่เอง) เมื่อรวบรวมเหล่านี้ผลิตรหัสวัตถุ ภาษาแรกมีภาษาเครื่องเป็นรหัสวัตถุ

หลายภาษาในปัจจุบันเช่น JAVA และ C # มักจะรวบรวมเป็นรหัสไบต์ที่ไม่ใช่รหัสเครื่อง แต่ภาษาที่ตีความได้ง่ายในเวลาทำงานเพื่อสร้างรหัสเครื่อง


ความคิดเห็นของคุณเกี่ยวกับ Java และ C # - ทั้งสองใช้การรวบรวม Just In Time เพื่อให้ไบต์ไม่แปลความหมาย C # (. NET ทั่วไป) คอมไพล์เป็น Intermediate Language (IL) ซึ่งจากนั้น JITed เป็นภาษาเครื่องดั้งเดิมสำหรับ CPU เป้าหมาย
Craig Shearer

-1

ซอร์สไฟล์ของโปรแกรมของคุณจะถูกคอมไพล์เป็นไฟล์ออบเจ็กต์จากนั้นตัวเชื่อมโยงจะลิงก์ไฟล์ออบเจ็กต์เหล่านั้นเข้าด้วยกันเพื่อสร้างไฟล์ปฏิบัติการรวมถึงรหัสเครื่องของสถาปัตยกรรมของคุณ

ทั้งอ็อบเจ็กต์ไฟล์และไฟล์ที่เรียกทำงานได้เกี่ยวข้องกับรหัสเครื่องของสถาปัตยกรรมในรูปแบบของอักขระที่พิมพ์ได้และไม่สามารถพิมพ์ได้เมื่อเปิดโดยตัวแก้ไขข้อความ

อย่างไรก็ตามความแตกต่างระหว่างไฟล์คือไฟล์วัตถุอาจมีการอ้างอิงภายนอกที่ไม่ได้แก้ไข (เช่นprintfเป็นต้น) ดังนั้นจึงอาจจำเป็นต้องเชื่อมโยงกับไฟล์วัตถุอื่น ๆ .. กล่าวคือการอ้างอิงภายนอกที่ไม่ได้แก้ไขจำเป็นต้องได้รับการแก้ไขเพื่อให้ได้ไฟล์ปฏิบัติการที่เรียกใช้ได้ดีโดยเชื่อมโยงกับไฟล์วัตถุอื่นเช่นไลบรารีรันไทม์ C / C ++ .

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.