Come individuare correttamente una variabile nell'assembly AT&T?
-
11-12-2019 - |
Domanda
Mi sto esercitando a scrivere un bootstrap utilizzando l'assembly (nella sintassi AT&T e gnu/gas).Il piccolo programma viene assemblato e collegato, quindi copiato nel primo settore di un disco virtuale.Il BIOS lo caricherà 0000:7c00
, e qui nasce il problema.IL call hello
sarà tradotto da call 0010
A call 7c10
durante la corsa.Ma il movw $message, %as
non viene trasferito.IL ax
è ancora 0026
, non 7c26
.Il risultato è che non riesco a farlo Hello World
sullo schermo.Invece, alcuni dati casuali a 0000:0026
verrà visualizzato sullo schermo.
Come posso correggerlo durante l'avvio?Dovrei modificare il codice sorgente asm utilizzando alcune direttive?O dovrei cambiare il mio script di collegamento?
Grazie!
.text
.global _start
.code16
_start:
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
call hello
jmp .
.org 0x10
hello:
movw $message, %ax
movw %ax, %bp
movw $13, %cx
movw $0x1301, %ax
movw $0x000c, %bx
movb $0, %dl
int $0x10
ret
message:
.ascii "Hello, World!"
.org 0x01fe
.byte 0x55
.byte 0xaa
Utilizzo i seguenti script di assemblaggio e collegamento
as -o boot.o boot.s
//generate object code
ld -Ttext 0x0 -e _start -s -o boot.out boot.o
//relocate .text to 0x0
//entry is _start
objcopy -O binary -j .text boot.out boot
//copy .text section to boot
vboxmanage convertfromraw boot boot.vdi --format VDI
//create vdi for virtual box
Soluzione
Vedo che il problema principale è nel modo in cui stai compilando il tuo codice.
I passaggi corretti per far funzionare il codice dovrebbero essere:
as boot.s -c -o boot.o
ld --oformat binary --Ttext 0x7C00 -o boot.bin boot.o
Tieni presente, come altri hanno già detto, che sto superando il --Ttext 0x7C00
parametro a ld
, per forzarlo a riposizionare il tuo codice a quell'indirizzo.
Come ulteriore suggerimento, prova a strutturare il tuo codice in questo modo:
.text
.global _start
.code16
_start:
jmp stage1_start
...
stage1_start:
<your bootloader here>
Tieni presente che questo è compatibile con il modo in cui il codice BIOS esamina i dischi rigidi, poiché dopo 2 byte (la lunghezza della prima istruzione di salto) dovresti posizionare la tabella di descrizione del disco.
Inoltre, puoi rifattorizzare le tue ultime istruzioni in un altro as
-like sintassi come questa:
. = _start + 0x0200 - 2
.short 0x0AA55
Dove il .
la variabile è il contatore della posizione.Guarda a questa pagina per ulteriori informazioni su come funziona questo contatore (nel contesto di ld
, non as
).
Spero che questo ti aiuti!