มีเว็บไซต์และตัวอย่างอื่น ๆ อีกนับไม่ถ้วน หลายพันถ้าไม่นับหมื่น มีไลบรารี c ที่รู้จักกันดีพร้อมสคริปต์ตัวเชื่อมโยงและรหัส boostrap, newlib, glibc โดยเฉพาะ แต่มีคนอื่นที่คุณสามารถค้นหาได้ Bootstraping C กับ C ไม่มีเหตุผล
คำถามของคุณได้รับคำตอบว่าคุณกำลังพยายามเปรียบเทียบสิ่งที่อาจไม่ถูกต้องอาจไม่เริ่มในขอบเขตที่รู้จักหรือสิ้นสุดในขอบเขตที่ทราบ ดังนั้นคุณสามารถทำสิ่งที่น้อยกว่า แต่ถ้ารหัสไม่ได้ทำงานกับการเปรียบเทียบที่แน่นอนนั่นหมายความว่าคุณเป็นศูนย์. อดีตที่ผ่านมาในส่วนถัดไปซึ่งอาจหรืออาจไม่ก่อให้เกิดสิ่งที่ไม่ดีเกิดขึ้นดังนั้นเพียงแค่แทนที่ด้วยน้อยกว่า การแก้ไขปัญหา.
ดังนั้นที่นี่จะไป TL; DR เป็นเรื่องปกติ คุณไม่ต้องบูตภาษาด้วยภาษานั้นคุณสามารถหนีไปได้ แต่คุณกำลังเล่นด้วยไฟเมื่อคุณทำเช่นนั้น หากคุณเป็นเพียงการเรียนรู้วิธีการทำเช่นนี้คุณจะต้องอยู่ในความระมัดระวังไม่โชคดีหรือข้อเท็จจริงที่คุณยังไม่ได้เปิด
สคริปต์ตัวเชื่อมโยงและรหัส bootstrap มีความสัมพันธ์ที่ใกล้ชิดมากพวกเขาแต่งงานเข้าร่วมที่สะโพกคุณไม่ได้พัฒนาสิ่งใดสิ่งหนึ่งที่นำไปสู่ความล้มเหลวครั้งใหญ่ และน่าเสียดายที่สคริปต์ตัวเชื่อมโยงถูกกำหนดโดยตัวเชื่อมโยงและภาษาแอสเซมบลีที่กำหนดโดยแอสเซมเบลอร์เมื่อคุณเปลี่ยนชุดเครื่องมือคาดว่าจะต้องเขียนใหม่ทั้งสอง ทำไมต้องประกอบภาษา มันไม่ต้องการ bootstrap ภาษาที่คอมไพล์โดยทั่วไปทำ C ถ้าคุณไม่ต้องการ จำกัด การใช้งานของคุณในการเริ่มต้นด้วยบางสิ่งที่ง่ายมากที่มีข้อกำหนดเฉพาะของ toolchain น้อยที่สุดคุณไม่คิดว่าตัวแปร. bss เป็นศูนย์ (ทำให้โค้ดอ่านน้อยลงถ้าตัวแปรไม่เคยเริ่มต้นในภาษานั้น พยายามหลีกเลี่ยงสิ่งนี้ไม่เป็นความจริงสำหรับตัวแปรในท้องที่ดังนั้นคุณจึงต้องใช้มันเหมือนเมื่อคุณใช้มัน แล้วทำไมเราถึงพูดถึง. bss และ. data ??? (กลมดีสำหรับการทำงานในระดับนี้ แต่นั่นเป็นหัวข้ออื่น)) กฎอื่น ๆ สำหรับการแก้ปัญหาง่ายๆคืออย่าเริ่มต้นตัวแปรในการประกาศทำในรหัส ใช่เบิร์นส์แฟลชมากขึ้นโดยทั่วไปคุณมีจำนวนมากไม่ใช่ว่าตัวแปรทั้งหมดจะเริ่มต้นด้วยค่าคงที่ต่อไปซึ่งจะจบลงด้วยคำแนะนำในการบริโภค
คุณสามารถบอกได้จากการออกแบบคอร์เท็กซ์ -m ว่าพวกเขาอาจกำลังคิดว่าไม่มีรหัสบูทสแตรปเลยไม่สนับสนุน. data หรือ. bbs คนส่วนใหญ่ที่ใช้ globals ไม่สามารถอยู่โดยที่นี่
ฉันสามารถทำให้มันน้อยลง แต่เป็นตัวอย่างการทำงานที่น้อยที่สุดสำหรับคอร์เท็กซ์ -ms ทั้งหมดโดยใช้ gnu toolchain ฉันจำไม่ได้ว่ารุ่นใดที่คุณสามารถเริ่มต้นด้วย 5.xx หรือมากกว่านั้นจนถึง 9.xx ปัจจุบันฉันสลับสคริปต์ลิงเกอร์ที่อื่นประมาณ 3 xx หรือ 4.xx เมื่อฉันเรียนรู้มากขึ้นและเมื่อ gnu เปลี่ยนบางสิ่งที่ทำให้ฉันเสียครั้งแรก
บูต:
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done
.thumb_func
reset:
bl centry
b done
.thumb_func
done: b .
.thumb_func
.globl bounce
bounce:
bx lr
จุดเข้าสู่รหัส C:
void bounce ( unsigned int );
unsigned int a;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
สคริปต์ลิงเกอร์
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
สิ่งเหล่านี้อาจเล็กลงและยังใช้งานได้เพิ่มสิ่งพิเศษบางอย่างที่นี่เพื่อดูในที่ทำงาน
การสร้างและลิงก์ที่ปรับให้เหมาะสม
00000000 <_start>:
0: 20001000
4: 00000015
8: 0000001b
c: 0000001b
10: 0000001b
00000014 <reset>:
14: f000 f804 bl 20 <centry>
18: e7ff b.n 1a <done>
0000001a <done>:
1a: e7fe b.n 1a <done>
0000001c <bounce>:
1c: 4770 bx lr
...
00000020 <centry>:
20: 2207 movs r2, #7
22: b510 push {r4, lr}
24: 4b04 ldr r3, [pc, #16] ; (38 <centry+0x18>)
26: 2007 movs r0, #7
28: 601a str r2, [r3, #0]
2a: f7ff fff7 bl 1c <bounce>
2e: 2000 movs r0, #0
30: bc10 pop {r4}
32: bc02 pop {r1}
34: 4708 bx r1
36: 46c0 nop ; (mov r8, r8)
38: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <a>:
20000000: 00000000 andeq r0, r0, r0
สำหรับผู้ค้าบางรายที่คุณต้องการใช้ 0x08000000 หรือ 0x01000000 หรือที่อยู่อื่นที่คล้ายคลึงกันเนื่องจากมีการทำแผนที่แฟลชและสะท้อนเป็น 0x00000000 ในโหมดการบูตบางโหมด บางตัวมีแฟลชมิรเรอร์จำนวนมากที่ 0x00000000 ดังนั้นคุณจึงต้องการให้จุดตารางเวกเตอร์ที่พื้นที่แฟลชของแอปพลิเคชันไม่เป็นศูนย์ เนื่องจากมันเป็นตารางเวกเตอร์ที่ใช้ทุกอย่างทำงานได้
ก่อนอื่นเยื่อหุ้มสมอง -ms เป็นเพียงนิ้วโป้งเครื่องเท่านั้นและด้วยเหตุผลใดก็ตามที่พวกเขาบังคับใช้ที่อยู่ฟังก์ชั่นนิ้วหัวแม่มือหมายถึง lsbit เป็นคี่ รู้ว่าเครื่องมือของคุณคำสั่ง. thumb_func บอกแอสเซมเบลอร์ gnu ว่าเลเบลถัดไปเป็นแอดเดรสของฟังก์ชันนิ้วหัวแม่มือ การทำสิ่ง +1 ในตารางจะนำไปสู่ความล้มเหลวอย่าถูกล่อลวงให้ทำถูกต้อง มีวิธีการประกอบ gnu อื่น ๆ ที่จะประกาศฟังก์ชั่นนี้เป็นวิธีการที่น้อยที่สุด
4: 00000015
8: 0000001b
c: 0000001b
10: 0000001b
มันจะไม่บูตหากคุณไม่ได้ตารางเวกเตอร์ที่ถูกต้อง
เนื้อหาต้องการเฉพาะเวกเตอร์ตัวชี้สแต็ก (สามารถใส่สิ่งใดก็ได้ในนั้นถ้าคุณต้องการตั้งค่าตัวชี้สแต็กด้วยตัวคุณเองในโค้ด) และเวกเตอร์รีเซ็ต ฉันใส่สี่ที่นี่โดยไม่มีเหตุผลพิเศษ มักจะใส่ 16 แต่ต้องการย่อตัวอย่างนี้
ดังนั้น bootstrap C ขั้นต่ำสุดที่ต้องทำคืออะไร? 1. ตั้งค่าพอยน์เตอร์สแต็ค 2. zero .bss 3. คัดลอก. data 4. branch ไปยังหรือเรียกจุดเข้า C
จุดเข้า C มักจะเรียกว่า main () แต่เครื่องมือบางอันจะเห็น main () และเพิ่มขยะพิเศษในโค้ดของคุณ ฉันใช้ชื่ออื่นโดยเจตนา YMMV
ไม่จำเป็นต้องใช้สำเนาของ. data หากเป็น ram ทั้งหมด การเป็นไมโครคอนโทรลเลอร์คอร์เท็กซ์ -m เป็นไปได้ในทางเทคนิค แต่ไม่น่าเป็นไปได้ดังนั้นจึงจำเป็นต้องมีการคัดลอก. data ..... ถ้ามี. data
ตัวอย่างแรกของฉันและรูปแบบการเข้ารหัสคือไม่ต้องพึ่งพา. data หรือ. bbs ดังเช่นในตัวอย่างนี้ แขนดูแลตัวชี้สแต็กดังนั้นสิ่งเดียวที่เหลือคือเรียกจุดเข้า ฉันชอบที่จะมีมันเพื่อให้จุดเริ่มต้นสามารถกลับมาหลายคนยืนยันว่าคุณไม่ควรทำอย่างนั้น คุณสามารถทำสิ่งนี้ได้แล้ว:
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word centry
.word done
.word done
.word done
และไม่ส่งคืนจาก centry () และไม่มีรหัสตัวจัดการรีเซ็ต
00000020 <centry>:
20: 2207 movs r2, #7
22: b510 push {r4, lr}
24: 4b04 ldr r3, [pc, #16] ; (38 <centry+0x18>)
26: 2007 movs r0, #7
28: 601a str r2, [r3, #0]
2a: f7ff fff7 bl 1c <bounce>
2e: 2000 movs r0, #0
30: bc10 pop {r4}
32: bc02 pop {r1}
34: 4708 bx r1
36: 46c0 nop ; (mov r8, r8)
38: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <a>:
20000000: 00000000
ตัวเชื่อมโยงใส่สิ่งที่เราถาม และโดยรวมแล้วเรามีโปรแกรมที่ทำงานได้อย่างสมบูรณ์
ดังนั้นก่อนอื่นให้ใช้สคริปต์ตัวเชื่อมโยง:
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > ted AT > bob
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
.bss : {
__bss_start__ = .;
*(.bss*)
} > ted
__bss_end__ = .;
__bss_size__ = __bss_end__ - __bss_start__;
}
เน้นว่าชื่อ rom และ ram ไม่มีความหมายพวกมันเชื่อมต่อจุดสำหรับตัวลิงก์ระหว่างส่วนเท่านั้น
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done
.thumb_func
reset:
bl centry
b done
.thumb_func
done: b .
.thumb_func
.globl bounce
bounce:
bx lr
.align
.word __data_rom_start__
.word __data_start__
.word __data_end__
.word __data_size__
เพิ่มบางรายการเพื่อให้เราเห็นว่าเครื่องมือทำอะไร
void bounce ( unsigned int );
unsigned int a;
unsigned int b=4;
unsigned char c=5;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
เพิ่มบางรายการที่จะวางในส่วนเหล่านั้น และรับ
Disassembly of section .text:
00000000 <_start>:
0: 20000800 andcs r0, r0, r0, lsl #16
4: 00000015 andeq r0, r0, r5, lsl r0
8: 0000001b andeq r0, r0, r11, lsl r0
c: 0000001b andeq r0, r0, r11, lsl r0
10: 0000001b andeq r0, r0, r11, lsl r0
00000014 <reset>:
14: f000 f80c bl 30 <centry>
18: e7ff b.n 1a <done>
0000001a <done>:
1a: e7fe b.n 1a <done>
0000001c <bounce>:
1c: 4770 bx lr
1e: 46c0 nop ; (mov r8, r8)
20: 0000004c andeq r0, r0, r12, asr #32
24: 20000000 andcs r0, r0, r0
28: 20000008 andcs r0, r0, r8
2c: 00000008 andeq r0, r0, r8
00000030 <centry>:
30: 2207 movs r2, #7
32: b510 push {r4, lr}
34: 4b04 ldr r3, [pc, #16] ; (48 <centry+0x18>)
36: 2007 movs r0, #7
38: 601a str r2, [r3, #0]
3a: f7ff ffef bl 1c <bounce>
3e: 2000 movs r0, #0
40: bc10 pop {r4}
42: bc02 pop {r1}
44: 4708 bx r1
46: 46c0 nop ; (mov r8, r8)
48: 20000008 andcs r0, r0, r8
Disassembly of section .data:
20000000 <c>:
20000000: 00000005 andeq r0, r0, r5
20000004 <b>:
20000004: 00000004 andeq r0, r0, r4
Disassembly of section .bss:
20000008 <a>:
20000008: 00000000 andeq r0, r0, r0
นี่คือสิ่งที่เรากำลังมองหาในการทดสอบนั้น (โปรดทราบว่าไม่มีเหตุผลที่จะโหลดหรือเรียกใช้รหัสใด ๆ ... รู้เครื่องมือของคุณเรียนรู้พวกเขา)
1c: 4770 bx lr
1e: 46c0 nop ; (mov r8, r8)
20: 0000004c andeq r0, r0, r12, asr #32
24: 20000000 andcs r0, r0, r0
28: 20000008 andcs r0, r0, r8
2c: 00000008 andeq r0, r0, r8
ดังนั้นสิ่งที่เราเรียนรู้ที่นี่คือตำแหน่งของตัวแปรมีความอ่อนไหวมากในสคริปต์ตัวเชื่อมโยง gnu บันทึกตำแหน่งdata_rom_startกับdata_startแต่ทำไมdata_end ถึงทำงาน ไม่ให้คุณคิดออก เข้าใจอยู่แล้วว่าทำไมคนเราอาจไม่ต้องการยุ่งกับ linker script และแค่ไปเขียนโปรแกรมง่ายๆ ...
ดังนั้นสิ่งอื่นที่เราเรียนรู้ที่นี่คือ linker จัดdata_rom_startให้เราเราไม่ต้องการ ALIGN (4) ในนั้น เราควรสมมติว่ามันจะได้ผลเสมอ
นอกจากนี้โปรดทราบว่ามันมีความสะดวกในการออกไปเรามี 5 ไบต์ของ. data แต่มันเพิ่มเป็น 8 โดยไม่มี ALIGN () เราสามารถคัดลอกโดยใช้คำ จากสิ่งที่เราเห็นด้วย toolchain นี้ในคอมพิวเตอร์ของฉันวันนี้มันอาจจะเป็นจริงสำหรับอดีตและอนาคต ใครจะรู้แม้กับ ALIGNs จะต้องตรวจสอบเป็นระยะเพื่อยืนยันบางเวอร์ชั่นใหม่ที่ไม่ทำลายสิ่งต่าง ๆ พวกเขาจะทำเช่นนั้นเป็นครั้งคราว
จากการทดสอบดังกล่าวจะช่วยให้ปลอดภัยได้
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
. = ALIGN(4);
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
. = ALIGN(4);
__data_end__ = .;
} > ted AT > bob
__data_size__ = __data_end__ - __data_start__;
. = ALIGN(4);
.bss : {
__bss_start__ = .;
*(.bss*)
. = ALIGN(4);
__bss_end__ = .;
} > ted
__bss_size__ = __bss_end__ - __bss_start__;
}
ย้ายปลายด้านในให้สอดคล้องกับสิ่งที่คนอื่นทำ และนั่นก็ไม่ได้เปลี่ยน:
0000001c <bounce>:
1c: 4770 bx lr
1e: 46c0 nop ; (mov r8, r8)
20: 0000004c andeq r0, r0, r12, asr #32
24: 20000000 andcs r0, r0, r0
28: 20000008 andcs r0, r0, r8
2c: 00000008 andeq r0, r0, r8
การทดสอบด่วนอีกหนึ่งข้อ:
.globl bounce
bounce:
nop
bx lr
ให้
0000001c <bounce>:
1c: 46c0 nop ; (mov r8, r8)
1e: 4770 bx lr
20: 0000004c andeq r0, r0, r12, asr #32
24: 20000000 andcs r0, r0, r0
28: 20000008 andcs r0, r0, r8
2c: 00000008 andeq r0, r0, r8
ไม่จำเป็นต้อง pad ระหว่างการตีกลับและ. align
โอ้จำได้แล้วตอนนี้ทำไมฉันไม่ใส่ _end__ ข้างใน เพราะมันไม่ทำงาน
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
. = ALIGN(4);
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > ted AT > bob
. = ALIGN(4);
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
. = ALIGN(4);
.bss : {
__bss_start__ = .;
*(.bss*)
} > ted
. = ALIGN(4);
__bss_end__ = .;
__bss_size__ = __bss_end__ - __bss_start__;
}
โค้ดที่เรียบง่าย แต่พกพาสะดวกบางอย่างเพื่อแต่งงานกับสคริปต์ตัวเชื่อมโยงนี้
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done
.thumb_func
reset:
ldr r0,blen
cmp r0,#0
beq bss_zero_done
ldr r1,bstart
mov r2,#0
bss_zero:
stmia r1!,{r2}
sub r0,#4
bne bss_zero
bss_zero_done:
ldr r0,dlen
cmp r0,#0
beq data_copy_done
ldr r1,rstart
ldr r2,dstart
data_copy:
ldmia r1!,{r3}
stmia r2!,{r3}
sub r0,#4
bne data_copy
data_copy_done:
bl centry
b done
.thumb_func
done: b .
.thumb_func
.globl bounce
bounce:
nop
bx lr
.align
bstart: .word __bss_start__
blen: .word __bss_size__
rstart: .word __data_rom_start__
dstart: .word __data_start__
dlen: .word __data_size__
ให้
Disassembly of section .text:
00000000 <_start>:
0: 20000800 andcs r0, r0, r0, lsl #16
4: 00000015 andeq r0, r0, r5, lsl r0
8: 0000003d andeq r0, r0, sp, lsr r0
c: 0000003d andeq r0, r0, sp, lsr r0
10: 0000003d andeq r0, r0, sp, lsr r0
00000014 <reset>:
14: 480c ldr r0, [pc, #48] ; (48 <blen>)
16: 2800 cmp r0, #0
18: d004 beq.n 24 <bss_zero_done>
1a: 490a ldr r1, [pc, #40] ; (44 <bstart>)
1c: 2200 movs r2, #0
0000001e <bss_zero>:
1e: c104 stmia r1!, {r2}
20: 3804 subs r0, #4
22: d1fc bne.n 1e <bss_zero>
00000024 <bss_zero_done>:
24: 480b ldr r0, [pc, #44] ; (54 <dlen>)
26: 2800 cmp r0, #0
28: d005 beq.n 36 <data_copy_done>
2a: 4908 ldr r1, [pc, #32] ; (4c <rstart>)
2c: 4a08 ldr r2, [pc, #32] ; (50 <dstart>)
0000002e <data_copy>:
2e: c908 ldmia r1!, {r3}
30: c208 stmia r2!, {r3}
32: 3804 subs r0, #4
34: d1fb bne.n 2e <data_copy>
00000036 <data_copy_done>:
36: f000 f80f bl 58 <centry>
3a: e7ff b.n 3c <done>
0000003c <done>:
3c: e7fe b.n 3c <done>
0000003e <bounce>:
3e: 46c0 nop ; (mov r8, r8)
40: 4770 bx lr
42: 46c0 nop ; (mov r8, r8)
00000044 <bstart>:
44: 20000008 andcs r0, r0, r8
00000048 <blen>:
48: 00000004 andeq r0, r0, r4
0000004c <rstart>:
4c: 00000074 andeq r0, r0, r4, ror r0
00000050 <dstart>:
50: 20000000 andcs r0, r0, r0
00000054 <dlen>:
54: 00000008 andeq r0, r0, r8
00000058 <centry>:
58: 2207 movs r2, #7
5a: b510 push {r4, lr}
5c: 4b04 ldr r3, [pc, #16] ; (70 <centry+0x18>)
5e: 2007 movs r0, #7
60: 601a str r2, [r3, #0]
62: f7ff ffec bl 3e <bounce>
66: 2000 movs r0, #0
68: bc10 pop {r4}
6a: bc02 pop {r1}
6c: 4708 bx r1
6e: 46c0 nop ; (mov r8, r8)
70: 20000008 andcs r0, r0, r8
Disassembly of section .data:
20000000 <c>:
20000000: 00000005 andeq r0, r0, r5
20000004 <b>:
20000004: 00000004 andeq r0, r0, r4
Disassembly of section .bss:
20000008 <a>:
20000008: 00000000 andeq r0, r0, r0
เราสามารถหยุดตรงนั้นหรือเดินต่อไป หากเราเริ่มต้นในลำดับเดียวกันกับสคริปต์ตัวเชื่อมโยงมันก็โอเคถ้าเราไปสู่สิ่งต่อไปเพราะเรายังไม่ได้ไปที่นั่น และ stm / ldm จำเป็นต้องใช้ / ต้องการใช้ที่อยู่ที่จัดเรียงคำเท่านั้นดังนั้นหากคุณเปลี่ยนเป็น:
ldr r0,blen
cmp r0,#0
beq bss_zero_done
ldr r1,bstart
mov r2,#0
mov r3,#0
mov r4,#0
mov r5,#0
bss_zero:
stmia r1!,{r2,r3,r4,r5}
sub r0,#16
ble bss_zero
bss_zero_done:
กับ bss เป็นอันดับแรกในตัวเชื่อมโยงสคริปต์และใช่คุณต้องการไม่ bls bls
Disassembly of section .text:
00000000 <_start>:
0: 20000800 andcs r0, r0, r0, lsl #16
4: 00000015 andeq r0, r0, r5, lsl r0
8: 00000043 andeq r0, r0, r3, asr #32
c: 00000043 andeq r0, r0, r3, asr #32
10: 00000043 andeq r0, r0, r3, asr #32
00000014 <reset>:
14: 480d ldr r0, [pc, #52] ; (4c <blen>)
16: 2800 cmp r0, #0
18: d007 beq.n 2a <bss_zero_done>
1a: 490b ldr r1, [pc, #44] ; (48 <bstart>)
1c: 2200 movs r2, #0
1e: 2300 movs r3, #0
20: 2400 movs r4, #0
22: 2500 movs r5, #0
00000024 <bss_zero>:
24: c13c stmia r1!, {r2, r3, r4, r5}
26: 3804 subs r0, #4
28: ddfc ble.n 24 <bss_zero>
0000002a <bss_zero_done>:
2a: 480b ldr r0, [pc, #44] ; (58 <dlen>)
2c: 2800 cmp r0, #0
2e: d005 beq.n 3c <data_copy_done>
30: 4907 ldr r1, [pc, #28] ; (50 <rstart>)
32: 4a08 ldr r2, [pc, #32] ; (54 <dstart>)
00000034 <data_copy>:
34: c978 ldmia r1!, {r3, r4, r5, r6}
36: c278 stmia r2!, {r3, r4, r5, r6}
38: 3810 subs r0, #16
3a: ddfb ble.n 34 <data_copy>
0000003c <data_copy_done>:
3c: f000 f80e bl 5c <centry>
40: e7ff b.n 42 <done>
00000042 <done>:
42: e7fe b.n 42 <done>
00000044 <bounce>:
44: 46c0 nop ; (mov r8, r8)
46: 4770 bx lr
00000048 <bstart>:
48: 20000000 andcs r0, r0, r0
0000004c <blen>:
4c: 00000004 andeq r0, r0, r4
00000050 <rstart>:
50: 20000004 andcs r0, r0, r4
00000054 <dstart>:
54: 20000004 andcs r0, r0, r4
00000058 <dlen>:
58: 00000008 andeq r0, r0, r8
0000005c <centry>:
5c: 2207 movs r2, #7
5e: b510 push {r4, lr}
60: 4b04 ldr r3, [pc, #16] ; (74 <centry+0x18>)
62: 2007 movs r0, #7
64: 601a str r2, [r3, #0]
66: f7ff ffed bl 44 <bounce>
6a: 2000 movs r0, #0
6c: bc10 pop {r4}
6e: bc02 pop {r1}
70: 4708 bx r1
72: 46c0 nop ; (mov r8, r8)
74: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <a>:
20000000: 00000000 andeq r0, r0, r0
Disassembly of section .data:
20000004 <c>:
20000004: 00000005 andeq r0, r0, r5
20000008 <b>:
20000008: 00000004 andeq r0, r0, r4
ลูปเหล่านั้นจะไปเร็วขึ้น ตอนนี้ฉันไม่รู้ว่ารถถัง ahb นั้นมีความกว้าง 64 บิตหรือไม่ แต่สำหรับแขนเต็มขนาดคุณต้องการจัดตำแหน่งสิ่งเหล่านี้ในขอบเขต 64 บิต การลงทะเบียนสี่ ldm / stm บนขอบเขต 32 บิต แต่ไม่ใช่ขอบเขต 64 บิตจะกลายเป็นธุรกรรมรถบัสที่แยกกันสามรายการโดยการจัดตำแหน่งบนขอบเขต 64 บิตเป็นธุรกรรมเดียวที่ประหยัดนาฬิกาหลายต่อการเรียนการสอน
เนื่องจากเรากำลังทำ baremetal และเรามีความรับผิดชอบในทุกสิ่งที่เราสามารถพูด bss ก่อนแล้วข้อมูลถ้าเรามีกองทำแล้วกองเติบโตจากด้านบนลงดังนั้นถ้าเราศูนย์ bss และหกกว่าบางตราบเท่าที่เราเริ่มที่ สถานที่ที่เหมาะสมที่เราไม่ได้ใช้หน่วยความจำนั้น จากนั้นเราก็คัดลอก. data ไปแล้วและสามารถกระจายเข้าไปใน heap ได้ดี heap หรือไม่มีที่ว่างมากมายสำหรับ stack ดังนั้นเราจึงไม่เหยียบกับใคร / อะไร (ตราบใดที่เรามั่นใจใน scripter linker ที่เราทำ หากมีข้อกังวลให้ทำให้ ALIGN () ใหญ่ขึ้นเพื่อให้เราอยู่ในพื้นที่ของเราเสมอสำหรับการเติมเหล่านี้
ดังนั้นวิธีง่ายๆของฉันเอาไปหรือทิ้งไป ยินดีต้อนรับสู่แก้ไขข้อบกพร่องใด ๆ ฉันไม่ได้เรียกใช้บนฮาร์ดแวร์หรือตัวจำลองของฉัน ...
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
. = ALIGN(8);
.bss : {
__bss_start__ = .;
*(.bss*)
} > ted
. = ALIGN(4);
__bss_end__ = .;
__bss_size__ = __bss_end__ - __bss_start__;
. = ALIGN(8);
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > ted AT > bob
. = ALIGN(4);
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
}
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done
.thumb_func
reset:
ldr r0,blen
cmp r0,#0
beq bss_zero_done
ldr r1,bstart
mov r2,#0
mov r3,#0
mov r4,#0
mov r5,#0
bss_zero:
stmia r1!,{r2,r3,r4,r5}
sub r0,#16
ble bss_zero
bss_zero_done:
ldr r0,dlen
cmp r0,#0
beq data_copy_done
ldr r1,rstart
ldr r2,dstart
data_copy:
ldmia r1!,{r3,r4,r5,r6}
stmia r2!,{r3,r4,r5,r6}
sub r0,#16
ble data_copy
data_copy_done:
bl centry
b done
.thumb_func
done: b .
.thumb_func
.globl bounce
bounce:
nop
bx lr
.align
bstart: .word __bss_start__
blen: .word __bss_size__
rstart: .word __data_rom_start__
dstart: .word __data_start__
dlen: .word __data_size__
void bounce ( unsigned int );
unsigned int a;
unsigned int b=4;
unsigned char c=5;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
arm-none-eabi-as --warn --fatal-warnings flash.s -o flash.o
arm-none-eabi-ld -o hello.elf -T flash.ld flash.o centry.o
arm-none-eabi-objdump -D hello.elf > hello.list
arm-none-eabi-objcopy hello.elf hello.bin -O binary
รวบรวมทั้งหมดเข้าด้วยกันและคุณจะได้รับ:
Disassembly of section .text:
00000000 <_start>:
0: 20000800 andcs r0, r0, r0, lsl #16
4: 00000015 andeq r0, r0, r5, lsl r0
8: 00000043 andeq r0, r0, r3, asr #32
c: 00000043 andeq r0, r0, r3, asr #32
10: 00000043 andeq r0, r0, r3, asr #32
00000014 <reset>:
14: 480d ldr r0, [pc, #52] ; (4c <blen>)
16: 2800 cmp r0, #0
18: d007 beq.n 2a <bss_zero_done>
1a: 490b ldr r1, [pc, #44] ; (48 <bstart>)
1c: 2200 movs r2, #0
1e: 2300 movs r3, #0
20: 2400 movs r4, #0
22: 2500 movs r5, #0
00000024 <bss_zero>:
24: c13c stmia r1!, {r2, r3, r4, r5}
26: 3810 subs r0, #16
28: ddfc ble.n 24 <bss_zero>
0000002a <bss_zero_done>:
2a: 480b ldr r0, [pc, #44] ; (58 <dlen>)
2c: 2800 cmp r0, #0
2e: d005 beq.n 3c <data_copy_done>
30: 4907 ldr r1, [pc, #28] ; (50 <rstart>)
32: 4a08 ldr r2, [pc, #32] ; (54 <dstart>)
00000034 <data_copy>:
34: c978 ldmia r1!, {r3, r4, r5, r6}
36: c278 stmia r2!, {r3, r4, r5, r6}
38: 3810 subs r0, #16
3a: ddfb ble.n 34 <data_copy>
0000003c <data_copy_done>:
3c: f000 f80e bl 5c <centry>
40: e7ff b.n 42 <done>
00000042 <done>:
42: e7fe b.n 42 <done>
00000044 <bounce>:
44: 46c0 nop ; (mov r8, r8)
46: 4770 bx lr
00000048 <bstart>:
48: 20000000 andcs r0, r0, r0
0000004c <blen>:
4c: 00000004 andeq r0, r0, r4
00000050 <rstart>:
50: 20000008 andcs r0, r0, r8
00000054 <dstart>:
54: 20000004 andcs r0, r0, r4
00000058 <dlen>:
58: 00000008 andeq r0, r0, r8
0000005c <centry>:
5c: 2207 movs r2, #7
5e: b510 push {r4, lr}
60: 4b04 ldr r3, [pc, #16] ; (74 <centry+0x18>)
62: 2007 movs r0, #7
64: 601a str r2, [r3, #0]
66: f7ff ffed bl 44 <bounce>
6a: 2000 movs r0, #0
6c: bc10 pop {r4}
6e: bc02 pop {r1}
70: 4708 bx r1
72: 46c0 nop ; (mov r8, r8)
74: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <a>:
20000000: 00000000 andeq r0, r0, r0
Disassembly of section .data:
20000004 <c>:
20000004: 00000005 andeq r0, r0, r5
20000008 <b>:
20000008: 00000004 andeq r0, r0, r4
โปรดทราบว่าสิ่งนี้ใช้งานได้กับ arm-none-eabi- และ arm-linux-gnueabi และตัวแปรอื่น ๆ เนื่องจากไม่มีการใช้ whee ghee whiz
คุณจะพบว่าเมื่อคุณมองไปรอบ ๆ นั้นผู้คนจะคลั่งไคล้กับ ghee whiz ในสคริปต์ linker ของพวกเขาห้องครัวขนาดใหญ่มหึมาจมสิ่งต่างๆ ดีกว่าที่จะรู้วิธีที่จะทำมัน (หรือดีกว่าวิธีที่เชี่ยวชาญเครื่องมือเพื่อให้คุณสามารถควบคุมสิ่งที่เกิดขึ้น) แทนที่จะพึ่งพาสิ่งที่คนอื่นและไม่ทราบว่ามันจะทำลายเพราะคุณไม่เข้าใจและ / หรือต้องการวิจัย มัน.
ตามกฎทั่วไปห้าม bootstrap ภาษาที่มีภาษาเดียวกัน (bootstrap ในกรณีนี้หมายถึงการเรียกใช้โค้ดที่ไม่คอมไพล์เลอร์ด้วยคอมไพเลอร์เดียวกัน) ที่คุณต้องการใช้ภาษาที่เรียบง่าย แต่มี bootstrap น้อยกว่า นั่นคือสาเหตุที่ C ประกอบเสร็จแล้วมันไม่มีข้อกำหนดบูตสแตรปที่คุณเพิ่งเริ่มจากคำสั่งแรกหลังจากรีเซ็ต JAVA แน่ใจว่าคุณอาจเขียน jvm ใน C และ bootstrap C ที่มี asm จากนั้น bootstrap JAVA หากคุณต้องการด้วย C แต่ยังรัน JAVA ใน C ด้วย
เนื่องจากเราควบคุมสมมติฐานเกี่ยวกับลูปการคัดลอกเหล่านี้พวกเขาจะถูกกำหนดโดยเข้มงวดและสะอาดกว่า memcpy / memset ที่ปรับด้วยมือ
โปรดทราบว่าปัญหาอื่นของคุณคือ:
unsigned int * bss_start_p = &_BSS_START;
unsigned int * bss_end_p = &_BSS_END;
ถ้าสิ่งเหล่านี้เป็นแบบโลคัลไม่มีปัญหาหากสิ่งเหล่านี้เป็นแบบโกลบอลคุณต้องมี. data เริ่มต้นก่อนเพื่อให้มันทำงานและถ้าคุณลองใช้เคล็ดลับที่จะทำ. data คุณจะล้มเหลว ตัวแปรท้องถิ่นที่ใช้ได้ หากคุณมีเหตุผลบางอย่างตัดสินใจที่จะทำให้คนในท้องถิ่นคงที่ (ฉันต้องการเรียกพวกเขา) คุณจะกลับมามีปัญหาอีกครั้ง ทุกครั้งที่คุณทำงานที่ได้รับมอบหมายในการประกาศถึงแม้ว่าคุณควรคิดเกี่ยวกับมันวิธีการที่มีการใช้งานและมีความปลอดภัย / สติ ทุกครั้งที่คุณถือว่าตัวแปรเป็นศูนย์เมื่อไม่ได้ประกาศใช้ข้อตกลงเดียวกันหากตัวแปรท้องถิ่นไม่ถือว่าเป็นศูนย์ถ้าเป็นสากลก็จะเป็นเช่นนั้น หากคุณไม่เคยคิดว่ามันจะเป็นศูนย์คุณก็ไม่ต้องกังวล