Page 1 of 1
How to call a program from C?
Posted: Sat Mar 26, 2016 2:03 pm
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
Re: How to call a program from C?
Posted: Sun Mar 27, 2016 3:49 am
by iansjack
You can't do far calls in the tiny memory model.
Re: How to call a program from C?
Posted: Sun Mar 27, 2016 7:51 am
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.
Re: How to call a program from C?
Posted: Sun Mar 27, 2016 8:24 am
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.
Re: How to call a program from C?
Posted: Sun Mar 27, 2016 9:08 am
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.
Re: How to call a program from C?
Posted: Sun Mar 27, 2016 12:51 pm
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 :
But with this don't work !!!!!!!!
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 !
Re: How to call a program from C?
Posted: Sun Mar 27, 2016 1:16 pm
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.
Re: How to call a program from C?
Posted: Mon Mar 28, 2016 8:05 am
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.
Re: How to call a program from C?
Posted: Mon Mar 28, 2016 10:41 am
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.
Re: How to call a program from C?
Posted: Mon Mar 28, 2016 2:08 pm
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.
Re: How to call a program from C?
Posted: Mon Mar 28, 2016 2:23 pm
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.
Re: How to call a program from C?
Posted: Tue Mar 29, 2016 4:59 am
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.
Re: How to call a program from C?
Posted: Wed Mar 30, 2016 3:50 pm
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!
Re: How to call a program from C?
Posted: Sat Apr 02, 2016 6:22 am
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?