กว่าจะมาถึงฟังก์ชัน main ต้องทำอะไรบ้างนะ?

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

สงสัยจริง ๆ ก่อนฟังก์ชัน main มีอะไร?

การเขียนโปรแกรมโดยใช้ภาษา C บน Windows หรือ Linux/UNIX จะเขียนโปรแกรมตั้งแต่ในฟังก์ชัน main เป็นต้นไป อย่างไรก็ตาม ดังที่กล่าวขั้นต้นโปรแกรมไม่ได้เริ่มต้นด้วยฟังก์ชัน main ก่อนหน้าฟังก์ชัน main นั้นจะมีสิ่งที่เรียกว่า startup routine อยู่ครับ

ในเชิงงาน embedded หรือ งานที่เกี่ยวข้องกับบอร์ด microcontroller จำเป็นต้องทำความเข้าใจ startup routine เพื่อให้โปรแกรมทำงาน อีกทั้งในบางครั้งการดีบักโปรแกรมโดยที่ไม่รู้ว่า startup routine มีการทำงานอะไรอยู่อาจไม่ใช่เรื่องดีนักยิ่งเป็นงานที่เกี่ยวข้องกับ microcontroller ด้วย

 

เมื่อเปิดเครื่องเราก็จะเรียก startup routine ขึ้นมายังไงล่ะ

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

 อ้างอิง URL

เมื่ออุปกรณ์หรือบอร์ดเริ่มทำงาน กล่าวคือ เมื่อเปิดเครื่องหรือกดปุ่มรีเซ็ต ตัว processor จะถูกบังคับให้รีเซ็ต ((1) ในรูปข้างต้น) สิ่งนี้จะเรียกว่าการขัดจังหวะ (interrupt) เป็นการขัดจังหวะการทำงานคำสั่งบังคับสำหรับให้ processor นั้น “ทำงานจากสถานะเริ่มต้น ไม่ว่าสถานะปัจจุบันจะเป็นอย่างไร” เมื่อการขัดจังหวะแบบบังคับรีเซ็ตเข้ามา processor จะอ่านข้อมูลจากในแอดเดรสที่ถูกกำหนดไว้ (กำหนดให้เป็นรีเซ็ตในพื้นที่ memory พิเศษของบอร์ดนั้น ๆ เราจะเรียกว่า reset vector) โดยข้อมูลการทำงานใน reset vector จะแตกต่างกันไปตาม processor ที่ใช้ 

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

เอ๊ะ! แล้ว startup routine ข้างใน มีอะไรบ้างนะ ?

startup routine จะทำงานเริ่มต้นก่อนการรันโปรแกรม C ขึ้นมา เมื่อพัฒนาโปรแกรมแอปพลิเคชันบน Windows หรือ Linux/UNIX เพื่อน ๆ จะไม่รับรู้ถึงการมีอยู่ของ startup routine เลย เนื่องจากสภาพแวดล้อมการทำงานของโปรแกรมจะเหมือนกันเสมอ (ไม่จำเป็นต้องเปลี่ยนในแต่ละครั้ง) และ compiler C จะเชื่อมโยง startup routine เข้ากับระบบโดยอัตโนมัติ (บนระบบ UNIX นั้น startup routine คือ ไลบรารีมาตรฐาน ซึ่งอยู่ด้วยกันภายใต้ชื่อ crt0.o) 

 อย่างไรก็ตามในเชิง embedded นั้นมีอุปกรณ์ต่าง ๆ ที่เชื่อมอยู่ หรือ memory ที่มีขนาดที่หลากหลายมากหน้าหลายตาแตกต่างกันไปค่อนข้างเยอะ การประมวลผลเองก็จะแตกต่างกันไปตามอุปกรณ์ 

 นอกจากนี้ วิธีการ initialize ของอุปกรณ์ยังแตกต่างกันไปตาม processor ที่ใช้ ดังนั้น startup routine จึงมีความสำคัญอย่างมาก อย่างที่บอกกับผู้อ่านไปข้างต้นว่าเราไม่สามารถสร้างโปรแกรม embedded ได้หากเรายังไม่เข้าใจ startup routine ครับ

 เรามาดูกันดีกว่าครับว่า startup routine นั้นทำอะไรกันบ้าง

    1. การตั้งค่า stack

    2. การตั้งค่าข้อมูลที่จำเป็นสำหรับการทำงานของโปรแกรม

    3. ถ่ายโอนข้อมูลโปรแกรมจากพื้นที่ ROM ไปยังพื้นที่ RAM

        3.1 การเคลียร์พื้นที่ memory ที่ไม่ได้มีค่าเริ่มต้นเป็น 0

    4. การตั้งค่าโหมดการทำงานของไมโครคอมพิวเตอร์

    5. การเริ่มต้นของ registers ต่าง ๆ สำหรับการใช้ฟังก์ชันที่มีอยู่ในไมโครคอมพิวเตอร์

    6. การเริ่มต้นทำงานฮาร์ดแวร์

    7. การตรวจสอบสถานะฮาร์ดแวร์

stack เป็นพื้นที่ RAM สำหรับตัวแปรที่จำเป็นเมื่อเรียกใช้โปรแกรม อีกทั้งตัว startup routine มักจะกำหนดใช้พื้นที่ stack เช่นกัน นอกจาก stack แล้วค่าคงที่และตัวแปร global ยังจำเป็นสำหรับการทำงานของโปรแกรม สิ่งเหล่านี้จะต้องเริ่มต้นหรือเคลียร์ค่าเป็น 0

ต่อมาค่าคงที่บางค่าอาจต้องอ้างอิงจาก ROM และคัดลอกไปยัง RAM นั่นคือการถ่ายโอนข้อมูลค่าจากพื้นที่ ROM ไปยังพื้นที่ RAM

จาก (4) ในรูปข้างต้น startup routine ถูกเขียนขึ้นเพื่อเรียกใช้ฟังก์ชันหลักของโปรแกรมภาษา C โดยตรง แต่เมื่อใช้ไลบรารีมาตรฐานภาษา C จะต้องดำเนินการ Initialization ไลบรารีมาตรฐานด้วย 

นอกเหนือจากการรันซอฟต์แวร์เองแล้ว จำเป็นต้องมีการเริ่มต้นเพื่อใช้ processor และฮาร์ดแวร์อื่น ๆ การเริ่มต้นเหล่านี้ถูกเข้ารหัส ซึ่งจะต้องอ้างอิงกับเอกสารของ processor และฮาร์ดแวร์นั้น ๆ

 หลังจากการเตรียมการเบื้องต้นเหล่านี้เสร็จเรียบร้อยแล้ว ฟังก์ชัน main ของโปรแกรมก็จะถูกเรียกขึ้นมานั่นเองครับ ((4) ในรูปข้างต้น)

 

สำหรับบทความ ก็จะขอจบเพียงเท่านี้นะครับ ขอขอบคุณบทความดีๆจาก http://www.kumikomi.net/ ด้วยครับ

Reference : http://www.kumikomi.net/archives/2003/05/10kumi.php?page=7