นอกเหนือจากคำตอบอื่น ๆ ฉันต้องการเพิ่มเมื่อแกะสลัก RAM ระหว่างพื้นที่สแต็คและพื้นที่กองที่คุณต้องพิจารณาพื้นที่สำหรับข้อมูลคงที่ไม่คงที่ (เช่นไฟล์กลม, สถิติการทำงานและโปรแกรมทั้ง กลมจากมุมมอง C และอื่น ๆ อาจสำหรับ C ++)
การจัดสรรสแต็ค / ฮีปทำงานอย่างไร
เป็นที่น่าสังเกตว่าไฟล์ชุดประกอบเริ่มต้นเป็นวิธีหนึ่งในการกำหนดภูมิภาค Toolchain (ทั้งสภาพแวดล้อมการสร้างของคุณและสภาพแวดล้อมแบบรันไทม์) ส่วนใหญ่ใส่ใจเกี่ยวกับสัญลักษณ์ที่กำหนดจุดเริ่มต้นของสแต็กสเปซ (ใช้เพื่อเก็บตัวชี้สแต็กเริ่มต้นในตารางเวกเตอร์) และจุดเริ่มต้นและจุดสิ้นสุดของพื้นที่ฮีป ตัวจัดสรรหน่วยความจำซึ่งโดยทั่วไปแล้วจะใช้โดย libc ของคุณ)
ในตัวอย่างของ OP มีการกำหนดสัญลักษณ์เพียง 2 ตัวขนาดของสแต็กที่ 1kiB และขนาดของฮีปที่ 0B ค่าเหล่านี้จะถูกนำไปใช้ที่อื่นเพื่อสร้างพื้นที่สแต็กและฮีปจริง
ในตัวอย่าง @Gilles ขนาดจะถูกกำหนดและใช้ในไฟล์ชุดประกอบเพื่อตั้งค่าพื้นที่สแต็กเริ่มต้นทุกที่และขนาดที่ยั่งยืนโดยระบุสัญลักษณ์ Stack_Mem และตั้งป้ายกำกับ __initial_sp ที่ส่วนท้าย ในทำนองเดียวกันสำหรับฮีปซึ่งพื้นที่คือสัญลักษณ์ Heap_Mem (ขนาด 0.5kiB) แต่มีป้ายกำกับที่จุดเริ่มต้นและสิ้นสุด (__heap_base และ __heap_limit)
สิ่งเหล่านี้ได้รับการประมวลผลโดย linker ซึ่งจะไม่จัดสรรอะไรภายในพื้นที่สแต็กและพื้นที่ฮีปเนื่องจากหน่วยความจำนั้นถูกครอบครอง (โดยสัญลักษณ์ Stack_Mem และ Heap_Mem) แต่สามารถวางความทรงจำเหล่านั้นและกลมทั้งหมดได้ทุกที่ที่ต้องการ ป้ายกำกับท้ายสุดเป็นสัญลักษณ์ที่ไม่มีความยาวตามที่อยู่ที่ระบุ __initial_sp ใช้โดยตรงสำหรับตารางเวกเตอร์ในเวลาเชื่อมโยงและ __heap_base และ __heap_limit ด้วยรหัสรันไทม์ของคุณ ที่อยู่ที่แท้จริงของสัญลักษณ์ได้รับมอบหมายจาก linker ตามที่มันวางไว้
ดังที่ฉันได้กล่าวถึงข้างต้นสัญลักษณ์เหล่านี้ไม่จำเป็นต้องมาจากไฟล์ startup.s พวกเขาสามารถมาจากการกำหนดค่า linker ของคุณ (โหลดกระจายใน Keil, linkerscript ใน GNU) และในสิ่งที่คุณสามารถควบคุมตำแหน่งได้อย่างละเอียดยิ่งขึ้น ตัวอย่างเช่นคุณสามารถบังคับให้สแต็กอยู่ที่จุดเริ่มต้นหรือจุดจบของ RAM หรือทำให้กลมกลืนของคุณห่างจากกองหรือสิ่งที่คุณต้องการ คุณสามารถระบุได้ว่า HEAP หรือ STACK นั้นจะใช้งาน RAM ที่เหลืออยู่หลังจากวาง globals ไว้ หมายเหตุแม้ว่าคุณจะต้องระมัดระวังว่าการเพิ่มตัวแปรแบบคงที่เพิ่มเติมที่หน่วยความจำอื่นของคุณจะลดลง
อย่างไรก็ตามแต่ละ toolchain นั้นแตกต่างกันและวิธีเขียนไฟล์กำหนดค่าและสัญลักษณ์ใดที่ตัวจัดสรรหน่วยความจำแบบไดนามิกของคุณจะใช้จะต้องมาจากเอกสารประกอบของสภาพแวดล้อมเฉพาะของคุณ
การปรับขนาดสแต็ก
สำหรับวิธีการกำหนดขนาดของกองซ้อนชุดเครื่องมือจำนวนมากสามารถให้ความลึกของสแต็กได้สูงสุดโดยการวิเคราะห์แผนผังการเรียกใช้ฟังก์ชันของโปรแกรมของคุณหากคุณไม่ใช้การเรียกซ้ำหรือตัวชี้ฟังก์ชัน หากคุณใช้สิ่งเหล่านั้นให้ประเมินขนาดสแต็กและเติมค่าด้วยคาร์ดินาลล่วงหน้า (อาจจะผ่านฟังก์ชั่นการป้อนข้อมูลก่อนหน้าหลัก) จากนั้นตรวจสอบหลังจากโปรแกรมของคุณทำงานในขณะที่มีความลึกสูงสุด จบ) หากคุณออกกำลังกายโปรแกรมอย่างเต็มที่จนถึงขีด จำกัด คุณจะรู้ได้อย่างถูกต้องว่าคุณสามารถย่อขนาดสแต็กหรือถ้าโปรแกรมของคุณขัดข้องหรือไม่มีค่าสำคัญที่เหลืออยู่คุณต้องเพิ่มสแต็กและลองอีกครั้ง
การปรับขนาดกอง
การกำหนดขนาดของฮีพนั้นขึ้นอยู่กับแอพพลิเคชั่นอีกเล็กน้อย หากคุณทำการจัดสรรแบบไดนามิกเฉพาะในระหว่างการเริ่มต้นคุณสามารถเพิ่มพื้นที่ที่ต้องการในรหัสเริ่มต้นของคุณ (รวมทั้งค่าใช้จ่ายสำหรับการจัดการหน่วยความจำ) หากคุณสามารถเข้าถึงแหล่งที่มาของตัวจัดการหน่วยความจำของคุณคุณสามารถรู้ได้อย่างชัดเจนว่าค่าใช้จ่ายคืออะไรและอาจเขียนโค้ดเพื่อเดินหน่วยความจำเพื่อให้ข้อมูลการใช้งานแก่คุณ สำหรับแอปพลิเคชันที่ต้องการหน่วยความจำแบบรันไทม์แบบไดนามิก (เช่นการจัดสรรบัฟเฟอร์สำหรับเฟรมอีเธอร์เน็ตขาเข้า) ที่ดีที่สุดที่ฉันสามารถแนะนำคือการฝึกกองขนาดเล็กของคุณอย่างระมัดระวังและให้กองทุกอย่างที่เหลือหลังจากกองซ้อนและสถิต
หมายเหตุสุดท้าย (RTOS)
คำถามของ OP ถูกติดแท็กสำหรับโลหะเปลือย แต่ฉันต้องการเพิ่มบันทึกสำหรับ RTOS บ่อยครั้ง (เสมอ?) แต่ละงาน / กระบวนการ / เธรด (ฉันเพิ่งจะเขียนงานที่นี่เพื่อความเรียบง่าย) จะได้รับการกำหนดขนาดสแต็คเมื่อมีการสร้างงานนอกเหนือไปจากสแต็คงานจะมีระบบปฏิบัติการขนาดเล็ก กอง (ใช้สำหรับขัดจังหวะและเช่น)
โครงสร้างบัญชีงานและสแต็กต้องได้รับการจัดสรรจากที่ไหนสักแห่งและสิ่งนี้มักจะมาจากพื้นที่โดยรวมของฮีปของแอพพลิเคชันของคุณ ในกรณีเหล่านี้ขนาดสแต็กเริ่มต้นของคุณมักจะไม่สำคัญเนื่องจากระบบปฏิบัติการจะใช้ในระหว่างการเริ่มต้นเท่านั้น ยกตัวอย่างเช่นฉันได้เห็นการระบุพื้นที่ที่เหลือทั้งหมดในระหว่างการเชื่อมโยงถูกจัดสรรไปที่ HEAP และวางตัวชี้สแต็กเริ่มต้นที่ท้ายฮีปให้เติบโตเป็นฮีปโดยที่รู้ว่าระบบปฏิบัติการจะจัดสรรเริ่มต้นตั้งแต่ฮีปและ จะจัดสรรสแต็ก OS ก่อนที่จะละทิ้ง initial_sp สแต็ก จากนั้นจะใช้พื้นที่ทั้งหมดสำหรับการจัดสรรสแต็กงานและหน่วยความจำที่จัดสรรแบบไดนามิกอื่น ๆ