มีกรณีที่ชาญฉลาดของการแก้ไขโค้ดรันไทม์หรือไม่?


119

คุณนึกถึงการใช้ (สมาร์ท) ที่ถูกต้องตามกฎหมายสำหรับการแก้ไขโค้ดรันไทม์ (โปรแกรมแก้ไขโค้ดของตัวเองในขณะรันไทม์) หรือไม่?

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

สิ่งที่ฉันคิดได้คือการเพิ่มประสิทธิภาพรันไทม์บางประเภทที่จะลบหรือเพิ่มโค้ดบางอย่างโดยรู้บางอย่างในรันไทม์ซึ่งไม่สามารถทราบได้ในเวลาคอมไพล์


8
ในสถาปัตยกรรมสมัยใหม่มันรบกวนการแคชและไปป์ไลน์คำสั่งไม่ดี: การแก้ไขโค้ดด้วยตนเองจะไม่แก้ไขแคชดังนั้นคุณจะต้องมีอุปสรรคและสิ่งนี้อาจทำให้โค้ดของคุณช้า และคุณไม่สามารถแก้ไขโค้ดที่มีอยู่แล้วในขั้นตอนคำสั่งได้ ดังนั้นการเพิ่มประสิทธิภาพใด ๆ ที่ขึ้นอยู่กับโค้ดที่ปรับเปลี่ยนด้วยตนเองจะต้องดำเนินการก่อนที่โค้ดจะถูกเรียกใช้เพื่อให้มีผลกระทบเชิงประสิทธิภาพที่เหนือกว่าการตรวจสอบรันไทม์
Alexandre C.

7
@Alexandre: เป็นเรื่องปกติสำหรับการแก้ไขโค้ดด้วยตนเองเพื่อทำการแก้ไขที่ไม่ค่อยมีความแตกต่างกัน (เช่นหนึ่งครั้งสองครั้ง) แม้ว่าจะมีการดำเนินการตามจำนวนครั้งโดยพลการดังนั้นค่าใช้จ่ายเพียงครั้งเดียวอาจไม่มีนัยสำคัญ
Tony Delroy

7
ไม่แน่ใจว่าเหตุใดจึงติดแท็ก C หรือ C ++ เนื่องจากไม่มีกลไกใด ๆ สำหรับสิ่งนี้
MSalters

4
@Alexandre: Microsoft Office เป็นที่รู้กันว่าทำอย่างนั้น ด้วยเหตุนี้ (?) โปรเซสเซอร์ x86 ทั้งหมดจึงมีการสนับสนุนที่ดีเยี่ยมสำหรับการแก้ไขโค้ดด้วยตนเอง ในโปรเซสเซอร์อื่น ๆ จำเป็นต้องมีการซิงโครไนซ์ที่มีราคาแพงซึ่งทำให้สิ่งทั้งหมดน่าสนใจน้อยลง
Mackie Messer

3
@Cawas: โดยปกติซอฟต์แวร์อัปเดตอัตโนมัติจะดาวน์โหลดแอสเซมบลีและ / หรือไฟล์ปฏิบัติการใหม่และเขียนทับชุดที่มีอยู่ จากนั้นจะรีสตาร์ทซอฟต์แวร์ นี่คือสิ่งที่ firefox, adobe และอื่น ๆ ทำ โดยทั่วไปการแก้ไขด้วยตนเองหมายความว่าในระหว่างรหัสรันไทม์จะถูกเขียนซ้ำในหน่วยความจำโดยแอปพลิเคชันเนื่องจากพารามิเตอร์บางตัวและไม่จำเป็นต้องกลับไปที่ดิสก์ ตัวอย่างเช่นอาจเพิ่มประสิทธิภาพเส้นทางรหัสทั้งหมดหากสามารถตรวจจับได้อย่างชาญฉลาดเส้นทางเหล่านั้นจะไม่ถูกใช้ในระหว่างการรันเฉพาะนี้เพื่อเร่งความเร็วในการดำเนินการ
NotMe

คำตอบ:


117

มีหลายกรณีที่ถูกต้องสำหรับการแก้ไขโค้ด การสร้างรหัสในขณะทำงานจะมีประโยชน์สำหรับ:

  • เครื่องเสมือนบางเครื่องใช้การคอมไพล์ JITเพื่อปรับปรุงประสิทธิภาพ
  • การสร้างฟังก์ชันพิเศษได้ทันทีเป็นเรื่องปกติในคอมพิวเตอร์กราฟิก ดูเช่น Rob Pike และ Bart Locanthi และ John Reiser Hardware Software Tradeoffs สำหรับกราฟิกบิตแมปบน Blit (1984)หรือโพสต์นี้(2006)โดย Chris Lattner เกี่ยวกับการใช้ LLVM ของ Apple สำหรับความเชี่ยวชาญด้านโค้ดรันไทม์ในสแต็ก OpenGL
  • ในบางกรณีซอฟต์แวร์ใช้เทคนิคที่เรียกว่าแทรมโพลีนซึ่งเกี่ยวข้องกับการสร้างโค้ดแบบไดนามิกบนสแต็ก (หรือที่อื่น) ตัวอย่างคือฟังก์ชันซ้อนของ GCC และกลไกสัญญาณของ Unices บางแห่ง

บางครั้งโค้ดจะถูกแปลเป็นโค้ดที่รันไทม์ (เรียกว่าการแปลไบนารีแบบไดนามิก ):

  • อีมูเลเตอร์เช่นRosettaของ Apple ใช้เทคนิคนี้เพื่อเร่งความเร็วในการจำลอง อีกตัวอย่างหนึ่งคือ Transmeta ของซอฟต์แวร์ morphing รหัส
  • ดีบักเกอร์และผู้สร้างโปรไฟล์ที่ซับซ้อนเช่นValgrindหรือPinใช้เพื่อเป็นเครื่องมือในการใช้รหัสของคุณในขณะที่กำลังดำเนินการ
  • ก่อนที่จะมีการสร้างส่วนขยายให้กับชุดคำสั่ง x86 ซอฟต์แวร์เวอร์ชวลไลเซชันเช่น VMWare ไม่สามารถรันโค้ด x86 ที่มีสิทธิพิเศษภายในเครื่องเสมือนได้โดยตรง แต่ต้องแปลคำแนะนำที่มีปัญหาในทันทีให้เป็นโค้ดที่กำหนดเองที่เหมาะสมกว่า

การปรับเปลี่ยนโค้ดสามารถใช้เพื่อหลีกเลี่ยงข้อ จำกัด ของชุดคำสั่ง:

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

กรณีอื่น ๆ ของการแก้ไขโค้ด:

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

10
รายการนี้ดูเหมือนจะรวมตัวอย่างของโค้ดที่แก้ไขตัวเองและโค้ดที่แก้ไขโค้ดอื่น ๆ เช่นตัวเชื่อมโยง
AShelly

6
@AShelly: ถ้าคุณพิจารณาว่าตัวเชื่อมโยง / ตัวโหลดแบบไดนามิกเป็นส่วนหนึ่งของโค้ดมันจะแก้ไขตัวเอง พวกเขาอาศัยอยู่ในพื้นที่ที่อยู่เดียวกันดังนั้นฉันคิดว่านั่นเป็นมุมมองที่ถูกต้อง
Mackie Messer

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

35

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


5
การอ่านที่น่าสนใจคือไมเคิล Abrash 3 ส่วนบทความ Pixomatic ใน DDJ: drdobbs.com/architecture-and-design/184405765 , drdobbs.com/184405807 , drdobbs.com/184405848 ลิงค์ที่สอง (Part2) พูดถึงเครื่องเชื่อมรหัส Pixomatic สำหรับท่อพิกเซล
typo.pl

1
บทความที่ดีมากในหัวข้อนี้ ตั้งแต่ปี 1984 แต่ก็ยังอ่านได้ดี: Rob Pike และ Bart Locanthi และ John Reiser ฮาร์ดแวร์ซอฟท์แว Tradeoffs สำหรับ Bitmap กราฟิกบน blit
Mackie Messer

5
Charles Petzold อธิบายตัวอย่างหนึ่งของประเภทนี้ในหนังสือชื่อ "Beautiful Code": amazon.com/Beautiful-Code-Leading-Programmers-Practice/dp/…
Nawaz

3
คำตอบนี้พูดถึงการสร้างโค้ด แต่คำถามคือถามเกี่ยวกับการแก้ไขโค้ด ...
Timwi

3
@ Timwi - มันแก้ไขโค้ด แทนที่จะจัดการโซ่ขนาดใหญ่ของ if มันจะแยกวิเคราะห์รูปร่างเพียงครั้งเดียวและเขียนตัวแสดงภาพใหม่ดังนั้นจึงตั้งค่าสำหรับประเภทของรูปร่างที่ถูกต้องโดยไม่ต้องตรวจสอบทุกครั้ง สิ่งที่น่าสนใจคือตอนนี้เป็นเรื่องธรรมดาสำหรับโค้ด opencl - เนื่องจากมันถูกรวบรวมได้ทันทีคุณสามารถเขียนใหม่สำหรับกรณีเฉพาะที่รันไทม์
Martin Beckett

23

เหตุผลหนึ่งที่ถูกต้องคือเนื่องจากชุดคำสั่ง asm ไม่มีคำสั่งที่จำเป็นซึ่งคุณสามารถสร้างขึ้นเองได้ ตัวอย่าง: บน x86 ไม่มีวิธีสร้างอินเทอร์รัปต์ให้กับตัวแปรในรีจิสเตอร์ (เช่นทำการขัดจังหวะด้วยหมายเลขอินเทอร์รัปต์ใน ax) อนุญาตให้ใช้เฉพาะหมายเลข const ที่เข้ารหัสใน opcode เท่านั้น ด้วยการปรับรหัสด้วยตนเองเราสามารถเลียนแบบพฤติกรรมนี้ได้


พอใช้. มีการใช้เทคนิคนี้หรือไม่? ดูเหมือนอันตราย
Alexandre C.

4
@Alexandre C: ถ้าฉันจำไลบรารีรันไทม์จำนวนมากที่ถูกต้อง (C, Pascal, ... ) ต้อง DOS คูณฟังก์ชันเพื่อทำการโทรขัดจังหวะ เนื่องจากฟังก์ชันดังกล่าวได้รับหมายเลขอินเทอร์รัปต์เป็นพารามิเตอร์ที่คุณต้องจัดหาฟังก์ชันดังกล่าว (แน่นอนว่าหากตัวเลขเป็นค่าคงที่คุณสามารถสร้างรหัสที่ถูกต้องได้ แต่ไม่รับประกัน) และไลบรารีทั้งหมดก็นำไปใช้กับรหัสการแก้ไขตัวเอง
flolo

คุณสามารถใช้เคสสวิตช์เพื่อทำได้โดยไม่ต้องแก้ไขโค้ด การลดขนาดคือรหัสผลลัพธ์จะใหญ่ขึ้น
phuclv

17

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


1
ดีมากโดยเฉพาะอย่างยิ่งหากหลีกเลี่ยงการล็อก / ปลดล็อก mutex
Tony Delroy

2
จริงๆ? วิธีนี้สำหรับโค้ดที่ใช้ ROM หรือสำหรับโค้ดที่ดำเนินการในส่วนของโค้ดที่ป้องกันการเขียน
Ira Baxter

1
@Ira Baxter: คอมไพเลอร์ใด ๆ ที่ปล่อยโค้ดที่ย้ายตำแหน่งได้จะรู้ว่าส่วนของโค้ดนั้นสามารถเขียนได้อย่างน้อยในระหว่างการเริ่มต้น ดังนั้นคำสั่ง "บางคอมไพเลอร์ใช้มัน" ยังคงเป็นไปได้
MSalters

17

มีหลายกรณี:

  • ไวรัสมักใช้โค้ดที่แก้ไขด้วยตนเองเพื่อ "ลดความยุ่งเหยิง" โค้ดของพวกเขาก่อนที่จะดำเนินการ แต่เทคนิคนั้นยังมีประโยชน์ในการทำวิศวกรรมย้อนกลับการแคร็กและการแฮกเกอร์ที่ไม่ต้องการ
  • ในบางกรณีอาจมีจุดใดจุดหนึ่งระหว่างรันไทม์ (เช่นทันทีหลังจากอ่านไฟล์กำหนดค่า) เมื่อทราบว่า - ตลอดอายุการใช้งานที่เหลือของกระบวนการสาขาใดสาขาหนึ่งจะถูกนำมาใช้เสมอหรือไม่เคย: แทนที่จะไม่จำเป็น การตรวจสอบตัวแปรบางตัวเพื่อกำหนดวิธีที่จะแยกสาขาคำสั่งของสาขาเองสามารถแก้ไขได้ตามนั้น
    • เช่นอาจเป็นที่ทราบกันดีว่าจะมีการจัดการประเภทที่ได้รับมาเพียงประเภทเดียวเท่านั้นดังนั้นการจัดส่งเสมือนสามารถถูกแทนที่ด้วยการโทรเฉพาะ
    • เมื่อตรวจพบว่าฮาร์ดแวร์ใดพร้อมใช้งานการใช้รหัสที่ตรงกันอาจเป็นฮาร์ดโค้ด
  • โค้ดที่ไม่จำเป็นสามารถแทนที่ได้ด้วยคำสั่งแบบไม่ใช้งานหรือข้ามไปเลยหรือให้โค้ดถัดไปเลื่อนเข้าที่โดยตรง (ง่ายกว่าถ้าใช้ opcodes ที่ไม่ขึ้นกับตำแหน่ง)
  • โค้ดที่เขียนขึ้นเพื่ออำนวยความสะดวกในการดีบักของตัวเองอาจฉีดคำสั่งกับดัก / สัญญาณ / ขัดจังหวะที่คาดว่าโดยดีบักเกอร์ในตำแหน่งยุทธศาสตร์
  • นิพจน์เพรดิเคตบางอย่างที่ขึ้นอยู่กับการป้อนข้อมูลของผู้ใช้อาจถูกรวบรวมเป็นโค้ดเนทีฟโดยไลบรารี
  • การแทรกการดำเนินการง่ายๆที่ไม่สามารถมองเห็นได้จนกว่าจะรันไทม์ (เช่นจากไลบรารีที่โหลดแบบไดนามิก) ...
  • เพิ่มขั้นตอนการวัดด้วยตนเอง / การทำโปรไฟล์ตามเงื่อนไข
  • แคร็กอาจใช้เป็นไลบรารีที่แก้ไขโค้ดที่โหลดได้ (ไม่ใช่การแก้ไขแบบ "ตัวเอง" แต่ต้องใช้เทคนิคและสิทธิ์เดียวกัน)
  • ...

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

จาก Wikipedia:

ซอฟต์แวร์แอพพลิเคชั่นที่ทำงานภายใต้ระบบปฏิบัติการที่มีการรักษาความปลอดภัย W ^ X ที่เข้มงวดไม่สามารถดำเนินการคำสั่งในหน้าที่อนุญาตให้เขียนได้เฉพาะระบบปฏิบัติการเท่านั้นที่ได้รับอนุญาตให้เขียนคำสั่งลงในหน่วยความจำและดำเนินการตามคำสั่งเหล่านั้นในภายหลัง

บนระบบปฏิบัติการดังกล่าวแม้แต่โปรแกรมเช่น Java VM ก็ต้องมีสิทธิ์รูท / ผู้ดูแลระบบเพื่อรันโค้ด JIT (ดูhttp://en.wikipedia.org/wiki/W%5EXสำหรับรายละเอียดเพิ่มเติม)


2
คุณไม่จำเป็นต้องมีสิทธิ์รูทสำหรับการแก้ไขโค้ดด้วยตนเอง Java VM ก็ไม่เหมือนกัน
Mackie Messer

ฉันไม่รู้ว่าระบบปฏิบัติการบางระบบเข้มงวดมาก แต่มันก็สมเหตุสมผลในบางแอพพลิเคชั่น อย่างไรก็ตามฉันสงสัยว่าการรัน Java ด้วยสิทธิ์รูทช่วยเพิ่มความปลอดภัยได้จริงหรือไม่ ...
Mackie Messer

@Mackie: ฉันคิดว่ามันจะต้องลดลง แต่บางทีมันอาจตั้งค่าสิทธิ์หน่วยความจำบางอย่างได้จากนั้นเปลี่ยน uid ที่มีประสิทธิภาพกลับเป็นบัญชีผู้ใช้บางส่วน ... ?
Tony Delroy

ใช่ฉันคาดหวังว่าพวกเขาจะมีกลไกแบบละเอียดเพื่อให้สิทธิ์ในรูปแบบการรักษาความปลอดภัยที่เข้มงวด
Mackie Messer

15

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

ใช่นั่นคือตัวอย่างของการเพิ่มประสิทธิภาพรันไทม์


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

@ Alexandre C. : คุณอาจสามารถกำจัดการตรวจสอบตัวชี้ว่างได้ด้วยวิธีนั้น บ่อยครั้งที่ผู้โทรเห็นได้ชัดว่าอาร์กิวเมนต์นั้นถูกต้อง
MSalters

@ อเล็กซานเดอร์: คุณสามารถอ่านงานวิจัยได้ที่ลิงค์ ฉันคิดว่าพวกเขามีสปีดอัพที่น่าประทับใจพอสมควรและนั่นน่าจะเป็นประเด็น: -}
Ira Baxter

2
สำหรับ syscalls ที่ค่อนข้างไม่สำคัญและไม่ผูกมัด I / O การประหยัดมีความสำคัญ ตัวอย่างเช่นหากคุณกำลังเขียน deamon สำหรับ Unix คุณจะมี syscall ของแผ่นหม้อไอน้ำจำนวนมากเพื่อตัดการเชื่อมต่อ stdio ตั้งค่าตัวจัดการสัญญาณต่างๆ ฯลฯ หากคุณรู้ว่าพารามิเตอร์ของการโทรเป็นค่าคงที่และ ผลลัพธ์จะเหมือนกันเสมอ (เช่นการปิด stdin) โค้ดจำนวนมากที่คุณเรียกใช้ในกรณีทั่วไปนั้นไม่จำเป็น
Mark Bessey

1
หากคุณอ่านวิทยานิพนธ์บทที่ 8 จะมีตัวเลขที่น่าประทับใจเกี่ยวกับ I / O แบบเรียลไทม์ที่ไม่สำคัญสำหรับการได้มาซึ่งข้อมูล จำได้ว่านี่เป็นวิทยานิพนธ์กลางทศวรรษ 1980 และเครื่องที่เขาใช้คือ 10? Mhz 68000 เขาสามารถใช้ซอฟต์แวร์เพื่อจับข้อมูลเสียงคุณภาพซีดี (44,000 ตัวอย่างต่อวินาที) ด้วยซอฟต์แวร์เก่าธรรมดา เขาอ้างว่าซันเวิร์คสเตชั่น (ยูนิกซ์คลาสสิก) สามารถตีได้เพียง 1/5 ของอัตรานั้น ฉันเป็นคนเขียนโค้ดภาษาแอสเซมบลีเก่า ๆ ในสมัยนั้นและมันก็น่าตื่นเต้นทีเดียว
Ira Baxter

9

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

ประเด็นของฉันการแก้ไขโค้ดด้วยตนเองอาจเป็นเรื่องที่น่ารังเกียจอย่างยิ่งในการทดสอบ / ดีบักและมักจะมีสมมติฐานที่ซ่อนอยู่เกี่ยวกับพฤติกรรมของเครื่อง (ไม่ว่าจะเป็นฮาร์ดแวร์หรือเสมือน) ยิ่งไปกว่านั้นระบบไม่สามารถแชร์โค้ดเพจระหว่างเธรด / กระบวนการต่างๆที่ดำเนินการบนเครื่องมัลติคอร์ (ตอนนี้) สิ่งนี้เอาชนะประโยชน์หลายอย่างของหน่วยความจำเสมือน ฯลฯ นอกจากนี้ยังจะทำให้การเพิ่มประสิทธิภาพสาขาที่ทำในระดับฮาร์ดแวร์เป็นโมฆะ

(หมายเหตุ - ฉันไม่ได้รวม JIT ไว้ในหมวดหมู่ของรหัสที่ปรับเปลี่ยนได้เอง JIT กำลังแปลจากการแสดงรหัสหนึ่งเป็นการแสดงทางเลือก แต่ไม่ได้แก้ไขรหัส)

สรุปแล้วมันเป็นแค่ความคิดที่ไม่ดี - เรียบร้อยจริงๆคลุมเครือ แต่แย่จริงๆ

แน่นอน - ถ้าทั้งหมดที่คุณมีคือ 8080 และ ~ 512 ไบต์ของหน่วยความจำคุณอาจต้องใช้วิธีปฏิบัติดังกล่าว


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

ซีพียู x86 ที่ทันสมัยมีการตรวจจับ SMC ที่แข็งแกร่งกว่าที่จำเป็นบนกระดาษ: การสังเกตคำสั่งที่ค้างในการดึงข้อมูลบน x86 ด้วยรหัสที่แก้ไขเอง และในซีพียูที่ไม่ใช่ x86 ส่วนใหญ่ (เช่น ARM) แคชคำสั่งไม่สอดคล้องกับแคชข้อมูลดังนั้นจึงจำเป็นต้องมีการล้าง / ซิงค์ด้วยตนเองก่อนที่ไบต์ที่จัดเก็บใหม่จะสามารถดำเนินการตามคำแนะนำได้อย่างน่าเชื่อถือ community.arm.com/processors/b/blog/posts/… . ไม่ว่าจะด้วยวิธีใดก็ตามประสิทธิภาพของ SMC นั้นแย่มากสำหรับซีพียูรุ่นใหม่เว้นแต่คุณจะแก้ไขเพียงครั้งเดียวและเรียกใช้หลายครั้ง
Peter Cordes

7

จากมุมมองของเคอร์เนลระบบปฏิบัติการทุก Just In Time Compiler และ Linker Runtime จะทำการแก้ไขข้อความโปรแกรมด้วยตนเอง ตัวอย่างที่โดดเด่นคือ V8 ECMA Script Interpreter ของ Google


5

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


5

คุณรู้ไหมว่าเกาลัดรุ่นเก่าไม่มีความแตกต่างทางตรรกะระหว่างฮาร์ดแวร์และซอฟต์แวร์ ... เราสามารถพูดได้ว่าไม่มีความแตกต่างทางตรรกะระหว่างรหัสและข้อมูล

โค้ดที่ปรับเปลี่ยนได้เองคืออะไร? โค้ดที่ใส่ค่าในสตรีมการดำเนินการเพื่อให้สามารถ imterpreted ไม่ใช่เป็นข้อมูล แต่เป็นคำสั่ง แน่นอนว่ามีมุมมองทางทฤษฎีในภาษาที่ใช้งานได้ว่าไม่มีความแตกต่างกัน ฉันกำลังบอกว่าใน e สามารถทำได้อย่างตรงไปตรงมาในภาษาที่จำเป็นและคอมไพเลอร์ / ล่ามโดยไม่ต้องสันนิษฐานว่ามีสถานะเท่าเทียมกัน

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

ดังนั้นแม้ในกรณีปกติที่คอมไพเลอร์สร้างพื้นที่โค้ดและอ้างถึงพื้นที่ข้อมูลที่แยกจากกันโดยสิ้นเชิง (ฮีป) ก็ยังสามารถแก้ไขข้อมูลเพื่อเปลี่ยนเส้นทางการดำเนินการอย่างชัดเจนได้


4
ไม่มีความแตกต่างทางตรรกะจริง ยังไม่เห็นวงจรรวมที่ปรับเปลี่ยนได้เองมากเกินไป
Ira Baxter

@ มิทช์ IMO การเปลี่ยนเส้นทางผู้บริหารไม่มีส่วนเกี่ยวข้องกับการแก้ไขโค้ด (ด้วยตนเอง) นอกจากนี้คุณสับสนข้อมูลกับข้อมูล ฉันไม่สามารถตอบความคิดเห็นของปีในการตอบกลับของฉันใน LSE b / c ฉันถูกแบนแบบฟอร์มที่นั่นตั้งแต่เดือนกุมภาพันธ์เป็นเวลา 3 ปี (1,000 วัน) สำหรับการแสดงใน meta-LSE pov ของฉันที่ชาวอเมริกันและชาวอังกฤษไม่ได้เป็นเจ้าของภาษาอังกฤษ
Gennady Vanin ГеннадийВанин

4

ฉันได้ติดตั้งโปรแกรมโดยใช้วิวัฒนาการเพื่อสร้างอัลกอริทึมที่ดีที่สุด มันใช้รหัสที่ปรับเปลี่ยนได้เองเพื่อแก้ไขพิมพ์เขียวของดีเอ็นเอ


2

กรณีการใช้งานหนึ่งคือไฟล์ทดสอบ EICARซึ่งเป็นไฟล์ COM ปฏิบัติการ DOS ที่ถูกต้องสำหรับการทดสอบโปรแกรมป้องกันไวรัส

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

ต้องใช้การแก้ไขโค้ดด้วยตนเองเนื่องจากไฟล์ปฏิบัติการต้องมีเฉพาะอักขระ ASCII ที่พิมพ์ได้ / พิมพ์ได้ในช่วง [21h-60h, 7Bh-7Dh] ซึ่ง จำกัด จำนวนคำสั่งที่เข้ารหัสได้อย่างมาก

มีการอธิบายรายละเอียดที่นี่


นอกจากนี้ยังใช้สำหรับการจัดส่งการดำเนินการจุดลอยตัวใน DOS

คอมไพเลอร์บางตัวจะปล่อยCD xxxx ตั้งแต่ 0x34-0x3B ในตำแหน่ง x87 คำแนะนำจุดลอยตัว เนื่องจากCDเป็น opcode สำหรับintคำสั่งมันจะข้ามไปที่ interrupt 34h-3Bh และเลียนแบบคำสั่งนั้นในซอฟต์แวร์หากไม่มีตัวประมวลผลร่วม x87 มิฉะนั้นตัวจัดการขัดจังหวะจะแทนที่ 2 ไบต์เหล่านั้น9B Dxเพื่อให้การดำเนินการในภายหลังถูกจัดการโดยตรงโดย x87 โดยไม่มีการจำลอง

โปรโตคอลสำหรับการจำลองจุดลอยตัว x87 ใน MS-DOS คืออะไร?


1

Linux Kernelมีโมดูลเคอร์เนลที่ใส่ได้ซึ่งทำเพียงแค่ว่า

Emacs ยังมีความสามารถนี้และฉันใช้มันตลอดเวลา

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


4
แทบจะไม่ การมีไลบรารีที่โหลดได้แบบไดนามิกซึ่งไม่ใช่ถิ่นที่อยู่เสมอไปมีส่วนเกี่ยวข้องกับโค้ดที่ปรับเปลี่ยนได้เอง
Dov

1

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


0

สถานการณ์ที่สามารถใช้เป็นโปรแกรมการเรียนรู้ เพื่อตอบสนองต่อการป้อนข้อมูลของผู้ใช้โปรแกรมจะเรียนรู้อัลกอริทึมใหม่:

  1. มันค้นหาฐานรหัสที่มีอยู่สำหรับอัลกอริทึมที่คล้ายกัน
  2. หากไม่มีอัลกอริทึมที่คล้ายกันอยู่ในโค้ดเบสโปรแกรมจะเพิ่มอัลกอริทึมใหม่
  3. หากมีอัลกอริทึมที่คล้ายกันโปรแกรม (อาจได้รับความช่วยเหลือจากผู้ใช้) จะปรับเปลี่ยนอัลกอริทึมที่มีอยู่เพื่อให้สามารถตอบสนองทั้งวัตถุประสงค์เก่าและวัตถุประสงค์ใหม่

มีคำถามว่าจะทำอย่างไรใน Java: อะไรคือความเป็นไปได้สำหรับการแก้ไขโค้ด Java ด้วยตนเอง?


-1

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

ฉันไม่ได้เป็นผู้เชี่ยวชาญ แต่ได้รับเสียงกระเพื่อมคนหนึ่งพูดถึงเรื่องนี้! มีเหตุผลที่พวกเขากล่าวว่า Lisp เป็นภาษาที่ทรงพลังที่สุดและคนที่ฉลาดไม่ว่าพวกเขาจะพูดถูก


2
นั่นเป็นการสร้างโค้ดดัดแปลงตัวเองจริง ๆ หรือเป็นเพียงตัวประมวลผลล่วงหน้าที่ทรงพลังกว่า (ตัวที่จะสร้างฟังก์ชัน)?
Brendan Long

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