Page 2 of 3

Re: problem with printing string !

Posted: Mon Nov 20, 2017 7:02 am
by osdevnewbie
MichaelPetch wrote: what is the file size of kernel.bin?
152 bytes

Re: problem with printing string !

Posted: Mon Nov 20, 2017 7:21 am
by osdevnewbie
I don't know if it's a good idea, at least aesthetically, to post all the code here. But i'll do since it's not very long. Perhaps some one can give it a try (with MINGW please).
the boot sector source code: boot.asm

Code: Select all

[ bits 16]
[org 0x7c00]
KERNEL_OFFSET equ 0x1000

mov [BOOT_DRIVE], dl	
mov bp, 0x9000
mov sp, bp

mov bx, MSG_REAL_MODE
call print_string

;load_kernel:
mov bx, MSG_LOAD_KERNEL
call print_string

mov bx, KERNEL_OFFSET
mov dh, 15
mov dl, [BOOT_DRIVE]
call disk_load
call switch_to_pm
jmp $

;==============
print_string:
	mov ah, 0x0e
loop:
	mov al, [bx]
	cmp al, 0
	je out
	int 0x10
	add bx, 0x01
	jmp loop
out:
	mov al, ' '
	int 0x10
	ret
;====================
disk_load:
	push dx
	mov ah, 0x02	
	mov al, dh	
	mov ch, 0x00	
	mov dh, 0x00		
	mov cl, 0x02
	int 0x13	
	jc disk_error
	pop dx
	cmp dh, al
	jne disk_error
	ret
disk_error:
	mov bx, [DISK_ERROR_MSG]
	call print_string
	jmp $

DISK_ERROR_MSG:
	db 'Disk read Error!', 0
;=======
switch_to_pm:
	cli	
	lgdt [gdt_descriptor]
	mov eax, cr0
	or eax, 0x1
	mov cr0, eax
	jmp CODE_SEG:init_pm

[bits 32]
init_pm:
	mov ax, DATA_SEG	 
	mov ds, ax		 
	mov ss, ax		 
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ebp, 0x90000
	mov esp, ebp
	mov ebx, MSG_PROT_MODE
	call print_string_pm

	call KERNEL_OFFSET
	jmp $

;=================
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f

print_string_pm:
	pusha
	mov edx, VIDEO_MEMORY
	print_string_pm_loop:
		mov al, [ebx]
		mov ah, WHITE_ON_BLACK
		cmp al, 0
		je done
		mov [edx], ax
		add edx, 2
		add ebx, 1
		jmp print_string_pm_loop
	done:
		popa
		ret
;===================
; GDT tabel
gdt_start:
	dd 0x0
	dd 0x0
gdt_code:
	dw 0xffff	
	dw 0x0		
	db 0x0		
	db 10011010b	
	db 11001111b	
	db 0x0		
gdt_data:
	dw 0xffff	
	dw 0x0		
	db 0x0		
	db 10010010b	
	db 11001111b	
	db 0x0		
gdt_end:	
gdt_descriptor:
	dw gdt_end - gdt_start - 1	
	dd gdt_start			

CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start

BOOT_DRIVE:
	db 0
MSG_REAL_MODE:
	db " Started in 16- bit Real Mode ", 0
MSG_PROT_MODE:
	db " Successfully landed in 32- bit Protected Mode ", 0
MSG_LOAD_KERNEL:
	db " Loading kernel into memory. ", 0

times 510-($-$$) db 0
dw 0xaa55
the kernel entry point "kernel_entry.asm" :

Code: Select all

[bits 32]
[extern _kmain]
call _kmain
jmp $ 
NOTE the underscore and the name of the main function it must be different than "main" else the linker will be unhappy!
The kernel source code "kernel.c":

Code: Select all

void kmain(void)
{
	const char *str = "Hello World!!";
	char *vidmem = (char*)0xb8000;
	unsigned int i; 
        // print char 'A' OK
	*vidmem ='A';
	*(vidmem+1) =0xA5;
	
       // first version to print the string NOT OK
	for(i=0;;i++){	
	if(str[i]==0) break;
	*vidmem =str[i];	
        *(vidmem+1) =0xA5;
          vidmem+=2;
	}
	
       // second version to print the string NOT OK
	while(*str != 0) {
		*vidmem= *str;
		vidmem+=2;
		str++;
	}

	// print char 'M' on the next line OK
	vidmem +=160;
	*vidmem ='M';
	*(vidmem+1) =0xA5;

	for(;;);
}
And last the makefile:

Code: Select all

# Default make target
all: os.img 

# Build the os image
os.img: boot.bin kernel.bin 
	cat boot.bin kernel.bin > os.img

# Build the kernel binary
kernel.bin: kernel_entry.o kernel.o
	ld -T NUL -o kernel.tmp -Ttext 0x1000 kernel_entry.o kernel.o
	objcopy -O binary -j .text  kernel.tmp kernel.bin

# Build the kernel object file
kernel.O: kernel.C
	gcc -ffreestanding -c kernel.c -o kernel.o

# Build the kernel entry object file
kernel_entry.o: kernel_entry.asm 
	nasm kernel_entry.asm -f elf -o kernel_entry.o

# Build the boot binary
boot.bin: boot.asm 
	nasm -f bin -o boot.bin boot.asm

clean:
	rm -f *.o *.tmp *.bin
the command :
ld -o kernel.bin -Ttext 0x1000 kernel.o --oformat binary
didn't work for me !!

Re: problem with printing string !

Posted: Mon Nov 20, 2017 9:06 am
by osdevnewbie
I've tested bochs with an image of retrounix and it works well.
So the suspect is MINGW.
I get the magic breakpoint working also. I must enable the option in the config file of the debugger (not the one for emulator) and use the debugger to start emulation.

Re: problem with printing string !

Posted: Mon Nov 20, 2017 10:22 am
by osdevnewbie
MichaelPetch wrote:Could you post the output of this command to humour me:

gcc -v
gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/mingw32/bin/../libexec/gcc/mingw32/4.8.1/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-4.8.1/configure --prefix=/mingw --host=mingw32 --build=mingw32 --without-pic --enable-shared --enable-static --with-gnu-ld --enable-lto --enable-libssp --disable-multilib --enable-languages=c,c++,fortran,objc,obj-c++,ada --disable-sjlj-exceptions --with-dwarf2 --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --with-gmp=/usr/src/pkg/gmp-5.1.2-1-mingw32-src/bld --with-mpc=/usr/src/pkg/mpc-1.0.1-1-mingw32-src/bld --with-mpfr= --with-system-zlib --with-gnu-as --enable-decimal-float=yes --enable-libgomp --enable-threads --with-libiconv-prefix=/mingw32 --with-libintl-prefix=/mingw --disable-bootstrap LDFLAGS=-s CFLAGS=-D_USE_32BIT_TIME_T
Thread model: win32
gcc version 4.8.1 (GCC)

Re: problem with printing string !

Posted: Mon Nov 20, 2017 10:31 am
by osdevnewbie
MichaelPetch wrote: Does this work by changing:

Code: Select all

const char *str = "Hello world!";
to

Code: Select all

const char str[] = "Hello world!";
YES this works !

Re: problem with printing string !

Posted: Mon Nov 20, 2017 11:18 am
by osdevnewbie
I really APOLOGIZE I am deeply ashamed.
The mistake was in the makefile:

Code: Select all

    objcopy -O binary -j .text  kernel.tmp kernel.bin
only the .text section is taken !!
I must delete the "-j .text" option to get all sections .
I copied the line as is from somewhere on the web without take care about every option in it

MANY thanks for all of you.

Re: problem with printing string ! [SOLVED]

Posted: Mon Nov 20, 2017 2:13 pm
by Schol-R-LEA
No need to apologize, really, this is the sort of thing that happens to everyone from time to time.

As for the aesthetics of posting the code, it isn't a problem for smaller sections, but for longer ones, we recommend giving a pointer to your offsite repo.

Let me back up a bit, and make a point which is, I hope, not really necessary. Do you have an offsite mirror of your version control repository on a host like CloudForge or GitHub?

Let me back up a bit more, just to be on the safe side: do you have your code under version control with a tool such as Subversion, Git, Bazaar, CVS, darcs, or Mercurial?

If not, then I strongly recommend getting it set up in one ASAP, and then find a suitable free host to keep a publicly accessible where you can keep a publicly-accessible mirror of the repo. Just sayin'. Trust me, you will definitely regret it if you don't have at least a local repository of your code, because sooner or later you are going to change something you didn't meant to, and will need to back your working copy up to a previous version.

That just the most basic use case for version control, but far from the only one - it isn't just about backups, its about managing change. You should still make regular backups of your files anyway, but version control goes beyond that.

Also, the public mirror not only serves as an additional backup copy of the repo, it allows you to show the code to others without having to explicitly post the code to a forum or send it as an attachment in an email.

Sorry for the digression, but I figured this was as good a point as any to mention this, and ask if you have that in hand already or not. Hopefully, you didn't even need this, but it's worth mentioning in case you didn't.

Re: problem with printing string ! [SOLVED]

Posted: Mon Nov 20, 2017 3:09 pm
by MichaelPetch
Glad you got it working. So i essence by using -j text you excluded all the sections but .text including .rdata. I hope you undo the change I had you make to your code as an experiment.

Re: problem with printing string ! [SOLVED]

Posted: Tue Nov 21, 2017 1:08 am
by osdevnewbie
MichaelPetch wrote:Glad you got it working.
Many thanks MichaelPetch again. Due to your suggestions I could fix the problem.
I've two more questions:
1- if I declare a global pointer to video ram I can't clear the screen or print the string:

Code: Select all

char* videmem = (char*)0XB8000;
void clrsc(){
....
*vidmem = ' ';
...........
}
void print(char* str){
.....
*vidmem = *str;
........
}
2- the size of the binary file generated is big (about 12k bytes) !!
Opening it in HXD, it seems that the sections (.text .rdata ...) are 4096 bytes aligned.
Can we disable this alignement ?

Re: problem with printing string ! [SOLVED]

Posted: Tue Nov 21, 2017 1:14 am
by osdevnewbie
Schol-R-LEA wrote:Do you have an offsite mirror of your version control repository on a host like CloudForge or GitHub?
Alas, NO!
I think I'm not so "pro" to have a repo.
I'm only in the first steps. I'm still learning (despite my old age!!) :?

Re: problem with printing string ! [SOLVED]

Posted: Tue Nov 21, 2017 6:00 am
by Solar
Backing up Schol-R-LEA here.

If you don't have a repository / version control software...
  • ...you have no way to trace back when you made which change, and what you were thinking when you made it (commit messages!)
  • ...you have no way to "undo" a change when you later find it was ill-advised
  • ...your project source code can be utterly and irrevocably wiped out with a single, careless, delete operation
If at all possible, keep the repository (or regular backups thereof) on a different computer. Hard drives can die, computers can get stolen, and you don't want your project to just go "poof" when (not if) that happens.

Getting an account with one of the free VCS hosters out there is easy enough. If you cannot / do not want to do this, note that many fileservers offer similar functionality for a comparably small price.

Personally, I've set up my home network so that *everything* is stored on a RAID-1 server (Synology DiskStation), with source code additionally kept in a SVN repo on the disk station and being backed up to cloud storage once a week.

Call it paranoid, but I couldn't care less if a hard drive dies, even in the disk station. Get a new one and get going again.

Re: problem with printing string ! [SOLVED]

Posted: Tue Nov 21, 2017 8:23 am
by osdevnewbie
@ Schol-R-LEA, @solar
No one can deny the pros of a repo. Just at the moment I'm not doing an interesting work that worth it !!
I save always a copy of my work on an external hard disk. Who knows.
Many thanks for the advice any way

Re: problem with printing string ! [SOLVED]

Posted: Tue Nov 21, 2017 8:41 am
by iansjack
If your code is interesting enough that you ask others to spend their time helping you with it then it is surely interesting enough for you to preserve it safely, with the ability to revert to previous versions.

Setting up a git repository is trivial.

Re: problem with printing string ! [SOLVED]

Posted: Tue Nov 21, 2017 8:15 pm
by MichaelPetch
On Windows if you use NUL as a script it doesn't alter the default Linker rules (Cygwin/MinGW LD) for sections that aren't processed in the script. Each section will potentially be aligned to 4kb boundairies when dealing with Windows PE objects. Since you have chosen not to use a cross compiler you'll have to use parameters specific to the LD (linker) for that platform. In particular if you want to reduce code since and get rid of the 4kb you can use this:

Code: Select all

ld -nostdlib -T NUL --file-alignment 0 --section-alignment 32 -o kernel.tmp -Ttext 0x1000 kernel_entry.o kernel.o
I highly recommend (insist) you use -nostdlib to explicitly tell LD that no standard library code will be used. --file-alignment 0 --section-alignment 32
will align each section to a 32-byte boundary. Doing a man ld will give you more details of these two parameters.

The reason your code started to break when you moved the vidmem to global scope is that it was placed in the data section, and that would have added an additional 4kb to your kernel. Since you only load 15 sectors (of 512 bytes each) for the kernel that will exclude anything beyond from byte 7680 (15*512) onward. Your `vidmem` pointer likely fell outside the kernel you were loading and thus not initialized to 0xb8000 .

I noticed an issue in your Makefile. You have this:

Code: Select all

kernel.O: kernel.C
Case matters here I believe you want

Code: Select all

kernel.o: kernel.c
. The way you have it would produce kernel.o from kernel.c using the default Make rules.

Re: problem with printing string ! [SOLVED]

Posted: Wed Nov 22, 2017 2:32 am
by osdevnewbie
iansjack wrote:If your code is interesting enough that you ask others to spend their time helping you with it
I've sincerely apologized for wasting your precious time.
when I said "not interesting" I meant for other people, cause I'm following a guide posted on the web since a long time, so there's no NEW thing I've done.
For me of course it's very very interesting.