bss section mit null initialiseren
-
Wie sieht ein eleganter Startcode in Assembler aus, der die bss section (evtl. auch COMMON) zuverlässig "nullt"?
Bisher (kernel.asm von PrettyOS):
[Bits 32] section .text ; ld needs that for coff format [global KernelStart] KernelStart: mov ax, 0x10 mov ds, ax ; data descriptor --> data, stack and extra segment mov ss, ax mov es, ax xor eax, eax ; null desriptor --> FS and GS mov fs, ax mov gs, ax mov esp, 0x200000 ; set stack below 2 MB limit [extern _main] ; entry point in ckernel.c call _main ; ->-> C-Kernel jmp $ ; hier fehlt nun diese Anweisung, oder macht man das mit einer Schleife?
Linkerskript:
OUTPUT_FORMAT("binary") ENTRY(KernelStart) SECTIONS { . = 0x00010000; .text : { *(EXCLUDE_FILE(shared_pages.o).text) } . = 0x00017000; .text1 : { shared_pages.o(.text) } . = 0x00018000; .data : { *(.data) } .rodata : { *(.rodata) } .bss : { *(.bss) *(COMMON) } }
Wie erledigt crt0 dies genau?
-
Ja, das macht man in einer Schleife. Dazu legst du die an den Anfang der BSS-Sektion und ans Ende jeweils ein Symbol.
... .bss : { __bss_start = .; *(.bss) *(COMMON) } __end = .;
Dann überschreibst du den Speicher von __bss_start bis __end (nicht inklusive) mit Nullen.
-
Linker-Skript:
OUTPUT_FORMAT("binary") ENTRY(KernelStart) SECTIONS { . = 0x00010000; .text : { __code_start = .; *(EXCLUDE_FILE(shared_pages.o).text) } . = 0x00017000; .text1 : { shared_pages.o(.text) } . = 0x00018000; .data : { __data_start = .; *(.data) } .rodata : { __rodata_start = .; *(.rodata) } .bss : { __bss_start = .; *(.bss) *(COMMON) } __end = .; }
-
Was soll ich dazu sagen außer: brilliant!
-
Was soll ich dazu sagen außer: brilliant!
Je kryptischer, desto besser?
Könntest mir noch bei der Zählschleife in kernel.asm helfen, bin leider nicht geübt in Assembler. Idee:
; Anfang auf __bss_start setzen
mov ecx, [__end - __bss_start]
.Schleife:
; Anweisung: setze speicherstelle auf (byte) null
loop .Schleifeoder geht das einfacher mit einer Superanweisung in einer Zeile?
Irgendwas mit times oder space oder ...?Wie sieht das in crt0.s aus?
-
extern __bss_start extern __end mov edi, __bss_start mov ecx, __end sub ecx, __bss_start mov al, 0 rep stosb
-
danke!
kernel.asm:
[Bits 32] section .text ; ld needs that for coff format [global KernelStart] KernelStart: mov ax, 0x10 mov ds, ax ; data descriptor --> data, stack and extra segment mov ss, ax mov es, ax xor eax, eax ; null desriptor --> FS and GS mov fs, ax mov gs, ax mov esp, 0x200000 ; set stack below 2 MB limit extern __bss_start extern __end mov edi, __bss_start mov ecx, __end sub ecx, __bss_start mov al, 0 rep stosb [extern _main] ; entry point in ckernel.c call _main ; ->-> C-Kernel jmp $
-
Es sollte auch gehen das in C mittels memset zu machen.
-
Lüttmoor schrieb:
Es sollte auch gehen das in C mittels memset zu machen.
Das gefällt mir aber besser in Assembler, habe eine solche Datei ja auch in der User-Sektion, da muss wahrscheinlich auch noch so etwas rein, sieht bisher so aus:
ENTRY(_start) OUTPUT_FORMAT(elf32-i386) SECTIONS { . = 0x400000; .text : { *(.text*) } .data : { *(.data*) *(.rodata*) } .bss : { *(.bss) *(COMMON) } }
; start.asm [BITS 32] extern _main global _start _start: mov esp, 0x600000 call _main end: jmp end
jetzt so:
ENTRY(_start) OUTPUT_FORMAT(elf32-i386) SECTIONS { . = 0x400000; .text : { __code_start = .; *(.text*) } .data : { __data_start = .; *(.data) } .rodata : { __rodata_start = .; *(.rodata) } .bss : { __bss_start = .; *(.bss) *(COMMON) } __end = .; }
; start.asm [BITS 32] extern __bss_start extern __end extern _main global _start _start: mov edi, __bss_start mov ecx, __end sub ecx, __bss_start mov al, 0 rep stosb ; repeats instruction decrementing ECX until zero ; and stores value from AL incrementing ES:EDI mov esp, 0x600000 ; stackpointer call _main jmp $