Page 2 of 3
Re: Calling C function from assembly
Posted: Sun Jan 27, 2013 4:53 am
by iansjack
Oops! My fault. 16 bit would make little sense.
I much prefer the 64-bit ABI where parameters are (mostly) passed in registers.
Re: Calling C function from assembly
Posted: Sun Jan 27, 2013 2:04 pm
by BMW
Combuster wrote:BMW wrote:16 bit boundary...
bit != byte
Yeah I know that... sorry I got it from here:
iansjack wrote:GCC (modern versions) require that the stack is aligned to a 16-bit boundary before a function call.
Re: Calling C function from assembly
Posted: Sun Jan 27, 2013 2:55 pm
by BMW
Ok...
Code: Select all
;align stack to a 16 byte boundary
and esp, -16
sub esp, 16
;push args onto stack in reverse order
mov dword eax, [memSize]
push eax
movzx eax, word [mmap_entries]
push eax
mov dword eax, MemMapAddress
push eax
mov ebx, KernelAddress
call ebx
Still not working lol... I'll look into it, unless I am not doing the stack alignment correctly?
Re: Calling C function from assembly
Posted: Sun Jan 27, 2013 8:59 pm
by BMW
Wait... why do I need to do
to align esp to a 16-byte boundary.....
Why can't I just use this
?
EDIT: And what does this do in AT&T assembly?
EDIT #2: If I use jmp ebx instead of call ebx, it works. But then there is no return address... dafuq?
Re: Calling C function from assembly
Posted: Mon Jan 28, 2013 3:15 am
by Combuster
Ever heard of desk checking?
Get a pencil, eraser and a sheet of paper. Then physically draw the stack, and afterwards, perform each instruction by hand and see where each variable ends up in memory in each scenario you're doubting about.
Worst thing of it, is that this is actually a school exercise given in the first month of the computer science bachelor programme (hint: required knowledge).
Re: Calling C function from assembly
Posted: Mon Jan 28, 2013 3:23 am
by bluemoon
Yesh, it's called
Dry Run.
Re: Calling C function from assembly
Posted: Wed Jan 30, 2013 3:23 am
by BMW
I have done the test on paper, and it all seemed good. I compiled a call to kmain into GAS with gcc, and this is the result: (the main function calls kmain)
Code: Select all
.file "test.c"
.section .rodata
.LC0:
.string "Skux OS\n"
.text
.globl kmain
.type kmain, @function
kmain:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $40, %esp
movl $31, (%esp)
call SetColour
call ClearScreen
movl $.LC0, (%esp)
call PrintString
call SetupInterrupts
call timer_install
call keyboard_install
#APP
# 14 "kernel.c" 1
sti
# 0 "" 2
#NO_APP
movl $10, 8(%esp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl 12(%ebp), %eax
movl %eax, (%esp)
call itoa
movl -12(%ebp), %eax
movl %eax, (%esp)
call PrintString
nop
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size kmain, .-kmain
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl $2, 4(%esp)
movl $1, (%esp)
call kmain
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2"
.section .note.GNU-stack,"",@progbits
Now this is how I call kmain from assembly:
Code: Select all
mov ebp, esp
;align stack to a 16 byte boundary
and esp, -16
;push args onto stack in reverse order
movzx eax, word [mmap_entries]
push eax
mov dword eax, MemMapAddress
push eax
;call kernel
mov ebx, KernelAddress
call ebx
I am doing the same stack operations as the code generated by GCC. (Except subtracting 16 from esp, which I tried and it makes no difference)
This is the kmain function:
Code: Select all
void kmain(void* mmap_address, uint32_t mmapentrycount)
{
SetColour(0x1F);
ClearScreen();
PrintString("Skux OS\n");
SetupInterrupts();
timer_install();
keyboard_install();
__asm__ __volatile__("sti");
char* a;
itoa(mmapentrycount, a, 10);
PrintString(a);
}
That kmain function prints mmap_address instead of mmapentrycount.
I am totally confused right now...
Re: Calling C function from assembly
Posted: Wed Jan 30, 2013 3:39 am
by iansjack
At the risk of stating the obvious, you are not calling kmain() in the same way that the compiled main function does. You are also not looking at the generated instructions but at the generated assembler source code. I would recommend using objdump to see exactly what instructions have been generated in the object file; that way you don't need to puzzle over strange compiler directives.
The compiled main function aligns the stack to a 16-byte boundary, subtracts 16-bytes from the stack pointer (preserving that alignment) and then places the parameters at the appropriate positions in the stack (it does this directly rather than with push instructions - that's why it subtracted 16 from the stack pointer before placing the parameters; only 8 bytes are needed for the two parameters, but it has to be 16 to preserve stack alignment).
Your code aligns the stack to a 16-byte boundary and then pushes 2 4-byte variables to the stack (8 bytes in all), thus misaligning it.
I've no idea whether that difference is the cause of your problem, but I would suggest that it would be reasonable to try the same call sequence as the generated C code rather than your own variation of it. In the end, single-stepping through the code, watching the value of the stack pointer and its contents at each instruction, should reveal the error. That's the same as doing it on paper but without any false assumptions and letting the computer do the hard work.
Re: Calling C function from assembly
Posted: Wed Jan 30, 2013 11:11 am
by Kazinsal
The lack of manual of style in your code (notably the mixed forms of function naming) suggests to me that you are copying and pasting from a multitude of sources and expecting everything to work. I am beginning to seriously doubt that you have the required knowledge for operating system development. Consider how the stack works. Then ask yourself why that sub esp, 16 is there.
I claim not that I am a master of OS dev. In fact, I am in most regards, the opposite. I simply learn from sources of my own finding, my own mistakes, R-ing TFM, and most importantly, thinking critically.
Re: Calling C function from assembly
Posted: Wed Jan 30, 2013 1:20 pm
by Combuster
char* a;
itoa(mmapentrycount, a, 10);
You obviously haven't been paying attention anywhere.
- Introducing
more code to an existing problem
- Using libc
- Using it wrongly:
reference for itoa, second argument wrote:str
Array in memory where to store the resulting null-terminated string.
I've seen enough. Go take a course C for absolute beginners.
Re: Calling C function from assembly
Posted: Wed Jan 30, 2013 8:55 pm
by BMW
Combuster wrote:char* a;
itoa(mmapentrycount, a, 10);
You obviously haven't been paying attention anywhere.
- Introducing
more code to an existing problem
- Using libc
- Using it wrongly:
reference for itoa, second argument wrote:str
Array in memory where to store the resulting null-terminated string.
I've seen enough. Go take a course C for absolute beginners.
I think I am the one that should be saying "I've seen enough".
What makes you think that I am noob enough to use libc, and use it wrongly? Your two accusations are based on an assumption, that I am using the itoa() function from libc. The truth is that I implemented my own itoa() function, and I am using my own itoa() function correctly. (Ok, I wasn't using it correctly but I am now)
Blacklight wrote:The lack of manual of style in your code (notably the mixed forms of function naming) suggests to me that you are copying and pasting from a multitude of sources and expecting everything to work. I am beginning to seriously doubt that you have the required knowledge for operating system development. Consider how the stack works. Then ask yourself why that sub esp, 16 is there.
I claim not that I am a master of OS dev. In fact, I am in most regards, the opposite. I simply learn from sources of my own finding, my own mistakes, R-ing TFM, and most importantly, thinking critically.
I think it is harder to use code from different sources than to blindly follow one tutorial, not even understanding the code. And I don't see anything wrong with copying and pasting provided you understand the code you are copying (which I do). This problem arose when I tried to put in my own code, and has nothing to do with "copying and pasting from a multitude of sources and expecting everything to work". I can program well enough to integrate different tutorials (although most people on this forum assume that I am a total noob). As for the function naming, I will be standardising the function names once I get everything working and have decided on a suitable naming convention.
Going back to the problem, I admit I could have done a better job at debugging. But what makes me angry is that people on this forum start to doubt my abilities using totally irrelevant information and unfair assumptions. The assumptions in themselves show that people don't trust my ability. For example someone assumed that I used itoa() from libc, and hadn't implemented my own.
And to all the people that think I never try to debug problems myself, but rather post questions of the forum,
stop assuming!!! I have successfully debugged many problems myself, many more that I have posted here on these forums.
Re: Calling C function from assembly
Posted: Wed Jan 30, 2013 10:14 pm
by BMW
Ok. This code is the code generated by GCC for calling the kmain function:
Code: Select all
and esp, -16
sub esp, 16
mov DWORD PTR [esp+4], 2
mov DWORD PTR [esp], 1
call kmain
It puts the first argument into [esp], then calls kmain. Wouldn't the call kmain overwrite the first argument with the return address?????
Re: Calling C function from assembly
Posted: Wed Jan 30, 2013 10:46 pm
by thepowersgang
(first off, from the C code snippet above, you _are_ calling itoa incorrectly, unless you're using C++ and references, in which case you should be shot)
Secondly, that code will work correctly, as ESP is decremented before the write when something is pushed to the stack (functionally the same as *--esp in C)
(Finally, is that actually the emitted code? that 'add esp, -16' looks very out of place)
SOLVED!!! :D
Posted: Wed Jan 30, 2013 11:05 pm
by BMW
thepowersgang wrote:(first off, from the C code snippet above, you _are_ calling itoa incorrectly, unless you're using C++ and references, in which case you should be shot)
Secondly, that code will work correctly, as ESP is decremented before the write when something is pushed to the stack (functionally the same as *--esp in C)
(Finally, is that actually the emitted code? that 'add esp, -16' looks very out of place)
Ok, is this better: ?
Code: Select all
char a[16] = {NULL};
itoa(number, a, 10);
Ok I see...
It is
and not add (that makes more sense).
Anyway, I have solved it. Sorry for wasting everyones time. Such a stupid mistake on my part.
When I called kmain from assembly, I was not actually calling kmain, but calling the loader stub (as used in the bare bones tutorial). This loader stub then CALLed kmain, pushing an extra return address onto the stack. Changing the CALL in the stub to JMP fixed my problem.
Once again, sorry guys for wasting your time. Thanks anyway for all your help.
Re: Calling C function from assembly
Posted: Thu Jan 31, 2013 12:23 am
by Antti
As an offtopic note, I think your posts are quite good nowadays. Spelling, politeness etc. meet the standards of this forum. Keep going! Do not take "noob" accusations too seriously.