How to call a program from C?

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
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

How to call a program from C?

Post by osdevnewbie »

Hi all,
I'm working in real mode on an 8088 based SBC and using BORLAND C++ V5.0 to generate code (Tiny memory model).

1-Suppose I've loaded a program to adress 8000h.
How to "CALL" this program from C?

My code is some thing like this:

Code: Select all

   char* load_adress= 8000h;
   load(char* name, int* adress);
   .........
   load(myfile, load_adress); // the file is loaded sucussfuly
   ........
   asm mov ax, 800h  // this code don't work !!!!!
   asm mov ds, ax
   asm call 800h:0000  
   .......
2- When I put "org 000" in the startup file (C0T.asm) I can compile, but if I choose other offset (8000H) I can't compile!
What is the problem? Please
Thanks
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: How to call a program from C?

Post by iansjack »

You can't do far calls in the tiny memory model.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: How to call a program from C?

Post by osdevnewbie »

iansjack wrote:You can't do far calls in the tiny memory model.
Thanks iansjack for ur reply.

The code can be compiled without errors but it does'nt work!
I think we can do a "far call" in run time at any moment, memory models are effective only at compilation time.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: How to call a program from C?

Post by Schol-R-LEA »

osdevnewbie wrote:
iansjack wrote:You can't do far calls in the tiny memory model.
Thanks iansjack for ur reply.

The code can be compiled without errors but it does'nt work!
I think we can do a "far call" in run time at any moment, memory models are effective only at compilation time.
Yes and no; while the 'memory models' are an abstraction related to how the compiler generates the code, the settings for the memory model *do* restrict the code which the compiler will produce. In the case of the tiny model, it is constrained to produce a flat, single- segment program with the stack and data all sharing the same 64KiB segment as the code - in other words, something suitable for an MS-DOS .COM executable.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: How to call a program from C?

Post by iansjack »

Have you examined the assembler code that is produced?

Have you used a debugger to determine what is happening?

These are the first steps to take in debugging your problem. They should be enough for you to determine what is causing your program to fail.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: How to call a program from C?

Post by osdevnewbie »

Here is the code wich is a part of a very simple CLI based OS:

Code: Select all

char* load_adress= 0x8000; // load adress for programs
char T1[16];  // buffer for input string from keyboard
char* cmd1= "HELP";        
char* cmd2= "CLS"; 
char* cmd3= "DIR";
char* cmd4= "LS";    
char* pT1= T1;
help();
error();

//===================================
main()
{
  char* str1 = "   *** WELLCOME ***";

	CLS();  // clear screen
	puts(str1) ; // print greeting message
	
	for(;;){ // for ever
	
	nextl();  // go to start of a new line
	putc('>'); // and print prompt

	// get string from keyboard
	gets(pT1);

  // which command ?
	if (strcmp(pT1,cmd1) == 0) help(); 
	else	if (strcmp(pT1,cmd2) == 0) CLS();  // 
	else 	if ((strcmp(pT1,cmd3) == 0) || (strcmp(pT1,cmd4) == 0)) list();
	else if(search(pT1) == 0)
	{ load(pT1, load_adress); // if a binary file name entered load it
    // call our program 
	  
	
	  asm mov ax, 800h
	  asm mov ds, ax
	  asm call far 800h:0000
	  

	}	
	else	error();}

return 0;

}

//--------------------------------------------
help(){  
	char* str1= " 1- HELP: prints this text\n 2- CLS: clear screen\n 3- DIR or LS: lists the files on card\n"; 
	char* str2= " 4- Or enter the name of a program\n";
	nextl();
  puts(str1);
  puts(str2);
}

//-------------------------------
error(){  
	char* str1= " No such command or program.\n";
	nextl();
  puts(str1);

}
it works if I do this :

Code: Select all

    asm call load_adress  
But with this don't work !!!!!!!!

Code: Select all

     asm call 8000h 
Here's the assembly:

Code: Select all

 ;	    // call our program 
   ;		  
   ;		  asm mov ax, 800h
   ;	
 	mov	 ax, 800h
   ;	
   ;		  asm mov ds, ax
   ;	
 	mov	 ds, ax
   ;	
   ;		  asm call far 800h:0000
   ;	
 	call	 far 800h:0000
   ;	
 
There is no change !
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: How to call a program from C?

Post by iansjack »

In one case you are doing a near call, in the other a far call. You may see no change, but the difference is the base address of the program. In the working case it is 0x8000, in the non-working case it is 0.

You don't show an example of a program that you try to call, but evidently it was built with a base address of 0x8000 rather than 0.

But why worry - if the near call works then use that method of calling the program.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: How to call a program from C?

Post by osdevnewbie »

iansjack wrote: In one case you are doing a near call, in the other a far call
.
Thanks again iansjack.
Excuse me, I did n't understand !

if the load_adress is defined like this:
char* load_adress= 0x8000;

1- why this works:
call load_adress

and this don't work?
call 0x8000
itsn't the same physical adress?

2- why also this code don't work:
mov ax, 800h
mov ds, ax
call 800H:00
logical adress 800h:00= phyical 8000h no?
But why worry - if the near call works then use that method of calling the program.
I need the far call for 2 reasons:
1- To get a complete segement for my applications, not only a part from the segment where the kernel is loaded.
2- As I said befor when I choose offset zero "org 00" in the startup file I can compile and exe2bin'e my code, but when I choose "org 8000" I get problems !!
so to avoid problems I want to use offset zero and do a far call (CS:00).
I hope the problem is clear now.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: How to call a program from C?

Post by iansjack »

I don't think you understand how segmented addressing works, and what assembler "org" directives do. And I'm afraid that this is not the place for tutorials in the basics of assembler programming.

The very best advice I can give you is to run you program under a debugger, watch what is happening, and try to understand it. Unfortunately, 16-bit real mode addressing is a lot harder in many ways that 32- or 64-bit protected mode programs. But the cardinal rule is (IMO) if you don't understand what the processor is doing then use an emulator and/or debugger to watch it in operation.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: How to call a program from C?

Post by osdevnewbie »

iansjack wrote:I don't think you understand how segmented addressing works, and what assembler "org" directives do.
Yes, I agree with u, segmentation is still a confusing subject for me !!!
Org is the origin adress from where code starts. This's what I know about this directive perhaps I'm wrong.
I'll revise my lessons very soon.
Many thanks any way.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: How to call a program from C?

Post by iansjack »

You need to understand that 0x800:0x0 and 0x0:0x8000 are not the same address. Yes, they refer to the same physical address, but logically you are dealing with different address spaces. The first one starts at location 0x0, the second at location 0x8000. Any absolute addresses in your program - referring to data or functions - needs to take this into account. The "org" directive tells the program where it will be loaded in memory; so in the first instance you would need an "org 0x0", in the second an "org 0x8000" for your program to function correctly.

Segmentation is a Frankenstein kludge that should have been dead and buried long ago.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: How to call a program from C?

Post by osdevnewbie »

iansjack wrote:You need to understand that 0x800:0x0 and 0x0:0x8000 are not the same address.
Very well understood. Thanks again.
But I still not understanding why "call 0x8000" is different than " call load_adress" ?

- Here is my COT.asm code:

Code: Select all

_text           segment byte public 'code'
_text           ends
_data           segment word public 'data'
_data           ends
_bss            segment word public 'bss'
_bss            ends

dgroup          group           _text, _data, _bss

_text           segment
                org 00h    ; 
begin:
_text           ends

                end     begin

If I choose org 8000h the code generated is 32k Kbs more than what it must be! and I can't exe2bin'e it.
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

Re: How to call a program from C?

Post by BASICFreak »

osdevnewbie wrote:if the load_adress is defined like this:
char* load_adress= 0x8000;

1- why this works:
call load_adress

and this don't work?
call 0x8000
itsn't the same physical adress?
http://x86.renejeschke.de/html/file_mod ... id_26.html

It is because an operand on call must be relative (to next instruction), unless it is a far call which requires SEGMENT:OFFSET

Your pointer "load_adress" (should be address BTW) is handled at assembler/compile time to be an exact point in memory, while 0x8000 is just an operand and the assembler will take it as is - it has no clue that it is a location in memory that you need calculated, it just knows you said to CALL EIP + 0x8000.

This one got me a few times in the past :)



Best regards,

B!
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
osdevnewbie
Member
Member
Posts: 36
Joined: Sat Mar 26, 2016 1:25 pm

Re: How to call a program from C?

Post by osdevnewbie »

BASICFreak wrote:
osdevnewbie wrote: It is because an operand on call must be relative (to next instruction), unless it is a far call which requires SEGMENT:OFFSET
Thanks BASICFreak for ur explanation.
Now if my loaded program at "load_adress = 8000h" is compiled with "org 0" not "org 8000h" how can I do a far call in form CS: 00?
Post Reply