VOOZH about

URL: https://qiita.com/Shohei_miyasako/items/dc112be3912448e9da34

⇱ 12Stepで作る 組込みOS自作入門 3ndステップ ~静的変数の読み書き #リンカスクリプト - Qiita


👁 Image
4

Go to list of users who liked

2

Share on X(Twitter)

Share on Facebook

Add to Hatena Bookmark

More than 3 years have passed since last update.

@Shohei_miyasako(Shohei Miyasako)

12Stepで作る 組込みOS自作入門 3ndステップ ~静的変数の読み書き

4
Last updated at Posted at 2022-01-23

はじめに

・学習本:12ステップで作る 組込みOS自作入門
・ソースコード:こちら の「osbook_03.zip」
・ハードウェアマニュアル:こちら

物理メモリと仮想メモリ

・汎用OSではメモリ・マップを意識することは少ない。
 仮想メモリという機構が働くため、各アプリで必要なメモリ量を
 要求するだけでよい。(ex.アプリxは0x00000000~0x0000FFFFを使用)
 実際にデータを保存する物理メモリ( + HDD、SDD など)への紐づけには
 MMU(Memory Management Unit)を使用する。

・組込みプログラミングでは仮想メモリの機能は実装しない。
 そのため、メモリ・マップの意識が必要。

 仮想メモリの説明はこちらが役に立った。

ROMとRAM

・ROM(Read Only Memory)はプログラム側からの書き込みは不可
電源OFFでも内容が保持される。
 H8/3069Fは電気的に内容の書き換えが可能フラッシュROM

・RAM(Random Access Memory)はプログラム側からの書き込みは可能
電源OFFで内容は失われる。

・2章での説明で外部DRAMの接続などでもアドレスを指定することができる。
 しかし基盤の大きさを考慮して、組込み機器向けのCPUではROMとRAMが
 内蔵している場合が多い。(512KBのROMと16KBのRAM)

H8/3069Fのメモリマップ

今回はマニュアルのP82、モード5で動作している。
👁 image.png

メモリと領域

・そのためCPUが
 プログラムを実行するためには、実行形式ファイルをメモリ上にコピーする。
 コピーは領域単位で行われる。

領域名 レジスタ
テキスト領域 CPUが実行する機械語コード
データ領域 初期値を持つ静的変数
BSS領域 初期値を持たない静的変数

・関数内で定義した変数が動的変数。それ以外の変数が静的変数。
・データ領域は値を定義しているので、実行形式ファイルの段階で
 値を保持しておく必要がある。
・BSS領域では値を定義していないので、実行形式の段階ではサイズ情報のみ
 保持して、プログラムの実行時にメモリ上に確保する。
 

セクション

・実行形式ファイル内には機械語の命令だけがただ羅列しているのではない。
 領域ごとに保持して、また領域の先頭に付加情報である「ヘッダ」を持っている。
 
・ファイルの中身の確認。本実行形式はELF形式のため、以下のコマンドを実行。

$ readelf -a kzload.elf
ELF Header:
 Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
 Class: ELF32
 Data: 2's complement, big endian
 Version: 1 (current)
 OS/ABI: UNIX - System V
 ABI Version: 0
 Type: EXEC (Executable file)
 Machine: Renesas H8/300
 Version: 0x1
 Entry point address: 0x100
 Start of program headers: 52 (bytes into file)
 Start of section headers: 1204 (bytes into file)
 Flags: 0x810000
 Size of this header: 52 (bytes)
 Size of program headers: 32 (bytes)
 Number of program headers: 2
 Size of section headers: 40 (bytes)
 Number of section headers: 8
 Section header string table index: 5

Section Headers:
 [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
 [ 0] NULL 00000000 000000 000000 00 0 0 0
 [ 1] .vectors PROGBITS 00000000 000074 000100 00 WA 0 0 4
 [ 2] .text PROGBITS 00000100 000174 0002dc 00 AX 0 0 2
 [ 3] .rodata PROGBITS 000003dc 000450 00001f 01 AMS 0 0 1
 [ 4] .data PROGBITS 000003fc 000470 00000c 00 WA 0 0 4
 [ 5] .shstrtab STRTAB 00000000 00047c 000038 00 0 0 1
 [ 6] .symtab SYMTAB 00000000 0005f4 0003c0 10 7 44 4
 [ 7] .strtab STRTAB 00000000 0009b4 000167 00 0 0 1
Key to Flags:
 W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
 L (link order), O (extra OS processing required), G (group), T (TLS),
 C (compressed), x (unknown), o (OS specific), E (exclude),
 D (mbind), p (processor specific)

There are no section groups in this file.

Program Headers:
 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
 LOAD 0x000074 0x00000000 0x00000000 0x003fb 0x003fb RWE 0x1
 LOAD 0x000470 0x000003fc 0x000003fc 0x0000c 0x0000c RW 0x1

 Section to Segment mapping:
 Segment Sections...
 00 .vectors .text .rodata
 01 .data

There is no dynamic section in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type Renesas H8/300 is not currently supported.

Symbol table '.symtab' contains 60 entries:
 Num: Value Size Type Bind Vis Ndx Name
 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
 1: 00000000 0 SECTION LOCAL DEFAULT 1 .vectors
 2: 00000100 0 SECTION LOCAL DEFAULT 2 .text
 3: 000003dc 0 SECTION LOCAL DEFAULT 3 .rodata
 4: 000003fc 0 SECTION LOCAL DEFAULT 4 .data
 5: 00000000 0 FILE LOCAL DEFAULT ABS vector.c
 6: 0000010a 0 NOTYPE LOCAL DEFAULT 2 .L1^B1
 7: 00000000 0 FILE LOCAL DEFAULT ABS main.c
 8: 0000014c 0 NOTYPE LOCAL DEFAULT 2 .L2
 9: 00000000 0 FILE LOCAL DEFAULT ABS lib.c
 10: 00000162 0 NOTYPE LOCAL DEFAULT 2 .L7
 11: 00000156 0 NOTYPE LOCAL DEFAULT 2 .L8
 12: 00000184 0 NOTYPE LOCAL DEFAULT 2 .L15
 13: 00000176 0 NOTYPE LOCAL DEFAULT 2 .L16
 14: 000001be 0 NOTYPE LOCAL DEFAULT 2 .L26
 15: 000001b6 0 NOTYPE LOCAL DEFAULT 2 .L21
 16: 000001b0 0 NOTYPE LOCAL DEFAULT 2 .L22
 17: 000001c0 0 NOTYPE LOCAL DEFAULT 2 .L17
 18: 0000019c 0 NOTYPE LOCAL DEFAULT 2 .L27
 19: 000001dc 0 NOTYPE LOCAL DEFAULT 2 .L34
 20: 000001d2 0 NOTYPE LOCAL DEFAULT 2 .L35
 21: 000001fa 0 NOTYPE LOCAL DEFAULT 2 .L38
 22: 000001ec 0 NOTYPE LOCAL DEFAULT 2 .L37
 23: 00000210 0 NOTYPE LOCAL DEFAULT 2 .L53
 24: 0000022c 0 NOTYPE LOCAL DEFAULT 2 .L50
 25: 00000226 0 NOTYPE LOCAL DEFAULT 2 .L45
 26: 00000220 0 NOTYPE LOCAL DEFAULT 2 .L46
 27: 0000022e 0 NOTYPE LOCAL DEFAULT 2 .L41
 28: 00000208 0 NOTYPE LOCAL DEFAULT 2 .L55
 29: 0000025e 0 NOTYPE LOCAL DEFAULT 2 .L57
 30: 00000258 0 NOTYPE LOCAL DEFAULT 2 .L60
 31: 00000252 0 NOTYPE LOCAL DEFAULT 2 .L61
 32: 0000026c 0 NOTYPE LOCAL DEFAULT 2 .L56
 33: 00000266 0 NOTYPE LOCAL DEFAULT 2 .L59
 34: 0000026a 0 NOTYPE LOCAL DEFAULT 2 .L58
 35: 00000244 0 NOTYPE LOCAL DEFAULT 2 .L63
 36: 00000290 0 NOTYPE LOCAL DEFAULT 2 .L65
 37: 000002bc 0 NOTYPE LOCAL DEFAULT 2 .L71
 38: 000002b0 0 NOTYPE LOCAL DEFAULT 2 .L72
 39: 000002ea 0 NOTYPE LOCAL DEFAULT 2 .L86
 40: 0000030e 0 NOTYPE LOCAL DEFAULT 2 .L75
 41: 00000000 0 FILE LOCAL DEFAULT ABS serial.c
 42: 000003fc 12 OBJECT LOCAL DEFAULT 4 _regs
 43: 000003ae 0 NOTYPE LOCAL DEFAULT 2 .L4
 44: 00000202 50 NOTYPE GLOBAL DEFAULT 2 _strcmp
 45: 00000000 256 OBJECT GLOBAL DEFAULT 1 _vectors
 46: 00000276 46 NOTYPE GLOBAL DEFAULT 2 _putc
 47: 000002a4 36 NOTYPE GLOBAL DEFAULT 2 _puts
 48: 00000362 36 NOTYPE GLOBAL DEFAULT 2 _serial_is_send_[...]
 49: 00000168 40 NOTYPE GLOBAL DEFAULT 2 _memcpy
 50: 0000014e 26 NOTYPE GLOBAL DEFAULT 2 _memset
 51: 00000100 0 NOTYPE GLOBAL DEFAULT 2 _start
 52: 0000032c 54 NOTYPE GLOBAL DEFAULT 2 _serial_init
 53: 000002c8 100 NOTYPE GLOBAL DEFAULT 2 _putxval
 54: 000001e4 30 NOTYPE GLOBAL DEFAULT 2 _strcpy
 55: 00000190 58 NOTYPE GLOBAL DEFAULT 2 _memcmp
 56: 00000234 66 NOTYPE GLOBAL DEFAULT 2 _strncmp
 57: 000001ca 26 NOTYPE GLOBAL DEFAULT 2 _strlen
 58: 00000386 86 NOTYPE GLOBAL DEFAULT 2 _serial_send_byte
 59: 0000010c 66 NOTYPE GLOBAL DEFAULT 2 _main

Section Headers:

・ELF形式はファイルの内部をセクションという単位で区切っている。
 「.vectors」「.text」「.rodata」・・・

Symbol table '.symtab'

・各領域のメモリ上への配置位置
 例1:serial.cの配列regs[]はシンボル名は「_regs」、メモリ上で「0x000003fc」
   これは初期値を定義しているので、データ領域に配置される。
   確かに「.data」はメモリ上で「0x000003fc」に配置している。

 例2:main.cの関数main()は、メモリ上で「0x0000014c」
   これは関数(機械語の命令)を定義しているので、テキスト領域に配置される。
   確かに「.text」はメモリ上で「0x00000100」に配置している。

変数の配置

・自動変数はスタックに割り当てられる。
・静的変数は静的領域(データ領域 or BSS領域)に割り当てられる。

しかし、問題が...
・現状のソースでは静的変数を書きかえたい場合、ROMに配置されているので
 書き換えることができない。

int a = 5;

main(){
 a = 10; 
 ・・・
}

リンカ・スクリプト


 そのため、起動時に動作するプログラムはROM上に存在する必要がある。


 リンクの際にどの部分をどのアドレスに配置するか定義する必要がある。
 → というファイルで指定する。実行形式ファイルを作成する際に、機械語コードや静的変数をどのアドレスに割り当てるか指示するためのファイル。

リンカ・スクリプトの説明

SECTIONS
{
	/* メモリの先頭番地から配置 */
	. = 0x0;

	/* 割込みベクタ*/
	.vectors : {
		vector.o(.data)
	}

	/*テキスト領域*/
	.text : {
		*(.text)
	}

	.rodata : {
		*(.strings)
		*(.rodata)
		*(.rodata.*)
	}

	/*データ領域*/
	.data : {
		*(.data)
	}

	/*BSS領域*/
	.bss : {
		*(.bss)
		*(COMMON)
	}
}

. = 0x0

・「.」はロケーションカウンタでカレント・アドレスを指す。

.vectors :

・「.vectors」というセクションを作成、その中にvector.oの
 .dataセクションの内容(割込みベクタの配列)を配置する。
 vector.oとは、vector.cをコンパイルしてできるオブジェクトファイル。
 

.text :

・「.text」というセクションを作成、その中に全てのオブジェクトファイル(*)の.textセクションの内容(機械語コード)を配置する。

.rodata :

・「.rodata」というセクションを作成。その中にConstで定義した文字列や
 文字列リテラルなどが配置される。
 文字列リテラルとは「"~"」で囲まれた文字列。

静的変数の配置

・現状、.dataと.bssセクションは.rodataの続きに配置される。
 つまりROMに配置されてしまう。

・では、書き込むときにRAM領域(0xffbf20~)から書き込みを開始すればよOK・・・?
 問題①:H8/3069Fの仕様としてフラッシュROMにしか書き込みできない。
 問題②:RAMに配置すると電源OFFで消える。

・問題①、②の対策
 一旦ROMに書き込んだ後に、実行時にRAMにコピー、その後はRAMを参照する。
 

物理アドレスと仮想アドレス

・物理アドレス・・・変数の初期値を配置するアドレス(Physical Address)
・仮想アドレス・・・プログラムが変数にアクセス際のアドレス(Virtual Address)
 
 セクションの「Program Headers:」以下の「VirtAddr」「PhysAddr」が該当

ELF形式のセクションとセグメントの違い

・セグメント・・・プログラムの実行時にはメモリ上に展開(ロード)するために参照
 セクション・・・リンク時に同じ内容の領域をリンカがまとめるために参照

BackNumber

1.12ステップで作る組込みOS自作入門 1stステップ
2.[12ステップで作る組込みOS自作入門 2ndステップ]
(https://qiita.com/Shohei_miyasako/items/9cf94b177ef39775ad28)

4

Go to list of users who liked

2
0

Go to list of comments

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4

Go to list of users who liked

2