I've set up a segment in my assembly source called s_data, of which only 3 bytes are defined. My linker script maps these to load at 0x200000. My GDT has an entry pointing to 0x200000, with a limit of 0x1000. DS is loaded with the selector pointing to that segment.
First, take a look at the following from bochs:
Code: Select all
(0) [0x0030007c] 0008:0000007c (unk. ctxt): mov al, byte ptr ds:0x200001 ; a001002000
<bochs:10> s
Next at t=32991012
(0) [0x00300081] 0008:00000081 (unk. ctxt): mov bl, 0xa0 ; b3a0
<bochs:11> sreg
cs:s=0x0008, dh=0x00409830, dl=0x00001000, valid=1
ds:s=0x0010, dh=0x00cf9300, dl=0x0000ffff, valid=7
ss:s=0x0020, dh=0x00409240, dl=0x00007fff, valid=7
es:s=0x0010, dh=0x00409220, dl=0x00001000, valid=1
fs:s=0x0010, dh=0x00409320, dl=0x00001000, valid=1
gs:s=0x0010, dh=0x00409320, dl=0x00001000, valid=1
ldtr:s=0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:s=0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1
gdtr:base=0x00210000, limit=0x2f
idtr:base=0x00000000, limit=0x3ff
<bochs:12> delete 1
<bochs:13> c
00032993553e[CPU0 ] read_virtual_checks(): read beyond limit
00032993553e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00032993553e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00032993553i[CPU0 ] CPU is in protected mode (active)
00032993553i[CPU0 ] CS.d_b = 32 bit
00032993553i[CPU0 ] SS.d_b = 32 bit
00032993553i[CPU0 ] | EAX=00000000 EBX=00026260 ECX=00000001 EDX=000903f2
00032993553i[CPU0 ] | ESP=00007ef0 EBP=00007f00 ESI=000263d3 EDI=000263e3
00032993553i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf ZF af PF cf
00032993553i[CPU0 ] | SEG selector base limit G D
00032993553i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00032993553i[CPU0 ] | CS:0008( 0001| 0| 0) 00300000 00001000 0 1
00032993553i[CPU0 ] | DS:0010( 0002| 0| 0) 00200000 00001000 0 1
00032993553i[CPU0 ] | SS:0020( 0004| 0| 0) 00400000 00007fff 0 1
00032993553i[CPU0 ] | ES:0010( 0002| 0| 0) 00200000 00001000 0 1
00032993553i[CPU0 ] | FS:0010( 0002| 0| 0) 00200000 00001000 0 1
00032993553i[CPU0 ] | GS:0010( 0002| 0| 0) 00200000 00001000 0 1
00032993553i[CPU0 ] | EIP=0000007c (0000007c)
00032993553i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
00032993553i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
(0).[32993553] [0x0030007c] 0008:0000007c (unk. ctxt): mov al, byte ptr ds:0x200001 ; a001002000
Now, this is where it comes back to the problem I was having earlier. 0x200001 is the location of my byte variable (called cury. DS:0x01 is the same thing. But the linker seems to keep me from accessing it with mov al,byte [cury]. Well, it does at least once as shown above!
Is this an error in bochs?
What is the preferred method of referencing my variable? Please, don't point me at something that enables paging, why would I need it?
Below is some of my code, it's sloppy I'm sure.
console.asm (where my variable is defined and accessed):
Code: Select all
;Need access to VID_SEL to print to the video screen
extern VID_SEL
global PrintChar
section s_data
curx db 0
cury db 0
attrib db 0x07
section s_code
;Procedure PrintChar(byte char)
;
;Prints a character to the screen using current attrib, moves curx and cury accordingly
PrintChar:
.c equ 8
push ebp
mov ebp,esp
push eax
push ebx
push ecx
push gs
xor eax,eax
mov al,[cury]
mov bl,160
mul bl
xor ebx,ebx
mov bl,byte [curx]
shl bl,1
add ebx,eax
mov eax,VID_SEL
mov gs,eax
mov cl,[bp+.c]
mov [gs:bx],cl
mov cl,[attrib]
mov [gs:bx+1],cl
inc byte [curx]
cmp byte [curx],81
jne .done
mov byte [curx],0
inc byte [cury]
call Scroll
.done:
pop gs
pop ecx
pop ebx
pop eax
pop ebp
ret 1
Code: Select all
%include "gdtn_inc.asm"
global STACK_SIZE
global CS_SEL
global DS_SEL
global SS_SEL
global VID_SEL
global gdtloc
STACK_SIZE equ 0x8000
SECTION s_gdt
gdtloc:
start_gdt
CS_SEL desc 0x300000,0x1000,D_CODE + D_DPL0 + D_BIG
DS_SEL desc 0x200000,0x1000,D_DATA + D_DPL0 + D_BIG + D_WRITE
GDT_SEL desc 0x210000,0x1000,D_DATA + D_DPL0 + D_BIG + D_WRITE
SS_SEL desc 0x400000,STACK_SIZE - 1,D_DATA + D_DPL0 + D_BIG + D_WRITE
VID_SEL desc 0xB8000,0xf9f,D_DATA + D_DPL0 + D_BIG + D_WRITE
end_gdt
Code: Select all
OUTPUT_ARCH(i386)
OUTPUT_FORMAT(elf32-i386)
INPUT(multiboot.o loader.o gdt.o main.o console.o)
OUTPUT(kernel.bin)
ENTRY(_loader)
phys = 0x00100000;
SECTIONS
{
. = 0x100000;
s_multiboot 0x100000 :
{
*(s_multiboot)
. = ALIGN(4096);
}
s_loader :
{
*(s_loader)
. = ALIGN(4096);
}
. = 0x200000;
s_data 0x200000 :
{
*(s_data)
. = ALIGN(4096);
}
. = 0x210000;
s_gdt 0x210000 :
{
*(s_gdt)
. = ALIGN(4096);
}
. = 0x300000;
s_code 0x300000 :
{
main.o(s_code)
*(s_code)
. = ALIGN(4096);
}
}