Using the .org directive with data in the .data section: In relation to ld
In my attempts to figure out how to use GNU binutils to create a simple bootloader using gas I came across the question of how do you tell the linker where to put its data in the file that uses. org to advance the location counter while keeping the file size 512 bytes. I can't seem to find a way to do this.
The build program that tries to do this:
# Author: Matthew Hoggan
# Date Created: Tuesday, Mar 6, 2012
.code16 # Tell assembler to work in 16 bit mode
.section .data
msg: # Message to be printed to the screen
.asciz "hello, world"
.section .text
.globl _start # Help linker find start of program
_start:
xor %ax, %ax # Zero out ax register (ah used to specify bios function to Video Services)
movw %ax, %ds # Since ax is 0x00 0x00 use it to set data segment to 0
mov $msg, %si # Use source index as pointer to string
loop:
movb %ds:(%si), %al # Pass data to BIOS function in low nibble of ax
inc %si # Advance the pointer
or %al, %al # If byte stored in al is equal to zero then...
jz _hang # Zero signifies end of string
call print_char # Print current char in al
jmp loop # Repeat
#
# Function that uses bios function calls
# to print char to screen
#
print_char:
movb $0x0e, %ah # Function to print a character to the screen
movb $0x07, %bl # color/style to use for the character
int $0x10 # Video Service Request to Bios
ret
#
# Function used as infinite loop
#
_hang:
jmp _hang
.org 510
.byte 0x55, 0xAA
.end
UPDATE Using the following commands, I get the following error:
mehoggan@mehoggan-laptop:~/Code/svn_scripts/assembly/bootloader/gas$ ld --oformat binary -o string string.o
string.o: In function `_start':
(.text+0x5): relocation truncated to fit: R_X86_64_16 against `.data'
source to share
For this to work, you must write your own linker script . Just pass it to the linker with the option -T
.
My script for a nearly identical problem was:
SECTIONS
{
. = 0x1000;
bootsec :
{
*(.text)
*(.data)
*(.rodata)
*(.bss)
endbootsec = .;
. = 0x1FE;
SHORT(0xAA55)
}
endbootsecw = endbootsec / 2;
image = 0x1200;
}
With this trick, you don't need to put 0x55 0xAA
in assembler!
0x1000
at the beginning: in fact, all jumps are relative, so they are not used, but this is needed later to enter protected mode ...
endbootsecw
, endbootsec
and image
are symbols used elsewhere in the code.
source to share