Có vô số trang web và ví dụ khác. Nhiều ngàn nếu không phải hàng vạn. Có những thư viện c nổi tiếng với các tập lệnh liên kết và mã boostrap, đặc biệt là newlib, glibc nhưng có những thư viện khác bạn có thể tìm thấy. Bootstraping C với C không có ý nghĩa.
Câu hỏi của bạn đã được trả lời, bạn đang cố gắng thực hiện một so sánh chính xác về những điều có thể không chính xác, nó có thể không bắt đầu trên một ranh giới đã biết hoặc kết thúc trên một ranh giới đã biết. Vì vậy, bạn có thể làm ít hơn nhưng nếu mã không hoạt động với một so sánh chính xác thì điều đó có nghĩa là bạn đang bỏ qua .bss vào phần tiếp theo có thể hoặc không thể gây ra những điều xấu xảy ra, vì vậy chỉ cần thay thế bằng một ít hơn là không giải pháp.
Vì vậy, ở đây đi TL; DR là tốt. Bạn không khởi động một ngôn ngữ với ngôn ngữ đó, bạn có thể thoát khỏi nó với ngôn ngữ đó, nhưng bạn đang chơi với lửa khi bạn làm điều đó. Nếu bạn chỉ đang học cách làm điều này, bạn cần phải thận trọng, không phải là may mắn ngu ngốc hay sự thật mà bạn chưa khám phá ra.
Kịch bản liên kết và mã bootstrap có mối quan hệ rất mật thiết, họ đã kết hôn, tham gia cùng nhau, bạn không phát triển cái này mà không có cái kia dẫn đến thất bại lớn. Và thật không may, tập lệnh liên kết được xác định bởi trình liên kết và ngôn ngữ lắp ráp được xác định bởi trình biên dịch chương trình để khi bạn thay đổi các công cụ dự kiến sẽ phải viết lại cả hai. Tại sao lắp ráp ngôn ngữ? Nó không cần bootstrap, ngôn ngữ biên dịch thường làm. C thực hiện nếu bạn không muốn giới hạn việc sử dụng ngôn ngữ của mình, Bắt đầu với một thứ rất đơn giản có yêu cầu cụ thể về công cụ tối thiểu, bạn không giả sử các biến .bss bằng 0 (làm cho mã ít đọc hơn nếu biến không bao giờ được khởi tạo trong ngôn ngữ đó , hãy cố gắng tránh điều này, điều này không đúng với các biến cục bộ vì vậy phải có mặt trên quả bóng khi bạn sử dụng nó. Mọi người hãy tránh xa toàn cầu, vậy tại sao chúng ta lại nói về .bss và .data ??? (toàn cầu là tốt cho công việc cấp độ này nhưng đó là một chủ đề khác)) quy tắc khác cho giải pháp đơn giản là không khởi tạo các biến trong khai báo, thực hiện trong mã. vâng, đốt cháy nhiều flash hơn, bạn thường có rất nhiều, không phải tất cả các biến đều được khởi tạo với các hằng số mà cuối cùng là hướng dẫn tiêu thụ.
Bạn có thể nói từ thiết kế cortex-m rằng họ có thể đã nghĩ rằng không có mã bootstrap nào cả nên không hỗ trợ .data và .bss. Hầu hết mọi người sử dụng toàn cầu không thể sống mà không có ở đây:
Tôi có thể làm cho điều này tối thiểu hơn nhưng là một ví dụ chức năng tối thiểu cho tất cả cortex-ms bằng cách sử dụng công cụ gnu, tôi không nhớ phiên bản nào bạn có thể bắt đầu với 5.xx hoặc hơn thông qua 9.xx hiện tại tôi đã chuyển các tập lệnh liên kết ở đâu đó khoảng 3. xx hoặc 4.xx khi tôi học được nhiều hơn và khi gnu thay đổi thứ gì đó đã phá vỡ cái đầu tiên của tôi.
bootstrap:
.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
điểm vào mã C:
void bounce ( unsigned int );
unsigned int a;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
tập lệnh liên kết.
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
Tất cả những thứ này có thể nhỏ hơn và vẫn hoạt động, thêm một số thứ bổ sung ở đây chỉ để xem nó tại nơi làm việc.
xây dựng và liên kết tối ưu.
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
đối với một số nhà cung cấp, bạn muốn sử dụng 0x08000000 hoặc 0x01000000 hoặc các địa chỉ tương tự khác khi đèn flash được ánh xạ ở đó và được nhân đôi thành 0x00000000 trong một số chế độ khởi động. một số chỉ có rất nhiều đèn flash được nhân đôi ở 0x00000000, vì vậy bạn muốn có điểm bảng vectơ tại không gian flash ứng dụng chứ không phải không. vì nó là bảng vector dựa trên tất cả các công trình.
đầu tiên lưu ý cortex-ms là máy chỉ ngón tay cái và vì bất kỳ lý do gì họ thực thi một địa chỉ chức năng ngón tay cái, có nghĩa là lsbit là số lẻ. Biết các công cụ của bạn, các lệnh .thumb_func cho trình biên dịch gnu biết rằng nhãn tiếp theo là địa chỉ hàm ngón tay cái. làm điều +1 trong bảng sẽ dẫn đến thất bại, đừng cố làm điều đó, hãy làm đúng. có nhiều cách khác để biên dịch hàm gnu để khai báo hàm, đây là cách tiếp cận tối thiểu.
4: 00000015
8: 0000001b
c: 0000001b
10: 0000001b
Nó sẽ không khởi động nếu bạn không nhận được bảng vector đúng.
có thể chỉ cần vectơ con trỏ ngăn xếp (có thể đặt bất cứ thứ gì vào đó nếu bạn muốn tự đặt con trỏ ngăn xếp trong mã) và vectơ thiết lập lại. Tôi đặt bốn ở đây không có lý do cụ thể. Thường đặt 16 nhưng muốn rút ngắn ví dụ này.
Vì vậy, tối thiểu một bootstrap C cần phải làm là gì? 1. đặt con trỏ ngăn xếp 2. zero .bss 3. sao chép .data 4. nhánh tới hoặc gọi điểm nhập C
điểm vào C thường được gọi là main (). nhưng một số công cụ xem main () và thêm rác vào mã của bạn. Tôi cố ý sử dụng một tên khác. YMMV.
bản sao của .data là không cần thiết nếu đây là tất cả dựa trên ram. là một vi điều khiển cortex-m về mặt kỹ thuật là có thể nhưng không thể vì vậy cần có bản sao .data ..... nếu có .data.
Ví dụ đầu tiên của tôi và một phong cách mã hóa là không dựa vào .data cũng như .bss, như trong ví dụ này. Arm đã chăm sóc con trỏ ngăn xếp nên điều duy nhất còn lại là gọi điểm vào. Tôi muốn có nó để điểm vào có thể trở lại, nhiều người tranh luận bạn không bao giờ nên làm điều đó. bạn chỉ có thể làm điều này sau đó:
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word centry
.word done
.word done
.word done
và không trả về từ centry () và không có mã xử lý thiết lập lại.
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
Trình liên kết đã đặt những thứ mà chúng tôi yêu cầu. Và tổng thể chúng tôi có một chương trình đầy đủ chức năng.
Vì vậy, đầu tiên làm việc trên kịch bản liên kết:
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__;
}
nhấn mạnh rằng tên rom và ram không có nghĩa là chúng chỉ kết nối các dấu chấm cho trình liên kết giữa các phần.
.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__
thêm một số mục để chúng ta có thể thấy những gì các công cụ đã làm
void bounce ( unsigned int );
unsigned int a;
unsigned int b=4;
unsigned char c=5;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
thêm một số mặt hàng để đặt trong những phần đó. và lấy
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
đây là thứ chúng tôi đang tìm kiếm trong thử nghiệm đó (lưu ý không có lý do để thực sự tải cũng như chạy bất kỳ mã nào ... biết công cụ của bạn, tìm hiểu chúng)
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
Vì vậy, những gì chúng ta học được ở đây là vị trí của các biến rất nhạy cảm trong các tập lệnh liên kết gnu. lưu ý vị trí của data_rom_start so với data_start nhưng tại sao data_end hoạt động? Ill cho phép bạn tìm ra điều đó. Đã hiểu lý do tại sao người ta có thể không muốn phải lộn xộn với các tập lệnh liên kết và chỉ cần lập trình đơn giản ...
Vì vậy, một điều khác mà chúng tôi đã học được ở đây là trình liên kết được căn chỉnh data_rom_start cho chúng tôi, chúng tôi không cần ALIGN (4) trong đó. Chúng ta có nên cho rằng điều đó sẽ luôn luôn làm việc?
Cũng lưu ý rằng nó được đệm trên đường ra, chúng ta có 5 byte .data nhưng nó được đệm đến 8. Nếu không có bất kỳ ALIGN () nào, chúng ta có thể thực hiện sao chép bằng các từ. Dựa trên những gì chúng ta thấy với chuỗi công cụ này trên máy tính của tôi ngày hôm nay, điều đó có thể đúng với quá khứ và tương lai không? Ai biết được, ngay cả với các ALIGN cần kiểm tra định kỳ để xác nhận một số phiên bản mới không phá vỡ mọi thứ, họ sẽ làm điều đó theo thời gian.
từ thí nghiệm đó cho phép chuyển sang điều này chỉ để an toàn.
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__;
}
di chuyển các kết thúc bên trong để phù hợp với những gì người khác làm. Và điều đó đã không thay đổi nó:
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
thêm một bài kiểm tra nhanh:
.globl bounce
bounce:
nop
bx lr
cho
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
không cần phải đệm giữa nảy và .align
Ồ, phải rồi, tôi nhớ tại sao tôi không đặt _end__ vào trong. bởi vì nó LÀM VIỆC.
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__;
}
một số mã đơn giản nhưng rất dễ mang theo để kết hợp với tập lệnh liên kết này
.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__
cho
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
chúng ta có thể dừng lại ở đó hoặc tiếp tục đi. Nếu chúng ta khởi tạo theo thứ tự giống như tập lệnh liên kết thì không sao nếu chúng ta chuyển sang điều tiếp theo vì chúng ta chưa đến đó. và stm / ldm chỉ được yêu cầu / mong muốn sử dụng địa chỉ căn chỉnh từ, vì vậy nếu bạn thay đổi thành:
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:
với bss đầu tiên trong tập lệnh liên kết, và có bạn muốn ble không 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
những vòng lặp sẽ đi nhanh hơn. bây giờ tôi không biết các bus ahb có thể rộng 64 bit hay không nhưng với một cánh tay có kích thước đầy đủ, bạn sẽ muốn căn chỉnh những thứ này trên ranh giới 64 bit. bốn thanh ghi ldm / stm trên ranh giới 32 bit nhưng không phải ranh giới 64 bit trở thành ba giao dịch xe buýt riêng biệt, trong đó căn chỉnh trên ranh giới 64 bit là một giao dịch duy nhất tiết kiệm nhiều đồng hồ trên mỗi lệnh.
vì chúng tôi đang thực hiện bar baral và chúng tôi chịu trách nhiệm hoàn toàn cho tất cả mọi thứ chúng tôi có thể nói bss trước sau đó là dữ liệu sau đó nếu chúng tôi có đống đó, thì stack sẽ tăng từ trên xuống, vì vậy nếu chúng tôi không bss và tràn vào chừng nào chúng tôi bắt đầu đúng nơi tốt là chúng tôi chưa sử dụng bộ nhớ đó. sau đó chúng tôi sao chép .data và có thể tràn vào heap đó là tốt, heap hay không có nhiều chỗ cho stack để chúng tôi không giẫm lên bất cứ ai / bất cứ điều gì (miễn là chúng tôi chắc chắn trong kịch bản liên kết chúng tôi làm điều đó. nếu có một mối quan tâm làm cho ALIGN () lớn hơn để chúng ta luôn nằm trong không gian của chúng ta cho những lần lấp đầy này.
Vì vậy, giải pháp đơn giản của tôi, mang nó hoặc để lại nó. hoan nghênh sửa bất kỳ lỗi nào, tôi không chạy nó trên phần cứng cũng như trình giả lập của mình ...
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
đặt tất cả lại với nhau và bạn nhận được:
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
lưu ý rằng điều này hoạt động với arm-none-eabi- và arm-linux-gnueabi và các biến thể khác vì không có công cụ ghee whiz nào được sử dụng.
Bạn sẽ thấy khi bạn nhìn xung quanh rằng mọi người sẽ phát điên với những thứ ghee whiz trong các tập lệnh liên kết của họ, những thứ nhà bếp khổng lồ quái dị. Tốt hơn là chỉ biết làm thế nào để làm điều đó (hoặc tốt hơn là làm chủ các công cụ để bạn có thể kiểm soát những gì đang diễn ra) thay vì dựa vào công cụ của ai đó và không biết nó sẽ bị phá vỡ ở đâu vì bạn không hiểu và / hoặc muốn nghiên cứu nó
như một quy tắc chung, đừng bootstrap một ngôn ngữ có cùng ngôn ngữ (bootstrap theo nghĩa này có nghĩa là chạy mã không biên dịch một trình biên dịch với cùng một trình biên dịch), bạn muốn sử dụng một ngôn ngữ đơn giản hơn với ít bootstrap hơn. Đó là lý do tại sao C được thực hiện trong lắp ráp, nó không có yêu cầu bootstrap mà bạn chỉ bắt đầu từ hướng dẫn đầu tiên sau khi thiết lập lại. JAVA, chắc chắn bạn có thể viết jvm bằng C và bootstrap mà C bằng asm sau đó bootstrap JAVA nếu bạn muốn với C nhưng cũng thực hiện JAVA trong C nữa.
Bởi vì chúng tôi kiểm soát các giả định trên các vòng lặp sao chép này, theo định nghĩa chặt chẽ và sạch sẽ hơn so với memcpy / memset điều chỉnh bằng tay.
Lưu ý vấn đề khác của bạn là đây:
unsigned int * bss_start_p = &_BSS_START;
unsigned int * bss_end_p = &_BSS_END;
Nếu đây là tiền phạt cục bộ, không có vấn đề gì, nếu đây là toàn cục thì bạn cần .data khởi tạo trước để chúng hoạt động và nếu bạn thử mẹo đó để làm .data thì bạn sẽ thất bại. Biến cục bộ, tốt mà sẽ làm việc. nếu bạn vì một lý do nào đó quyết định thực hiện các địa phương tĩnh (toàn cầu địa phương tôi muốn gọi cho họ) thì bạn sẽ lại gặp rắc rối. Mỗi khi bạn thực hiện một nhiệm vụ trong một tuyên bố mặc dù bạn nên nghĩ về nó, nó được thực hiện như thế nào và nó có an toàn / lành mạnh không. Mỗi khi bạn giả sử một biến là 0 khi không được khai báo, cùng một giao dịch, nếu một biến cục bộ thì nó không được coi là 0, nếu là toàn cục thì nó là. nếu bạn không bao giờ cho rằng chúng bằng 0 thì bạn không bao giờ phải lo lắng.