turdus wrote:Text mode video ram contains words. Lower byte encodes the char, upper byte encodes attributes. So it's totally wrong if you draw a char at 1, and it shows up instead of changing the colour of first character on screen. The bug will be in your code or linker script I bet.
That sounds reasonable. This is what my code looks like:
Code: Select all
.set ALIGN, 1 << 0
.set MEM_INFO, 1 << 1
.set KLUDGE, 1 << 16
.set MAGIC, 0x1BADB002
.set FLAGS, ALIGN | MEM_INFO | KLUDGE
.set CHECKSUM, -(MAGIC + FLAGS)
.set STACKSIZE, 4096
.set PAGE_TABLE, 0x9000
.set PAGE_PRESENT, 1<<0
.set PAGE_WRITE, 1<<1
.text
.code32
.align 4
mb_header:
.long MAGIC
.long FLAGS
.long CHECKSUM
.long mb_header
.long text
.long data_end
.long kernel_end
.long start
.global start
start:
cld
movl $(stack + STACKSIZE), %esp
movl $PAGE_TABLE, %edi
movl $0x1000, %ecx
xorl %eax, %eax
rep stosw
leal PAGE_TABLE+0x1000, %eax
orl $(PAGE_PRESENT | PAGE_WRITE), %eax
movl %eax, PAGE_TABLE
leal PAGE_TABLE+0x2000, %eax
orl $(PAGE_PRESENT | PAGE_WRITE), %eax
movl %eax, PAGE_TABLE+0x1000
leal PAGE_TABLE+0x3000, %eax
orl $(PAGE_PRESENT | PAGE_WRITE), %eax
movl %eax, PAGE_TABLE+0x2000
leal PAGE_TABLE+0x3000, %edi
movl $(PAGE_PRESENT | PAGE_WRITE), %eax
1:
movl %eax, (%edi)
addl $0x1000, %eax
addl $8, %edi
cmp $0x200000, %eax
jb 1b
movl 0b10100000, %eax
movl %eax, %cr4
movl $PAGE_TABLE, %edx
movl %edx, %cr3
movl $0xC0000080, %ecx
rdmsr
orl $0x00000100, %eax
wrmsr
movl %cr0, %ebx
orl $0x80000001, %ebx
movl %ebx, %cr0
lgdt gdtinfo
ljmp $0x8, $start64
.code64
start64:
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
call main
hang:
hlt
jmp hang
.data
stack:
.space STACKSIZE, 0
gdt:
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00
gdtinfo:
.word .-gdt-1
.long gdt
.long 0
And this is the linker script:
Code: Select all
OUTPUT_FORMAT("elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(start)
SECTIONS {
. = 0x200;
kernel_start = .;
.text ALIGN(4096) : AT( ADDR(.text) ) {
text = .;
*(.text)
*(.rodata)
text_end = .;
}
.data ALIGN(4096) : AT( ADDR(.data) ) {
data = .;
*(.data)
data_end = .;
}
.bss ALIGN(4096) : AT( ADDR(.bss) ) {
bss = .;
*(.bss)
bss_end = .;
}
kernel_end = .;
}
turdus wrote:What interesting, objdump shows your main code starts at 00000000000010c8
but the regdump says the instruction pointer is at 000010c5,
three bytes BEFORE your code. Something is totally wrong with your code.
The objdump was only for the main function. I have some initialization code located before it that enters long mode and calls the function. After main have returned it stays there in a loop where it does nothing. It's probably best if I post the complete objdump.
Code: Select all
kernel: file format elf64-x86-64
Disassembly of section .text:
0000000000001000 <text>:
1000: 02 b0 ad 1b 03 00 add 0x31bad(%rax),%dh
1006: 01 00 add %eax,(%rax)
1008: fb sti
1009: 4f 51 rex.WRXB push %r9
100b: e4 00 in $0x0,%al
100d: 10 00 adc %al,(%rax)
100f: 00 00 add %al,(%rax)
1011: 10 00 adc %al,(%rax)
1013: 00 24 30 add %ah,(%rax,%rsi,1)
1016: 00 00 add %al,(%rax)
1018: 00 40 00 add %al,0x0(%rax)
101b: 00 20 add %ah,(%rax)
101d: 10 00 adc %al,(%rax)
...
0000000000001020 <start>:
1020: fc cld
1021: bc 00 30 00 00 mov $0x3000,%esp
1026: bf 00 90 00 00 mov $0x9000,%edi
102b: b9 00 10 00 00 mov $0x1000,%ecx
1030: 31 c0 xor %eax,%eax
1032: 66 f3 ab rep stos %ax,%es:(%rdi)
1035: 8d 05 00 a0 00 00 lea 0xa000(%rip),%eax # b03b <PAGE_TABLE+0x203b>
103b: 83 c8 03 or $0x3,%eax
103e: a3 00 90 00 00 8d 05 movabs %eax,0xb000058d00009000
1045: 00 b0
1047: 00 00 add %al,(%rax)
1049: 83 c8 03 or $0x3,%eax
104c: a3 00 a0 00 00 8d 05 movabs %eax,0xc000058d0000a000
1053: 00 c0
1055: 00 00 add %al,(%rax)
1057: 83 c8 03 or $0x3,%eax
105a: a3 00 b0 00 00 8d 3d movabs %eax,0xc0003d8d0000b000
1061: 00 c0
1063: 00 00 add %al,(%rax)
1065: b8 03 00 00 00 mov $0x3,%eax
106a: 89 07 mov %eax,(%rdi)
106c: 05 00 10 00 00 add $0x1000,%eax
1071: 83 c7 08 add $0x8,%edi
1074: 3d 00 00 20 00 cmp $0x200000,%eax
1079: 72 ef jb 106a <start+0x4a>
107b: a1 a0 00 00 00 0f 22 movabs 0xbae0220f000000a0,%eax
1082: e0 ba
1084: 00 90 00 00 0f 22 add %dl,0x220f0000(%rax)
108a: da b9 80 00 00 c0 fidivrl -0x3fffff80(%rcx)
1090: 0f 32 rdmsr
1092: 0d 00 01 00 00 or $0x100,%eax
1097: 0f 30 wrmsr
1099: 0f 20 c3 mov %cr0,%rbx
109c: 81 cb 01 00 00 80 or $0x80000001,%ebx
10a2: 0f 22 c3 mov %rbx,%cr0
10a5: 0f 01 15 18 30 00 00 lgdt 0x3018(%rip) # 40c4 <kernel_end+0xc4>
10ac: ea (bad)
10ad: b3 10 mov $0x10,%bl
10af: 00 00 add %al,(%rax)
10b1: 08 00 or %al,(%rax)
00000000000010b3 <start64>:
10b3: 66 b8 10 00 mov $0x10,%ax
10b7: 8e d8 mov %eax,%ds
10b9: 8e c0 mov %eax,%es
10bb: 8e e0 mov %eax,%fs
10bd: 8e e8 mov %eax,%gs
10bf: e8 04 00 00 00 callq 10c8 <main>
00000000000010c4 <hang>:
10c4: f4 hlt
10c5: eb fd jmp 10c4 <hang>
...
00000000000010c8 <main>:
10c8: 55 push %rbp
10c9: 48 89 e5 mov %rsp,%rbp
10cc: 48 83 ec 10 sub $0x10,%rsp
10d0: 48 c7 45 f8 00 80 0b movq $0xb8000,-0x8(%rbp)
10d7: 00
10d8: 48 8b 45 f8 mov -0x8(%rbp),%rax
10dc: c6 00 41 movb $0x41,(%rax)
10df: 48 8b 45 f8 mov -0x8(%rbp),%rax
10e3: 48 83 c0 01 add $0x1,%rax
10e7: c6 00 07 movb $0x7,(%rax)
10ea: c9 leaveq
10eb: c3 retq