Some problems with C code
Some problems with C code
I have some problems with c.
I mean i get this error:
include/vesa.c:3: initializer element is not constant
2 line: unsigned long LFBAddr;
3 line: unsigned long *video = (unsigned long *) (LFBAddr);
What is wrong here?
I get LFBAddr value in kernel.asm, and in kernel.asm i write the value to LFBAddr address.
Thanks in advance.
I mean i get this error:
include/vesa.c:3: initializer element is not constant
2 line: unsigned long LFBAddr;
3 line: unsigned long *video = (unsigned long *) (LFBAddr);
What is wrong here?
I get LFBAddr value in kernel.asm, and in kernel.asm i write the value to LFBAddr address.
Thanks in advance.
Re:Some problems with C code
I'm guessing that those two values are outside of a function and are standalone declarations.
So, declarations like that are initialised at compile time... and since you are trying to set video to LFBAddr at compile time, LFBAddr is not initialised or constant.
You'll need to move line 3 into a function and call the function at some point to initialise *video during run time.
Or, you could just set the value of video from your kernel.asm instead and do away with LFBAddr and the video initialisation.
If your LFB is at 0xA0000, set video to 0xA0000 in kernel.asm and then *video will direct you into the lfb area correctly.
So, declarations like that are initialised at compile time... and since you are trying to set video to LFBAddr at compile time, LFBAddr is not initialised or constant.
You'll need to move line 3 into a function and call the function at some point to initialise *video during run time.
Or, you could just set the value of video from your kernel.asm instead and do away with LFBAddr and the video initialisation.
If your LFB is at 0xA0000, set video to 0xA0000 in kernel.asm and then *video will direct you into the lfb area correctly.
Re:Some problems with C code
It appears you want these two variables to have the same value. Why are they two different variables, then? If it's just because of the types, and you don't want to add type casting operators when using them one way or the other, declare a union, e.g.:
Then, video.addr is an unsigned integer, and video.mem is a pointer, but they're both the same variable, the same value, just typed differently.
Code: Select all
union {
unsigned long addr;
unsigned long *mem;
} video;
Re:Some problems with C code
Jesus! Dreamsmith, how can you suggest such a thing? :O
For the sake of your sanity when debugging your code later: Just because you're working in kernel space ain't excuse for raping the language. C doesn't guarantee that a pointer and an integer are represented in any compatible way. They needn't even be the same width...
*shudder*
For the sake of your sanity when debugging your code later: Just because you're working in kernel space ain't excuse for raping the language. C doesn't guarantee that a pointer and an integer are represented in any compatible way. They needn't even be the same width...
*shudder*
Every good solution is obvious once you've found it.
Re:Some problems with C code
actually the C99 standard has intptr_t and uintptr_t which are specifically for converting a pointer to a safe integer type and back
proxy
proxy
Re:Some problems with C code
Yep... doesn't make it any more beautiful, but much cleaner.
Yet still, what's guaranteed there is that you can safely cast one into the other - there's still no guarantee that you can union them safely.
I know that sounds paranoid. "Hell, I know no platform this won't work on". But I made it a habit not to assume anything not guaranteed, running the compiler in strictest error-checking etc... makes a pain in the making, but you get much less issues later on.
Yet still, what's guaranteed there is that you can safely cast one into the other - there's still no guarantee that you can union them safely.
I know that sounds paranoid. "Hell, I know no platform this won't work on". But I made it a habit not to assume anything not guaranteed, running the compiler in strictest error-checking etc... makes a pain in the making, but you get much less issues later on.
Every good solution is obvious once you've found it.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Some problems with C code
beside the 'this and that', of whether unions are clean or not ...
- why do you need *two* variables ? can't you simply declare "unsigned long *video" and have the ASM writing the address there ?
- if you need two variables, why do you need them to have a compiler-initialized value ? can't copying (with cast if required) of the value in an init() function do the trick ?
- why do you need *two* variables ? can't you simply declare "unsigned long *video" and have the ASM writing the address there ?
- if you need two variables, why do you need them to have a compiler-initialized value ? can't copying (with cast if required) of the value in an init() function do the trick ?
Re:Some problems with C code
Hmm, I have no other way how to do this.
Maybe I better create new question ;D :
My LFB Address is 0x111FF (linear).
I initialize VESA when i am being in Real mode(bootloader), so how can I reach that address from kernel which is in PMODE?
This doesn't work:
unsigned long *video = (unsigned long *) (0x111FF + 0x28);
Maybe I better create new question ;D :
My LFB Address is 0x111FF (linear).
I initialize VESA when i am being in Real mode(bootloader), so how can I reach that address from kernel which is in PMODE?
This doesn't work:
unsigned long *video = (unsigned long *) (0x111FF + 0x28);
Re:Some problems with C code
If you have a pointer to your linear frame buffer, you already have both the address and the pointer. To access stuff in the frame buffer you use "video[offset]" or "*(video+(offset))" which are obviously the same thing.
To access the address, you use "video". The only problem here is ofcourse that depending on warning settings, the compiler might warn you about comparing/assigning between integers and pointers. I think you should try to keep memory addresses as pointers. As for constants ((void*)0xa0000) isn't really that bad, and is good for readability since you then know it's an address and not some magick constant.
As for raping the language with unions, I think it's perfectly fine to assume certain alignment in code that's platform dependant anyway. The benefits can often (while not necessarily in this case) outweight the cost. The cost is your code is not longer portable to another system (which in platform dependant code ofcourse doesn't matter anyway) or other compilers (which may or may not be a problem, although I'd like to see a compiler for native x86 32-bit protected mode where "unsigned long" was not equivalent to "void*" on generated code level.
Then again, unions are again something that can hurt compiler optimizations since figuring aliasing becomes a bit harder. I have no idea if this affects GCC but it might.
That said, you can't write a kernel in portable C99 anyway, so being to strict about the standard is simply useless and stupid. Besides, you can't use C99 standard lib either, so you are not even programming in C99 environment.
To access the address, you use "video". The only problem here is ofcourse that depending on warning settings, the compiler might warn you about comparing/assigning between integers and pointers. I think you should try to keep memory addresses as pointers. As for constants ((void*)0xa0000) isn't really that bad, and is good for readability since you then know it's an address and not some magick constant.
As for raping the language with unions, I think it's perfectly fine to assume certain alignment in code that's platform dependant anyway. The benefits can often (while not necessarily in this case) outweight the cost. The cost is your code is not longer portable to another system (which in platform dependant code ofcourse doesn't matter anyway) or other compilers (which may or may not be a problem, although I'd like to see a compiler for native x86 32-bit protected mode where "unsigned long" was not equivalent to "void*" on generated code level.
Then again, unions are again something that can hurt compiler optimizations since figuring aliasing becomes a bit harder. I have no idea if this affects GCC but it might.
That said, you can't write a kernel in portable C99 anyway, so being to strict about the standard is simply useless and stupid. Besides, you can't use C99 standard lib either, so you are not even programming in C99 environment.
Re:Some problems with C code
So how about that address? If i us 0xA0000, then i just can reach 64K of memory(it is about 16lines on 0x118 mode). So I can use just a small bold line of screen ;D .
In bootloader, kernel.asm I can use 0x111FF+0x28 . I use it like this:
mov eax, [0x111FF+0x28]
mov ecx, 1024*768*4
loopas:
mov byte [eax], 0xAA
inc eax
loop loopas
and it works.
But when i want to integrate this to my kernel.c, I have to do it another way. But how?
In bootloader, kernel.asm I can use 0x111FF+0x28 . I use it like this:
mov eax, [0x111FF+0x28]
mov ecx, 1024*768*4
loopas:
mov byte [eax], 0xAA
inc eax
loop loopas
and it works.
But when i want to integrate this to my kernel.c, I have to do it another way. But how?
Re:Some problems with C code
Oh, the address was just taken out of the hat. In most cases, the address you REALLY want to use ofcourse depends on the mode, the card and what not.
Re:Some problems with C code
I am testing with Virtual PC so I think everything is the same everywhere
;D .
But how to get working that address ;/
;D .
But how to get working that address ;/
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Some problems with C code
could it be that your data segment's base is not 0 ? in that case you need to convert your linear address in something that looks like "linear - ds_base"
Re:Some problems with C code
No way. Nothing could be cleaner than my suggestion, it's just not necessarily portable. Cleanliness is almost always sacrificed in the name of portability. Readability frequently is as well. If portability is a design goal, then make the sacrifices, if not, then for the sakes of all the gods, keep it clean and simple.Solar wrote:Yep... doesn't make it any more beautiful, but much cleaner.
Hmm, no odd defines, no unnecessary type declarations to alias things that are already there... "raping the language?" Please. I'm using the language exactly as it was designed to be used, rather than layering a bunch of unnecessary crap on top of it to make it do things it wasn't originally designed to do, smothering a beautiful language in the process. The C standards have thrown a lot of stuff on top of the language, some good, some bad -- the nice thing is, you can use what's appropriate for the task at hand. If you're trying to write portable code, then by all means, use the facilities the standard defines for doing so. If you're not, then for the gods sakes, please don't...
Re:Some problems with C code
It should also be noted that, as I pointed out when posting the example, this was designed to handle the problem of having two different variables that are holding exactly the same value. I can guarentee that this solution is a completely portable way to solve that specific problem. Any example you can provide where it won't work violates the very premise of the problem this was an attempt to solve.Solar wrote:C doesn't guarantee that a pointer and an integer are represented in any compatible way. They needn't even be the same width...
Futhermore, this was designed to be used by code that needed to sometimes refer the value as a pointer and sometimes as an integer. In other words, the code that would be accessing this variable already assumes ints and pointers are interchangable and cannot possibly be portable to platforms where this is not the case. Given this, it would be utterly silly to eschew a union for portability reasons in this particualr case.
Now, whether the code that's using it should be rewritten to not make that assumption is another issue, but unless portability is a higher design goal than efficiency in your OS, my guess would be no.