problem with printing string ! [SOLVED]

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

problem with printing string ! [SOLVED]

Post by osdevnewbie »

EDIT: the mistake was in the makefile

Hi all,
I'm following Blundell's guide to write a simple OS.
The bootsector works as a charm. In the kernel I can clear the screen and print characters individually, but when I want to print a string I get only the letter "A" !!
I'm working under WIN and using nasm, mingw and bochs .

Code: Select all

void kmain(void)
{
	const char *str = "Hello world!";
	char *vidmem = (char*)0xb8000; 	
	unsigned int i = 0;
	unsigned int j = 0;

	// clear screen OK
	while(j < 80 * 25 * 2) {
		vidmem[j] = ' ';
		vidmem[j+1] = 0x07; 		
		j = j + 2;
	}
      
      // print a character OK
       j=0;
       vidmem[j] = 'A';
       vidmem[j+1] = 0x07;
  
       // print a string :  this part don't work !!!!
	j = 0;
	while(str[j] != '\0') {
		vidmem[i] = str[j];
		vidmem[i+1] = 0x07;
		++j;
		i = i + 2;
	}
	return;
}
Many thanks in advance.
Last edited by osdevnewbie on Mon Nov 20, 2017 11:31 am, edited 2 times in total.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: problem with printing string !

Post by iansjack »

1. Examine the generated code. Does it use the "movs" instruction?

2. Have you set DS and ES registers?

3. Single-step the code under a debugger to see what is happening.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: problem with printing string !

Post by osdevnewbie »

iansjack wrote: 2. Have you set DS and ES registers?
Thanks iansjack for the quick reply !!
DS and ES are set in the bootsector:

Code: Select all

[bits 32]
; Initialise registers and the stack once in PM.
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         
where DATA_SEG =0x10 (3rd entry in the GDT).
Last edited by osdevnewbie on Sat Nov 18, 2017 12:46 pm, edited 1 time in total.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: problem with printing string !

Post by osdevnewbie »

iansjack wrote:1. Examine the generated code. Does it use the "movs" instruction?
I've examined the code:
gcc -S kernel.c

there's no "movs" instruction, only movl, movb.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: problem with printing string !

Post by Brendan »

Hi,
osdevnewbie wrote:The bootsector works as a charm. In the kernel I can clear the screen and print characters individually, but when I want to print a string I get only the letter "A" !!
I'm working under WIN and using nasm, mingw and bochs .
What does it do instead of printing the rest of the string?

Does it return from "kmain()" (e.g. because the kernel wasn't loaded properly and the string was truncated)? Does it crash (e.g. because an IRQ occurred just after the "A" was printed)? Does it do something else (e.g. execute a lot of addition instructions because the CPU Is executing zeros/garbage)?

Note: There were at least some versions of one of the emulators (can't remember if it was Bochs or Qemu, and I'm not sure if it was fixed or not); where it'd use emulated video display memory to update the emulator's window on the host after emulating a specific number of instructions (e.g. "every 100000 emulated instructions update the output window"); and where if you do a "HLT" instruction with IRQs disabled it didn't emulate more instructions, so the "number of instructions emulated" counter didn't increase, so it doesn't update the output window anymore. In this case the code might correctly print the first character; then the emulator might update its output window; then the code might correctly print the remainder of the string, return from "kmain()" and then do "HLT" with IRQs disabled - the remainder of the string would have been printed correctly, but would never be seen in the emulator's output window.

I'm also wondering if your copy of Bochs has been compiled with all the nice debugging options. If it has; you should be able to put a breakpoint immediately before the loop that prints the string and single-step one instruction at a time, and figure out exactly what is going wrong where.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: problem with printing string !

Post by osdevnewbie »

Brendan wrote: What does it do instead of printing the rest of the string?
Thanks Brendan for the long response.
In fact I'm new to bochs, it seems that it halted cause there's no output in boxhs's console.
in the bootsector there's an infinite loop after calling the kernel code:

Code: Select all

  call KERNEL_OFFSET        
  jmp $                   
I tried a break point in the code and added :
magic_break: enabled=1
in bochs's config file but it did'nt stop:

Code: Select all

	while(j < 80 * 25 * 2) {
		/* blank character */
		vidptr[j] = ' ';
		/* attribute-byte - light grey on black screen */
		vidptr[j+1] = 0x07; 		
		j = j + 2;
	}
	
	//magic break point
  asm  volatile ("xchgw %bx, %bx");
  
	j = 0;
	vidptr[j] = 'A';
  vidptr[j+1] = 0x07;
I'm reading more about debugging with bochs.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: problem with printing string !

Post by Brendan »

Hi,
osdevnewbie wrote:I tried a break point in the code and added :
magic_break: enabled=1
in bochs's config file but it did'nt stop:
I suspect that you've downloaded a pre-compiled "Bochs for Windows" where most of the debugging stuff was disabled at compile time.

In that case; it'd probably be best to download the Bochs source code, then configure and compile it yourself, so that you can enable support for all the debugging (and whatever other features you do/don't want).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: problem with printing string !

Post by MichaelPetch »

I hope you aren't compiling the C code as 64-bit code and running it in 32-bit protected mode.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: problem with printing string !

Post by osdevnewbie »

Brendan wrote: I suspect that you've downloaded a pre-compiled "Bochs for Windows" where most of the debugging stuff was disabled at compile time.
Yes, perhaps.
I'll try to build bochs from sources.
Thanks again
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: problem with printing string !

Post by osdevnewbie »

MichaelPetch wrote:I hope you aren't compiling the C code as 64-bit code and running it in 32-bit protected mode.
Thanks MichaelPetch.
I'm on a 32bit system with 32bit win xp.
I don't think that default gcc output is a 64bit file !!
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: problem with printing string !

Post by MichaelPetch »

Could you post the output of this command to humour me:

gcc -v
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: problem with printing string !

Post by MichaelPetch »

One guess I have though is that you possibly aren't reading all of your kernel into memory and the read only data section containing your string is not in memory so it doesn't print anything. Verify in your bootloader that you are reading enough sectors of the disk to read your entire kernel into memory.

A test to see if you can print a string from a loop would to be to place it on the stack as an experiment. Does this work by changing:

Code: Select all

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

Code: Select all

const char str[] = "Hello world!";
. This change should have the effect of the string being generated on the stack rather than placed in the read only section of the kernel. This isn't meant as a fix, but a simple experiment. If the program works with this change then I highly suspect you have a problem with the read only section not being in memory for some reason.
Last edited by MichaelPetch on Sun Nov 19, 2017 9:08 pm, edited 1 time in total.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: problem with printing string !

Post by Schol-R-LEA »

Apropos of @MichaelPetch's question: how are you preparing the C executable, in what form or format is it stored in the disk image, and how are you loading it? Are you converting it to a raw binary image, or is it loading it from an executable in a standard Executable Format such as ELF or PE?

I am not particularly familiar with the tutorial you mention, but a quick review of the PDF tells me that it is converting the executable to raw binary, so am assuming that this is the procedure you are following.

I should point out that while this does look like a pretty solid tutorial, you should keep in mind that no tutorial is flawless, and most tutorials have long-standing, known bugs which don't always get fixed. Also, while most of the things they apply remain stable for years, things do grow out of date with time. You need to apply any tutorial thoughtfully, and while you do seem to be doing so, it is always worth reminding people of this - especially when the tutorial is, for the most part, a good one, as it is all too easy to get used to assuming that the tutorial will remain correct.

Trust me, I am speaking from personal experience on this, having made that mistake all too many times myself.

On a somewhat related note, have you prepared a separate GCC Cross-Compiler and cross-development OS-Specific Toolchain, separate from any tools targeting your development host (which you state is 32-bit Windows XP)? Again, not being familiar with the tutorial, I can't be sure, but it looks it isn't something it discusses. While it is possible to work without doing that - as the part that does seem to work shows - using a cross-compiler solves a lot of the problems with doing that, as does using a build tool such as Make rather than running the compiler on the command line directly.

You probably should keep following the process as given, to avoid confusion for now, but be aware that in later development you probably should set up a cross-compiler.

One other thing, though this is just a stylistic question: why are you using while() loops for definite loops instead of for()? For example, rather than:

Code: Select all

   while(j < 80 * 25 * 2) {
      vidmem[j] = ' ';
      vidmem[j+1] = 0x07;       
      j = j + 2;
   }
you could use

Code: Select all

const unsigned int rows = 25, columns = 80;
const unsigned int vidbuf_size = rows * columns * 2;

   unsigned int j = 0;

   for (j = 0; j < vidbuf_size; j += 2) {
      vidmem[j] = ' ';
      vidmem[j+1] = 0x07;
   }
This makes it clearer that the intent is to walk through a fixed number of iterations - what is called a 'definite iteration' - which is the main purpose of for(). The while() loop, conversely, is usually used for indefinite loops, where the number of passes is determined by something in the loop body rather than the loop conditionals.

I am not saying the code was wrong - it does clearly work - but it isn't really idiomatic in C to use while() for that. I was just wondering if there was a specific reason why you were doing it that way.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: problem with printing string !

Post by osdevnewbie »

Many thanks Schol-R-LEA and MichaelPetch for your replys, I'll try your solutions and post feedback soon.
The disk image is in binary format :

Code: Select all

     cat boot.bin kernel.bin > os.img
so the kernel code is on the 2nd sector on the disk.
the boot loads 15 sectors from the disk (starting from 2nd sector).
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: problem with printing string !

Post by MichaelPetch »

osdevnewbie wrote:

Code: Select all

     cat boot.bin kernel.bin > os.img
so the kernel code is on the 2nd sector on the disk.
the boot loads 15 sectors from the disk (starting from 2nd sector).
If you do a directory listing what is the file size of kernel.bin?
Post Reply