Page 1 of 2
Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 6:19 pm
by Puffy
(Sorry for making a new thread quite so soon after my last).
I've knocked together a quick function to get the CPU vendor using the CPUID instruction, but a few things about it are a bit strange.
Edit: I don't want the function its self to print the vendor string, I want to return the vendor string so I'm able to print myself elsewhere, that's why the function is as such.
Here's the function:
Code: Select all
char *getCPUVendor(char *rtn)
{
asm(
".intel_syntax noprefix;"
"mov eax,0;"
"cpuid;"
"mov [%0],ebx;"
"mov [%0+4],edx;"
"mov [%0+8],ecx;"
"movb [%0+12],0;"
".att_syntax;" : "=r" (rtn)
);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//int t;
//for (t = 0; t< 13;t++){
// printCharacter(*(rtn+t));
//}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return rtn;
}
I call it from my main function like so:
Code: Select all
#include <screen.h>
#include <cpuid.h>
void kmain( void* mbd, unsigned int magic )
{
initScreen();
char vendor[13];
char *ptr = vendor;
ptr = getCPUVendor(ptr);
printString("SEPARATOR");
printString(ptr);
for(;;);
}
Now, when I boot my kernel with the code set up like this, all that is printed is "SEPARATOR" BUT if I uncomment the section in between the two lines of exclamation marks the correct vendor string is printed twice (once by the loop in the getCPUVendor() function and once by the printString(ptr) call in the main function).
I cannot understand why that section in the getCPUVendor() function makes a difference.
Here's the printString() and printCharacter() functions.
Code: Select all
void printCharacter(unsigned char character)
{
if (character == '\b'){
if (pos_x != 0){
pos_x--;
}
}else if (character == '\t'){
pos_x = (pos_x + 8) & ~(8 - 1);
}else if (character == '\r'){
pos_x = 0;
}else if (character == '\n'){
pos_y++;
}else if (character == '\a'){
}else{
short offset = calculateOffset(pos_x,pos_y);
unsigned short output = constructOutputShort(character);
buffer[offset] = output;
pos_x++;
}
scroll();
}
void printString(const char *string)
{
int stringLength = strlen(string);
const char *strPointer = (const char *)string;
for(; stringLength > 0; stringLength--){
printCharacter(*strPointer++);
}
}
I cannot see a reason why this behaviour occurs! Can anyone help?
Cheers,
Puff
P.S. I know I'm asking a lot of questions on this forum, but every answer I get really helps me learn. Thank You all very much!
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 8:27 pm
by Alboin
Hi,
Try making the array global.
OT:
In C, when you pass a variable to a function, a copy of that variable is passed, not the actual variable. Thus:
Code: Select all
void printString(const char *string)
{
int stringLength = strlen(string);
const char *strPointer = (const char *)string;
for(; stringLength > 0; stringLength--){
printCharacter(*strPointer++);
}
}
Could much easily be written as:
Code: Select all
void printString(char *string)
{
while(*string != '\0') {
printCharacter(*string++);
}
}
This is why pointers are used so much in C.
*Note: strlen goes through the string until it encounters a \0. You can save yourself a variable, and an instruction or two, by simply checking yourself.
Toodles,
Alboin
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 8:55 pm
by Adek336
as a quick debug:
if uncomenting
Code: Select all
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//int t;
//for (t = 0; t< 13;t++){
// printCharacter(*(rtn+t));
//}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
changes the behaviour of the program, I'd check what is the outcome after changing the loop to things such as
Code: Select all
int t;
for (t = 0; t< 13;t++){
// choose one:
// printCharacter(*(rtn+0));
// printCharacter('A');
// do nothing
// *(rtn+t);
}
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 9:14 pm
by Puffy
Thanks for your adivce Alboin, I've updated my printString() function to match your example and I've stopped returning a value from getCPUVendor(). With the updated printString() function the vendor string
does not print at all, even after uncommenting the block within getCPUVendor(). That makes me even more confused!
My code now looks like this:
getCPUVendor()
Code: Select all
void getCPUVendor(char *rtn)
{
asm(
".intel_syntax noprefix;"
"mov eax,0;"
"cpuid;"
"mov [%0],ebx;"
"mov [%0+4],edx;"
"mov [%0+8],ecx;"
"movb [%0+12],0;"
".att_syntax;" : "=r" (rtn)
);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//int t;
//for (t = 0; t<13;t++){
// printCharacter(*(rtn+t));
//}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
printString()
Code: Select all
void printString(char *string)
{
while (*string != '\0'){
printCharacter(*(string++));
}
}
kmain()
Code: Select all
#include <screen.h>
#include <cpuid.h>
void kmain( void* mbd, unsigned int magic )
{
initScreen();
char vendor[13];
char *ptr = vendor;
getCPUVendor(ptr);
printString("SEPERATOR");
printString(ptr);
for(;;);
}
As for the debugs suggested by Adek336, nothing else gets the vendor string printed than my original commented block
Edit: Interestingly, if I call printString(rtn); from inside getCPUVendor() then the string continues to print forever (i.e. the null character is never found).
Edit2: More interstingly, if you keep the commented section commented and move the same code to the main function:
Code: Select all
#include <screen.h>
#include <cpuid.h>
void kmain( void* mbd, unsigned int magic )
{
initScreen();
if (isCPUIDSupported()){
printString("CPUID is supported.");
}else{
printString("CPUID is not supported.");
}
char vendor[13];
char *ptr = vendor;
getCPUVendor(ptr);
printString("SEPERATOR");
//printString(ptr);
int t;
for (t = 0; t<13;t++){
printCharacter(*(ptr+t));
}
for(;;);
}
Nothing is printed there either.
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 9:24 pm
by Alboin
Change your last asm line to ".att_syntax;" :: "r" (rtn)".
The register is an input operand, not an output.
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 9:30 pm
by Puffy
Nope, that doesn't help either. The kernel keeps printing nothing forever.
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 9:35 pm
by Alboin
Try your old printstring.
I'm not sure what the problem is. This works on my Linux box:
Code: Select all
void getCPUVendor(char *rtn) {
asm(
".intel_syntax noprefix;"
"movb [%0], 'a';"
"movb [%0+1],'b';"
"movb [%0+2],'c';"
"movb [%0+3],0;"
".att_syntax;" :: "r" (rtn));
}
void printString(char *string) {
while (*string != '\0')
printf("%c", *string++);
}
void main() {
char vendor[13];
getCPUVendor(vendor);
printString(vendor);
}
It prints 'abc'.
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 9:45 pm
by Puffy
Using my original printString():
i. The string is not printed from the kmain() function.
ii. If you try to print rtn from getCPUVendor() then it does print there but still does not print from kmain
Edit: Your code also works on my linux box.
This problem is driving me around the bend.
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 9:54 pm
by Alboin
I feel like I'm the blind leading the blind.
Making the variable global doesn't work wither then? It does sound like a local array\stack problem, but I can't put my finger on it...
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 10:01 pm
by Puffy
Edit: I said 'local' when I meant 'global' below, so changed it.
Making vendor global (I put 'char vendor[13]' in cpuid.h) didn't help either. :/
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 10:03 pm
by thepowersgang
Just a comment on the code:
The getCPUVendor function need not return the string as the buffer is passed as a pointer.
Also in C arrays and pointers are the same so
Code: Select all
char buf[13];
getCPUVendor(buf);
printString(buf);
should work.
EDIT: putting a global in a header is a bad idea.
Better to put it in a source file and then put
in the header.
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 10:06 pm
by Puffy
Thank you, that has already been pointed out and I've modified the code to reflect the suggestion. It's still all broke and stuff
Edit: Implemented the global as above - the string still wasn't printed, but my kernel didn't print nothing forever.
Edit2:
Maybe it's to do with my compiler flags?
gcc Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o
Edit3:
Earlier Alboin posted the following code:
Code: Select all
void getCPUVendor(char *rtn) {
asm(
".intel_syntax noprefix;"
"movb [%0], 'a';"
"movb [%0+1],'b';"
"movb [%0+2],'c';"
"movb [%0+3],0;"
".att_syntax;" :: "r" (rtn));
}
void printString(char *string) {
while (*string != '\0')
printf("%c", *string++);
}
void main() {
char vendor[13];
getCPUVendor(vendor);
printString(vendor);
}
I compiled it as a stand-alone project and it worked. I just tried replacing his test getCPUVendor() function with mine and the code failed. Thus there is a problem with my implementation of getCPUVender() although I still don't know what it is.
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 11:02 pm
by Alboin
I compiled it as a stand-alone project and it worked. I just tried replacing his test getCPUVendor() function with mine and the code failed. Thus there is a problem with my implementation of getCPUVender() although I still don't know what it is.
Do you mean my getCPUVendor failed when you switched it in? If mine failed, your problem is elsewhere. (Considering it works on a normal box.)
Re: Bizarre String-Printing Behavior
Posted: Wed Jul 23, 2008 11:10 pm
by Puffy
To clarify:
I copy/pasted your code exactly and compiled it on its own (I used stdio.h) and it ran perfectly. I then replaced the dummy getCPUVendor() function that you wrote (the one that puts abc into the char array) with my own, recompiled, and the code failed (nothing was printed).
Edit:
I've knocked together the following test code. If you uncomment the getCPUVendor() line in the main() function nothing gets printed to the screen at all.
This bug is one of the strangest I have ever encountered. :/
Code: Select all
#include <stdio.h>
void test(char *rtn)
{
unsigned int input = 0;
unsigned int first, second, third;
asm volatile("cpuid;" : "=b"(first),"=d"(second),"=c"(third): "a"(input));
rtn[0] = first;
rtn[1] = first >> 8;
rtn[2] = first >> 16;
rtn[3] = first >> 24;
rtn[4] = second >> 0;
rtn[5] = second >> 8;
rtn[6] = second >> 16;
rtn[7] = second >> 24;
rtn[8] = third >> 0;
rtn[9] = third >> 8;
rtn[10] = third >> 16;
rtn[11] = third >> 24;
rtn[12] = '\0';
}
void getCPUVendor(char *rtn)
{
asm volatile(
".intel_syntax noprefix;"
"mov eax,0;"
"cpuid;"
"mov [%0],ebx;"
"mov [%0+4],edx;"
"mov [%0+8],ecx;"
"movb [%0+12],0;"
".att_syntax;" : "=r" (rtn)
);
}
void printString(char *string) {
while (*string != '\0')
printf("%c", *string++);
}
void main() {
char vendor[13];
test(vendor);
printString(vendor);
//getCPUVendor(vendor);
//printf(vendor);
}
Re: Bizarre String-Printing Behavior
Posted: Thu Jul 24, 2008 2:13 am
by jnc100
Perhaps its a problem with you not specifying the clobber list?
Code: Select all
...
".att_syntax;" : : "r" (rtn) : "a", "b", "c", "d" );
Regards,
John.