Code: Select all
mov eax, 0x0010
mov es, ax
mov si, -2
w:
add si, 2
mov ax, si
mov byte [es:si], al
cmp si, 0xff
jne w
Double post removed - Combuster
Code: Select all
mov eax, 0x0010
mov es, ax
mov si, -2
w:
add si, 2
mov ax, si
mov byte [es:si], al
cmp si, 0xff
jne w
That would beInsightSoft wrote:Does anybody knows how to implements this code in gcc???
I need to trace the problem I'm experiencing calling C 32bit codeCode: Select all
mov eax, 0x0010 mov es, ax mov si, -2 w: add si, 2 mov ax, si mov byte [es:si], al cmp si, 0xff jne w
Code: Select all
uint8* p = (uint8*)0x100;
for (int i = 0; ; i+=2)
{
p[i] = i & 0xFF;
}
Code: Select all
mov eax, 0x0010
mov es, ax
mov si, -2
w:
add si, 2
mov ax, si
mov byte [es:si], al
cmp si, 0xff
jne w
Code: Select all
typedef unsigned char uint8;
int i;
uint8* p = (uint8*)0x100;
for(i = 0; i<= 100 ; i+=2)
{
p[i] = i & 0xFF;
}
00000312 B80000 mov ax,0x0
00000315 0000 add [bx+si],al
00000317 88800001 mov [bx+si+0x100],al
0000031B 0000 add [bx+si],al
0000031D 83C002 add ax,byte 0x2
00000320 83F866 cmp ax,byte 0x66
00000323 75F2 jnz 0x317
Oh, I see.InsightSoft wrote:pardon,
the two instructions allows us to select the selector that represent the video memory (...the selector, gdt and pl, as you know...)
Yes and no. First, you compiled the wrong C code. My assembly to C transcript was an endless loop, but the loop you quoted terminates after 50 iterations. Second, most C compilers target application development (user mode), and assume that all segment registers are set up (by the kernel or by the programmer). Old real-mode C compilers may be an exception to this, however.InsightSoft wrote: following your code (in c) result this opcodes...
As we can see, there is no reference to the selector... it will crash, right?
Code: Select all
00017202782i[BIOS ] Booting from 0000:7c00
00018358895e[CPU0 ] write_virtual_checks(): no write access to seg
00018358895i[CPU0 ] CPU is in protected mode (active)
00018358895i[CPU0 ] CS.d_b = 32 bit
00018358895i[CPU0 ] SS.d_b = 16 bit
00018358895i[CPU0 ] EFER = 0x00000000
00018358895i[CPU0 ] | RAX=0000000000000018 RBX=0000000000000000
00018358895i[CPU0 ] | RCX=0000000000000003 RDX=0000000000000000
00018358895i[CPU0 ] | RSP=000000000000ffe3 RBP=0000000000000000
00018358895i[CPU0 ] | RSI=00000000ffff009c RDI=000000000008ffac
00018358895i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00018358895i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00018358895i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00018358895i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00018358895i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af pf cf
00018358895i[CPU0 ] | SEG selector base limit G D
00018358895i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00018358895i[CPU0 ] | CS:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | DS:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | SS:0020( 0004| 0| 0) 00080000 000cffff 0 0
00018358895i[CPU0 ] | ES:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | FS:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | GS:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | MSR_FS_BASE:0000000000090000
00018358895i[CPU0 ] | MSR_GS_BASE:0000000000090000
00018358895i[CPU0 ] | RIP=00000000000004ec (00000000000004ec)
00018358895i[CPU0 ] | CR0=0x60000011 CR1=0x0 CR2=0x0000000000000000
00018358895i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00018358895i[CPU0 ] >> mov dword ptr ds:0x1000, 0x000b8000 : C7050010000000800B0
0
00018358895e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown
status is 00h, resetting
00018358895i[SYS ] bx_pc_system_c::Reset(SOFTWARE) called
There is no way to distinguish code sections from data sections in a binary file without any headers. There are no sections in a binary file to begin with. It's just a big blob of bits.InsightSoft wrote: How can I distinguish the .text, .data and .bss sections? I try to make a simple debug and is not easy... maybe I'm trying with hard way... that's why I came again asking for help...
Code: Select all
at gdt_tbl.dummy, db 0 ;Empty
at gdt_tbl.ks1code, dw 0xFFFF ;[08] size 1 e 2
dw 0x0 ;base 1 e 2
db 0x0 ;base 3
db 0x9a ;flag1 > 1 00 1 1010 > [p=1 (in mem); dpl=10 (level); s=0 (system); segtype=1010] _1 10 0 1010
db 0x0 ;flag2 > 0 0 0 1 1010 > [g=0 (len in byts); d/b=0 (); 0; avl=1; seg size nib=1010 (); ] 00011010
db 0x0 ;base4
; 00 00 00 00 (32 bits) (0000:0000)
; 04|03|01|02 (7000:0000)
at gdt_tbl.ks1video, dw 0x0FA0 ;[16] at run-time:fixed/size 0fA0=4.000 bytes
dw 0x8000 ;base1 e 2
db 0x0B ;base3
db 0x92 ;flag1 > 1 00 1 0010 > [p=1 (in mem); dpl=00 (level); s=1 (not system); segtype=0010]
db 0x0 ;flag2 > 0 0 0 0 0000 > [g=0 (len in bytes); d/b=0 (data); 0; avl=0 (?); sg size nib=0000]
db 0x0 ;at run-time:fixed
;000B8000 32 bits (b800:0000 bits)
;04030102
at gdt_tbl.ks2code, dw 0xffff ;[24] - 32 Bits ---- asm c bootstrap
dw 0x0 ;
db 0x0 ;
db 0x9a ;
db 0xcf ;
db 0x0 ;
at gdt_tbl.c32stack, dw 0xFFFF ;[32] - Stack
dw 0x0
db 0x0
db 0x92
db 0xC
db 0x0
at gdt_tbl.c32code, dw 0xffff ;[40] - 32 Bits ---- C EntryPoint
dw 0x0 ;
db 0x0 ;
db 0x9a ;
db 0xcf ;
db 0x0 ;
at gdt_tbl.c32data, dw 0xffff ;[48] - 32 Bits ---- C Data
dw 0x0 ;
db 0x0 ;
db 0x9a ;
db 0xcf ;
db 0x0 ;
Code: Select all
[BITS 32]
global KernelEntry
KernelEntry:
;setting up the 32 bit stack
mov eax, 0x0020
mov ss, ax
mov esp, 0x0000ffff
;setting up segments
;mov ax, 40
;mov ds, ax
;mov es, ax
;mov fs, ax
;mov gs, ax
;call C Kernel
extern _kernel
call _kernel
;loop endless
jmp $
global _prnt
_prnt:
mov ax, 16
mov es, ax
mov byte [es:0x0], 'I'
ret
global _gdt_flush
extern _gp
_gdt_flush:
lgdt [_gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2
flush2:
ret
Code: Select all
typedef int size_t;
extern size_t strlen(const char *str);
struct gdt_entry
{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
struct gdt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
struct gdt_entry gdt[3];
struct gdt_ptr gp;
extern void gdt_flush();
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
prnt(); //it works fine
gdt[num].base_low = (base & 0xFFFF); //crash here!!!
prnt(); //it will not run
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}
void gdt_install()
{
gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
gp.base = &gdt;
gdt_set_gate(0, 0, 0, 0, 0);
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
gdt_flush();
}
extern void prnt();
int kernel()
{
prnt(); //it works fine
gdt_install();
for (;;);
return 0;
}
I should have noticed it when I posted my earlier reply...InsightSoft wrote: It seems to me that when I work with a variable it crash...
at that point all piece of code is running at descriptor 24 (code and 32 bit)... and doesn't allow any write operation...
Code: Select all
00018358895i[CPU0 ] | CS:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | DS:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | SS:0020( 0004| 0| 0) 00080000 000cffff 0 0
00018358895i[CPU0 ] | ES:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | FS:0018( 0003| 0| 0) 00090000 000fffff 1 1
00018358895i[CPU0 ] | GS:0018( 0003| 0| 0) 00090000 000fffff 1 1
Code: Select all
_gdt_flush:
call _prnt ;work fine
lgdt [_gp] ;crash here
call _prnt ;will not run
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2
flush2:
ret
This one should be easy. If you check the operand of the lgdt instruction in the assembler's listing, you will find that it uses an offset measured from the start of the assembly file. Which is fine as long as the data segment points to the start of the assembly file. However, when you load ds: with selector 0x30, which specifies a descriptor with base address zero and limit four gigabytes (also called a flat segment), the data segment no longer points to the start of the assembly code. You need to compensate for the difference by doing something like this:InsightSoft wrote:Code: Select all
call _prnt ;work fine lgdt [_gp] ;crash here call _prnt ;will not run
Code: Select all
call _prnt
mov ebx, runtime_address_where_the_assembly_code_is_loaded
lgdt [ebx + _gp]
call _prnt
Code: Select all
xor eax, eax
mov ax, ds
shl eax, 4
mov [where_is_my_assembly_code_loaded], eax
...
...
call _print
mov ebx, [where_is_my_assembly_code_loaded]
lgdt [ebx + _gp]
call _print
Why would you want to preserve code that doesn't work? Though I haven't read Bran's tutorial, so I don't know if the code doesn't work generally, or doesn't work for you specifically.InsightSoft wrote:Ok... I will try changing the code...
(even if the original idea were to preserve the code as is) (I took from Bran's Kernel Development Tutorial)
Bran's tutorial uses a flat segment model, totally different to yours. It therefore makes sense that pasting his code into your environment violates assumptions.InsightSoft wrote:Ok... I will try changing the code...
(even if the original idea were to preserve the code as is) (I took from Bran's Kernel Development Tutorial)