Moinsen,
habe hier ein komisches Problem mit dem Global Pointer beim MIPS.
Im Linkerscript steht folgendes:
1 | ENTRY(_start)
|
2 | SECTIONS
|
3 | {
|
4 | /*resetvector*/
|
5 | . = 0x00000000;
|
6 | reset : {
|
7 | *(.text.reset)
|
8 | }
|
9 |
|
10 | /*main*/
|
11 | . = 0x00000400;
|
12 | .text : {
|
13 | *(.text)
|
14 | main.o (.text)
|
15 | }
|
16 |
|
17 | /*.sbss und .sdata benutzt das Global Pointer Register
|
18 | daher passendes Symbol setzen fuer start.s*/
|
19 | _gp = .;
|
20 |
|
21 | }
|
In der start.s setze ich dann auch den gp mit:
1 | .section .text.reset
|
2 | .extern main
|
3 | _start:
|
4 | li $sp, 0x100000 /*1MB*/
|
5 | li $gp, _gp
|
6 | j main
|
li ist ein Pseudobefehl, der nach Größe von _gp ein lui, ein ori oder
eine Kombination aus beiden erzeugt um die Variable ins Register zu
bekommen.
Nun ist mein Programm etwas größer und der Globalpointer wird 17 Bit
lang.
Allerdings werden mit dem li Pseudobefehl nur die untersten 16Bit nach
$gp geladen und das Bit16 wird ignoriert.
Der Offset im restlichen Programm (wenn was aus .sdata geladen werden
soll) ist auch nicht groß genug um über die 64k Grenze zu kommen.
Erst wenn ich das Bit16 manuell in das $gp schreibe funktioniert mein
Programm:
1 | .section .text.reset
|
2 | .extern main
|
3 | _start:
|
4 | li $sp, 0x100000 /*1MB*/
|
5 | lui $gp, 0x1
|
6 | ori $gp, $gp, _gp
|
7 | j main
|
Kann mir wer erklären was ich da falsch mache?
Zum Globalpointer findet sich leider nicht viel an Anleitung, außer:
"Zeigt in die Mitte des 64k Bereichs der .sdata und .sbss"
Nutze den GCC.