Sayısız başka site ve örnek var. On binlerce olmasa da binlerce. Bağlayıcı betikleri ve boostrap kodu, newlib, glibc ile iyi bilinen c kütüphaneleri vardır, ancak bulabileceğiniz başka şeyler de vardır. C'nin C ile önyüklenmesi mantıklı değil.
Sorunuz, kesin olmayan şeyler üzerinde tam bir karşılaştırma yapmaya çalıştığınız yanıtlandı, bilinen bir sınırda başlamayabilir veya bilinen bir sınırda sona ermeyebilir. Bu yüzden daha az şey yapabilirsiniz, ancak kod tam bir karşılaştırma ile çalışmadıysa, bu, bir sonraki bölüme geçmiş .bss'yi sıfırladığınız anlamına gelir; çözüm.
İşte TL gidiyor; DR iyi. Bu dil ile bir dil önyükleme yapmıyorsunuz, bundan kurtulabilirsiniz, ancak bunu yaparken ateşle oynuyorsunuz. Sadece bunu nasıl yapacağınızı öğreniyorsanız, aptal şans ya da henüz ortaya çıkmamış gerçekler değil, dikkatli olmanız gerekir.
Bağlayıcı komut dosyası ve bootstrap kodu çok samimi bir ilişkiye sahiptir, evlidirler, kalçaya katılırlar, büyük bir başarısızlığa yol açan diğeri olmadan gelişmezsiniz. Ne yazık ki linker betiği, bağlayıcılar ve birleştirici tarafından tanımlanan derleme dili tarafından tanımlanır, böylece araç zincirlerini değiştirdiğinizde, her ikisini de yeniden yazmak zorunda kalırsınız. Neden montaj dili? Önyükleme gerektirmez, derlenmiş diller genellikle yapar. C dil kullanımını sınırlamak istemiyorsanız, minimum araç zincirine özgü gereksinimleri olan çok basit bir şeyle başlayacağım, .bss değişkenlerinin sıfır olduğunu varsaymayın (değişken bu dilde hiç başlatılmazsa kodu daha az okunabilir yapar , bundan kaçınmaya çalışın, yerel değişkenler için doğru değildir, bu yüzden topu kullandığınız zamanki gibi olmanız gerekir. millet yine de globals shun, neden .bss ve .data hakkında konuşuyoruz ??? (globals bu seviye çalışma için iyidir ama bu başka bir konudur)) basit çözüm için diğer kural bildirimde değişkenleri başlatmayın, kodda yapın. evet daha fazla flaş yakar, genellikle bol miktarda var, tüm değişkenler zaten tüketen talimatlarla sonuçlanan sabitlerle başlatılmaz.
Korteks-m tasarımından, hiç bir bootstrap kodu olmadığını düşündüklerini söyleyebilir, bu nedenle .data veya .bss desteği yoktur. Global kullanan pek çok kişi olmadan yaşayamaz.
Gnu araç zincirini kullanarak tüm korteks-ms için bu daha az ama minimal fonksiyonel bir örnek yapabilirim, mevcut 9.xx ile hangi sürümleri başlatabileceğinizi hatırlamıyorum. 9. 3'te bir yerlerde linker komut dosyalarını değiştirdim. xx veya 4.xx daha fazla öğrendim ve gnu olarak benim ilk bir kırdı bir şey değişti.
önyükleme:
.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 koduna giriş noktası:
void bounce ( unsigned int );
unsigned int a;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
bağlayıcı komut dosyası.
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
Bunların hepsi daha küçük olabilir ve hala işe yarayabilir, sadece iş yerinde görmek için buraya ekstra şeyler ekleyebilir.
optimize edilmiş yapı ve bağlantı.
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
bazı satıcılar için, 0x08000000 veya 0x01000000 veya benzer adresleri flaş burada eşlenir ve bazı önyükleme modlarında 0x00000000 olarak yansıtılır. bazıları sadece 0x00000000'de yansıtılan flaşın çoğuna sahiptir, bu nedenle vektör tablosu noktasının uygulama flaş alanında sıfır olmasını istemezsiniz. vektör tablosu tabanlı olduğu için hepsi işe yarıyor.
ilk önce korteks-ms sadece başparmak makineleridir ve herhangi bir nedenle bir başparmak fonksiyon adresi uyguladılar, yani lsbit tuhaftır. Araçlarınızı bilin, .thumb_func yönergeleri GNU montajcısına bir sonraki etiketin bir başparmak işlevi adresi olduğunu bildirir. tablodaki +1 şeyi yapmak başarısızlığa yol açacaktır, bunu yapmak için cazip olmayın, doğru yapın. bir işlev bildirmek için başka bir gnu montajcı yolları vardır, bu minimal yaklaşımdır.
4: 00000015
8: 0000001b
c: 0000001b
10: 0000001b
vektör tablosu doğru alamazsanız önyükleme olmaz.
tartışmalı olarak sadece yığın işaretçi vektörüne (yığın işaretçisini kodda kendiniz ayarlamak istiyorsanız oraya bir şey koyabilirsiniz) ve sıfırlama vektörüne ihtiyacınız vardır. Buraya özel bir sebep olmadan dört tane koydum. Genellikle 16 koydu ama bu örneği kısaltmak istedi.
Peki bir C önyüklemesinin yapması gereken en az şey nedir? 1. yığın işaretçisini ayarlayın 2. sıfır .bss 3. .data 4. dalını C giriş noktasına kopyalayın veya çağırın
C giriş noktasına genellikle main () denir. ancak bazı araç zincirleri main () öğesini görür ve kodunuza fazladan çöp ekler. Kasten farklı bir isim kullanıyorum. YMMV.
eğer tüm ram tabanlıysa .data kopyası gerekli değildir. bir korteks-m mikrodenetleyici olarak teknik olarak mümkündür ancak .data kopyası gerekiyorsa olası değildir.
İlk örneğim ve bir kodlama stili, bu örnekte olduğu gibi .data veya .bss'ye güvenmemektir. Kol yığın işaretçisine dikkat etti, böylece geriye kalan tek şey giriş noktasını aramak. Giriş noktasının geri dönmesini istiyorum, birçok insan bunu asla yapmamanız gerektiğini savunuyor. o zaman bunu yapabilirsin:
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word centry
.word done
.word done
.word done
ve centry () 'den dönmüyor ve işleyici kodunu sıfırlamıyor.
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
linker istediğimiz şeyleri koydu. Ve genel olarak tamamen işlevsel bir programımız var.
Bağlayıcı komut dosyası üzerinde ilk çalışma:
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 ve ram isimlerinin hiçbir anlamı olmadığını vurgulayarak, sadece bölümler arasındaki bağlayıcı için noktaları birleştirirler.
.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__
araçların ne yaptığını görebilmemiz için bazı öğeler ekleyin
void bounce ( unsigned int );
unsigned int a;
unsigned int b=4;
unsigned char c=5;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
bu bölümlere yerleştirilecek bazı öğeler ekleyin. ve Al
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
İşte bu deneyde aradığımız şeyler olmak (herhangi bir kodu yüklemek veya çalıştırmak için hiçbir neden olmadığını unutmayın ... araçlarınızı tanıyın, öğrenin)
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
burada öğrendiğimiz şey, gnu linker komut dosyalarında değişkenlerin konumunun çok hassas olmasıdır. konumuna dikkat data_rom_start vs data_start ama neden yapar data_end işi? Bunu çözmene izin vereceğim. Zaten bir kişinin neden linker betikleriyle uğraşmak istemeyeceğini ve sadece basit programlamaya ulaşmak istemediğini anlıyoruz ...
burada öğrendiğimiz bir diğer şey ise linker data_rom_start bizim için hizalandı , orada bir ALIGN (4) gerek yoktu. Bunun her zaman işe yarayacağını varsaymalı mıyız?
Ayrıca çıkış yolunda doldurduğumuzu, 5 byte'lık bir veriye sahip olduğumuzu ancak 8'e doldurduğumuzu unutmayın. Herhangi bir ALIGN () olmadan kopyaları zaten kelimelerle yapabiliriz. Bugün bilgisayarımda bu araç zinciri ile gördüğümüze dayanarak, bu geçmiş ve gelecek için doğru olabilir mi? Kim bilir, ALIGN'larla bile bazı yeni sürümlerin bir şeyleri kırmadığını onaylamak için periyodik olarak kontrol etmesi gerekir, bunu zaman zaman yapacaklardır.
o denemeden sadece güvenli olmak için buna geçelim.
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ğer insanların yaptıklarıyla tutarlı olmak için uçları içeride hareket ettirmek. Ve bu değişmedi:
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
bir hızlı test daha:
.globl bounce
bounce:
nop
bx lr
vererek
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
sıçrama ve .align arasında padlemeye gerek yok
Ohh, doğru, şimdi neden _end__'i içeri koymadığımı hatırlıyorum. çünkü ÇALIŞMIYOR.
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__;
}
Bu bağlayıcı komut dosyası ile evlenmek için basit ama çok taşınabilir bazı kodlar
.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__
vererek
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
orada durabiliriz veya devam edebiliriz. Linker komut dosyası ile aynı sırayla başlatırsak, henüz oraya gitmediğimiz için bir sonraki şeye geçersek sorun olmaz. ve stm / ldm yalnızca sözcüklerle hizalanmış adresleri kullanmak için gereklidir / istenir, dolayısıyla şu şekilde değiştirirseniz:
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:
link betiğinde ilk bss ile ve evet bls değil ble istiyorum.
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
bu döngüler daha hızlı gidecek. şimdi ahb veriyollarının 64 bit genişliğinde olup olmadığını bilmiyorum ama tam boyutlu bir kol için bu şeyleri 64 bit sınırlarında hizalamak istersiniz. 32 bitlik bir sınır üzerinde dört kayıt ldm / stm, ancak 64 bitlik bir sınır olmayan üç ayrı veri yolu işlemi haline gelir, burada 64 bitlik bir sınıra hizalanmış, talimat başına birkaç saat tasarrufu sağlayan tek bir işlemdir.
çünkü baremetal yapıyoruz ve önce bss diyebileceğimiz her şeyden tamamen sorumluyuz, sonra veri yaparsak yığın yaparsak, o zaman yığın yukarıdan aşağıya doğru büyür, bu yüzden bss'i sıfırlar ve başladığımız sürece biraz üzerine dökülürsek doğru yeri bu hafızayı henüz kullanmıyoruz. sonra biz .data kopyalayın ve yığın thats güzel, yığın ya da değil dökmek için yığın için boş yer var, bu yüzden biz kimseye / hiçbir şey üzerine basmıyoruz (sürece biz linker komut emin olun. bir endişeniz varsa, ALIGN () 'ları daha büyük hale getirin, böylece bu dolgular için her zaman alanımızda yer alırız.
benim basit çözümüm, al ya da bırak. Herhangi bir hatayı düzeltmek hoş geldiniz, bunu donanımda veya simülatörde çalıştırmadım ...
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
hepsini bir araya getirin ve elde edersiniz:
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
bunun ghee whiz şeyler kullanılmadığı için arm-none-eabi- ve arm-linux-gnueabi ve diğer varyantlarla çalıştığını unutmayın.
Etrafınıza baktığınızda, halkın linker senaryolarında ghee whiz şeyleri ile çıldırdığını göreceksiniz, büyük canavarca mutfak lavabo şeyleri. Birinin başkalarına güvenmekten ziyade, nerede yapılacağını bilmemek yerine, nasıl yapılacağını bilmek (veya araçlarda nasıl ustalaşılacağını daha iyi bilmek) ve nerede kırılacağını bilmemek daha iyidir çünkü o.
Genel bir kural olarak, aynı dilde bir dil önyükleme yapmayın (bu anlamda önyükleme, aynı derleyiciye sahip bir derleyiciyi derlemeyen çalıştırma kodu anlamına gelir), daha az önyükleme ile daha basit bir dil kullanmak istersiniz. Bu yüzden C montajda yapılır, sıfırlamadan sonra ilk talimattan başlamanız için hiçbir önyükleme gereksinimi yoktur. JAVA, C jvm yazabilirsiniz ve asm ile C bootstrap sonra C ile yapacaksanız JAVA bootstrap ama aynı zamanda C de JAVA yürütmek olabilir.
Bu kopya döngülerindeki varsayımları kontrol ettiğimiz için, tanım gereği elle ayarlanmış memcpy / memset'ten daha sıkı ve temizler.
Diğer sorununuzun şu olduğuna dikkat edin:
unsigned int * bss_start_p = &_BSS_START;
unsigned int * bss_end_p = &_BSS_END;
eğer bunlar yerel para cezası ise, sorun değil, eğer bunlar küresel ise, ilk önce onların çalışması için .data başlatmanız gerekir ve eğer bu hile .data yapmak için denerseniz o zaman başarısız olacak. Yerel değişkenler, işe yarayacak para cezası. Eğer herhangi bir nedenle statik yerliler (onları aramak istiyorum yerel küreseller) yapmaya karar verdiyseniz o zaman tekrar belada olmak için vardır. Deklarasyonda her ne zaman bir görev yaparsanız düşünün, bu nasıl uygulanır ve güvenli / aklı başındadır. Bir değişkenin bildirilmediği zaman sıfır olduğunu varsaydığınızda, aynı anlaşma, eğer yerel bir değişken sıfır olarak kabul edilmezse, küresel ise. Eğer asla sıfır olduklarını varsaymazsanız, asla endişelenmenize gerek yoktur.