0

I've been working on a customized operating system project in school, and when I started coding in C++, I reached a huge problem:

I've built a custom put_char function in assembly, it basically takes an address and a Dword value and saves it in memory. I'm using Qemu virtual machine, and 0xb8000 is the Screen memory start (SCREEN_START)

if I run the code in CPP:

put_char(SCREEN_START, 0x2f562f56)

(0x2f202f56 is "/V/V") it prints "VV" to the screen, so the function itself does work.

The put_chars code:

put_char:

push ebp    ; save the prior EBP value
mov ebp, esp

mov ebx, edi;
mov edx, esi;

mov dword [ebx], edx

xor eax,eax

pop ebp     ; minimal cleanup
ret

But the problem happens when i tied to print a char from an array: When I tried passing a string (char *) to a function, it sends the wrong values.

void pp(char hello[])
{
    for (int i = 0; i < 7; i++)
    {
        put_char(SCREEN_START + i*4, hello[i] );
    }
}

global void kernel_main()
{
    pp("Hello!");
}

The screen prints different values each time, and it's never "Hello!"... For example it prints spaces only...

According to what I read, this happens when the stack is corrupted, but I haven't used the stack in any of my codes, especially the assembly ones.

Not really sure how to fix this, tried different things, like building a struct or a class, passing it as char* and not char[], making a constant string to print outside of the function... nothing really worked, I even tried sending int array, and didn't work.

Please let me know if anyone could help! really need it!

  • Note: the put_char function works just fine if a send an instant value... – Just a burger Jan 08 '21 at 10:22
  • 1
    `I've been working on a customized operating system project in school` This doesn't look like smart thing to do at school. – Marek R Jan 08 '21 at 10:23
  • From the looks of it, your problem could be anything, from something as simple as the wrong order of parameters to `put_chatr()` (first char, then number) to something as complicated as `put_char()` simply not working. If you do not show us a lot more, and if you do not explain in far greater detail exactly what happens, ("prints different values" is inadequate) we cannot tell. – Mike Nakis Jan 08 '21 at 10:29
  • Also, for future reference, when asking a question on stackoverflow just stick to the facts and skip theories as to what is happening. Your function receiving a wrong pointer is a theory. The stack being corrupted is a theory. These theories are both irrelevant. What is relevant, but you have not shown, is the prototype of `put_char()` and the implementation or at the very least the documentation of `put_char()`. – Mike Nakis Jan 08 '21 at 10:43
  • I've edited the question. take a look. – Just a burger Jan 08 '21 at 10:56
  • Just so you don't waste time on that one: `char[]` and `char *` are strictly identical in a function arguments. — Now, that's not the full code, at the very least it misses the c++ declaration for `put_char`. Which is important, because that's what determines what exact code will be generated in `pp`. We'd also need to know the ABI you're building with. – spectras Jan 08 '21 at 12:10

2 Answers2

0

A DWORD is an unsigned, 32-bit unit of data while a char in the C programming language is a data type with the size of exactly 8-bit. So the put_char is printing 32 bits while every char is 8 bit in your array and so it is printing garbage. You should either use a different function than put_char so that it prints exactly 8 bit at a time, or make your array of 32-bit unsigned integers.

Chaitanya
  • 177
  • 2
  • 9
  • I know all of that, and that's not the problem. I've added to the question, you can see the put_char function now... – Just a burger Jan 08 '21 at 10:44
  • Have you tried using `put_char(SCREEN_START + i*4, *hello[i] );` in your code? it might be just taking the address of the `hello[i]` instead of data stored in that address. – Chaitanya Jan 08 '21 at 10:56
  • 1
    Thanks for the help, the problem turns out to be very simple and stupid: I forgot to set a stack for the system in the bootloader. – Just a burger Jan 10 '21 at 18:01
0

The definition of put_char() as shown above in Intel Assembly assumes that the first parameter passed to it is in register edi and the second parameter is in register esi. The OP has still failed to show the prototype of put_char() in C++, but it is reasonable to presume that no calling convention has been specified, and therefore the fact that these registers contain these values when the function is invoked in a certain scenario is purely coincidental. This means that when this function is used in a different scenario, these registers contain different values, so the result is the observed malfunction.

To solve this problem, the calling convention of the function should be specified in the prototype, (probably cdecl or stdcall,) and then the assembly is likely to have to be modified to follow this convention, meaning that the value of each parameter will probably need to be obtained from a certain offset from ebp. For further information, see Stack Overflow: What does “cdecl” stand for?

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • Thank you for the help, ill try check it out right now. – Just a burger Jan 09 '21 at 10:46
  • Good luck! Let us know what happened. – Mike Nakis Jan 09 '21 at 13:12
  • But actually, now that I look at the edited question again, it seems to me that Chaitanya's answer may also be correct. `0x2f562f56` is a `DWORD`, and `mov dword [ebx], edx` stores a `DWORD`. You have ***still*** failed to tell us exactly what "different values" it prints, but `hello[i]` is a char, and this is bound to cause problems. – Mike Nakis Jan 09 '21 at 13:18
  • Also, the fact that you can pass either a `DWORD` or a `char` to your function may mean that you have no prototype defined at all, (but you have so far failed to say so,) or that you receive compiler warnings but you are ignoring them, (which is guaranteed to lead to failure,) or are trying to actually engage in the fine art of programming without having a sufficient number of compiler warnings enabled. (Which is also guaranteed to lead to failure.) – Mike Nakis Jan 09 '21 at 13:23