How to call pascal from assembler

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.
Post Reply
LinuxMan

How to call pascal from assembler

Post by LinuxMan »

Hello. I have a problem. if i using C i do asm file with something like:
[BITS 32]
[EXTERN KERNEL_MAIN]
[GLOBAL _start]
_start:
mov esp, 0x200000-4
call KERNEL_MAIN

and C file with
void KERNEL_MAIN() {
//code
}

But when i try used the same with pascal(in start of program i have
program KERNEL_MAIN; ) in linking i have startup.asm:(.text+0x6): undefined reference to `KERNEL_MAIN'
Is anybody know how to call pascal fuctins from assembler? I'm use freepascal
P.S. Sorry for my English. My native language is Ukrainian
Habbit

Re:How to call pascal from assembler

Post by Habbit »

It is very possible that your Pascal compiler is adding a prefix/suffix to its symbols, or maybe even mangling the procedure names just as C++ (for example, my [tt]void Kernel::Kernel::Panic(const char*)[/tt] translates as [tt]_ZN6Kernel6Kernel5PanicEPKc[/tt]).

If you are using the GNU toolchain and your Pascal compiler outputs an object format usable by the GNU binutils, you can see what are your procedure names being mangled to:

Code: Select all

yourPascalCompiler kernel_main.pas -o kernel_main.o
objdump -d kernel_main.o
Objdump will show you the disassembly of the code sections of the file the Pascal compiler wrote, and it should contain the procedure names just as assembler expects you to call them.
nick8325
Member
Member
Posts: 200
Joined: Wed Oct 18, 2006 5:49 am

Re:How to call pascal from assembler

Post by nick8325 »

LinuxMan wrote: Is anybody know how to call pascal fuctins from assembler? I'm use freepascal
I think something like

Code: Select all

unit KernelMain;

interface

implementation

procedure kernel_main; [public, alias: 'KERNEL_MAIN'];
begin
    ...
end;

end.
might work. But it's been a few years since I used FreePascal, so I'm not sure.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:How to call pascal from assembler

Post by Candy »

Note that when you start working with arguments that you have to push them in inverse order compared to what pretty much all internet tutorials do. Also, if you call ASM from Pascal, the called function is responsible for removing the arguments, using "ret <n>". You can try using some form of objdump to see what the actual name is of the function, use "objdump -t".
LinuxMan

Re:How to call pascal from assembler

Post by LinuxMan »

Thank you, Habbit. My function is named "THREADVARLIST_P$KERNEL_MAIN" :o
Habbit

Re:How to call pascal from assembler

Post by Habbit »

You're welcome :)

I had similar problems when I set my loader: the linked could not found the [tt]kmain[/tt] function... After toying a bit with objdump, I found its name was being mangled to [tt]_Z5kmainmRN9Multiboot8BootInfoE[/tt].

Many static typed languages that support function overloading based on its full signature (its name and the parameters it takes instead of just the name) mangle the "official procedure names" to include that signature. That way, I can have a func(int) and another func(char*): C++ would mangle those names to something including the argument types so they would not conflict at the assembly level.

However, when you want to interface with assembly (and, particularly, call your procedures from it), you need a way of knowing what a function name will be mangled to, which in C++ is very difficult because there is no standard about name mangling and even GCC switches behaviours between versions.

In my case I had an easy workaround: the C++ option [tt]extern "C"[/tt]. Prefixing a function with such an attribute makes the compiler to use C naming for that function. C functions are usually just prefixed with an underscore (i.e., my kmain would be _kmain), or even no prefix, depending on the compiler.

As I don't know Pascal, I can't point out anything like that for you: the best I can tell you is to keep using [tt]objdump -t[/tt] to see the symbol table, but there seems to be an interesting suggestion already in the forum:
nick8325 wrote:

Code: Select all

procedure kernel_main; [public, alias: 'KERNEL_MAIN'];
begin
    ...
end;
evincarofautumn

Re:How to call pascal from assembler

Post by evincarofautumn »

Note that when you start working with arguments that you have to push them in inverse order compared to what pretty much all internet tutorials do.
iirc pascal supports a [tt]cdecl[/tt] option placed like so:

[tt]procedure some_kernel_function; [public, alias: 'some_kernel_function']; cdecl;
begin
...
end;[/tt]

Which should allow you to pass parameters C++-style.

I wish you the best of luck trying to write an OS in Pascal; it's a very unconventional project and I will enjoy seeing your results. :)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:How to call pascal from assembler

Post by Pype.Clicker »

Here's the FAQ page you've all been waiting for :
Doing a kernel in Pascal

i pushed as much as i could retrieve, but you're open to tell what you know about Pascal OSDev'ing there too :)
Habbit

Re:How to call pascal from assembler

Post by Habbit »

Pype.Clicker wrote: Here's the FAQ page you've all been waiting for :
Doing a kernel in Pascal
You're the man, Pype!! (or the woman, I can't tell from that Yoda pic). Now, let me write the "Doing a kernel in PHP 5" FAQ page ;D
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:How to call pascal from assembler

Post by Pype.Clicker »

Habbit wrote: You're the man, Pype!!
The man, indeed. If you know of a woman who has spent 10 years of hobby on writing a OS kernel, and who is moderator of an OSdev' forum where she cumulates +5000 posts, please, tell her .... that i'm engaged already ;D
Kemp

Re:How to call pascal from assembler

Post by Kemp »

Heh, I don't think she'd reveal her gender for fear of being propositioned by every unattached guy who visits here ;D My other half is picking up stuff scarily quickly though, she's never done computer stuff before and yet picked up binary counting and addition with a mere 10 minute intro from me while we were walking somewhere with no paper to demonstrate anything on. I'll make a geek chick out of her yet :)
Crazed123

Re:How to call pascal from assembler

Post by Crazed123 »

LinuxMan wrote: Hello. I have a problem. if i using C i do asm file with something like:
[BITS 32]
[EXTERN KERNEL_MAIN]
[GLOBAL _start]
_start:
mov esp, 0x200000-4
call KERNEL_MAIN

and C file with
void KERNEL_MAIN() {
//code
}

But when i try used the same with pascal(in start of program i have
program KERNEL_MAIN; ) in linking i have startup.asm:(.text+0x6): undefined reference to `KERNEL_MAIN'
Is anybody know how to call pascal fuctins from assembler? I'm use freepascal
P.S. Sorry for my English. My native language is Ukrainian
You have pretty good English for an internet user. Don't worry about it.

The actual answer here is that when you write your Pascal kernel as...

Code: Select all

program Kernel;

uses Console,Other,System,Etc;

var
 stuff: type;

begin
...
end.
the compiler sets the actual name of the kernel main routine (which goes between begin and end) to PASCALMAIN. Reference PASCALMAIN in assembler files, and your calls to it should work.

I'll give you an extra tip for coding in Free Pascal: somewhere in your code, declare something like:

Code: Select all

var
 btInitialHeap: array [0..$100000-1] of byte;

function KMalloc(lwSize: longword): Pointer;
const
 lwAllocatedInitial: longword = 0; 
begin
Result:= nil;
if Length(btInitialHeap) - lwAllocatedInitial >= lwSize then
 begin
 Result:= @btInitialHeap[lwAllocatedInitial];
 Inc(lwAllocatedInitial,lwSize);
 end;
end;
Hook this code into the System unit's SysOSAlloc() function, the most primitive heap allocation function FPC's RTL uses. This way, you can use heap allocated types such as dynamic arrays and instances of classes in your kernel, even before you set up the memory manager. The RTL will handle the heap memory once you give that memory through SysOSAlloc(), so the kernel won't need to free it.
Post Reply