Writing a C program to call another program withou

2019-06-14 19:21发布

I am trying to write a simple 'go-command' for boot-loader that takes me to specific address in RAM say 0x18000000 and it should execute a program that blinks led. I have two .c files say led.c and go.c in which led.c blinks two leds. But I am wondering and don't know that how can I pass a control/invoke its main() to this go.c file to go to that address and start blinking leds? But it should be done without including other header files, libraries, etc. Kindly help me!! Thanks in advance. Below code is for led.c

void delay ()
{
    volatile int i;
    for(i=0;i<1000000;i++)
    {}

}
int main(void)
{
    *led0=0;
    *led1=0;
    while(1)
    {
        *led0=1;
        delay();
        *led0=0;
        *led1=1;
        delay();
        *led1=0;
    }
}

In my go.c file I want to pass a control to invoke this led.c main() func

3条回答
ら.Afraid
2楼-- · 2019-06-14 19:53

There is a lot you have omitted that is likely to be relevant, but taken at face value, you simply declare a function pointer, initialised with the absolute address and invoke the function through that pointer.

However it may not be that simple since the called program will use the C run-time environment of the calling program; any global static objects will not be initialised - you need to call the program entry point (which is notmain()) to establish the run-time environment expected by the program. In simple case it may work or appear to work to some extent.

查看更多
男人必须洒脱
3楼-- · 2019-06-14 19:58

So I have an sifive riscv board, going to be a little different than yours but here is an led blinker program (compiled version):

Disassembly of section .text:

80001000 <_start>:
80001000:   80004137            lui x2,0x80004
80001004:   016000ef            jal x1,8000101a <notmain>
80001008:   9002                    ebreak
8000100a:   a001                    j   8000100a <_start+0xa>

8000100c <dummy>:
8000100c:   8082                    ret

8000100e <PUT32>:
8000100e:   00b52023            sw  x11,0(x10)
80001012:   8082                    ret

80001014 <GET32>:
80001014:   00052503            lw  x10,0(x10)
80001018:   8082                    ret

8000101a <notmain>:
8000101a:   1101                    addi    x2,x2,-32
8000101c:   c84a                    sw  x18,16(x2)
8000101e:   10012937            lui x18,0x10012
80001022:   00890513            addi    x10,x18,8 # 10012008 <_start-0x6ffeeff8>
80001026:   006805b7            lui x11,0x680
8000102a:   ce06                    sw  x1,28(x2)
8000102c:   ca26                    sw  x9,20(x2)
8000102e:   c64e                    sw  x19,12(x2)
80001030:   cc22                    sw  x8,24(x2)
80001032:   3ff1                    jal 8000100e <PUT32>
80001034:   00c90513            addi    x10,x18,12
80001038:   006805b7            lui x11,0x680
8000103c:   3fc9                    jal 8000100e <PUT32>
8000103e:   04090513            addi    x10,x18,64
80001042:   4581                    li  x11,0
80001044:   001e84b7            lui x9,0x1e8
80001048:   37d9                    jal 8000100e <PUT32>
8000104a:   006809b7            lui x19,0x680
8000104e:   0931                    addi    x18,x18,12
80001050:   48048493            addi    x9,x9,1152 # 1e8480 <_start-0x7fe18b80>
80001054:   85ce                    mv  x11,x19
80001056:   854a                    mv  x10,x18
80001058:   3f5d                    jal 8000100e <PUT32>
8000105a:   4401                    li  x8,0
8000105c:   8522                    mv  x10,x8
8000105e:   0405                    addi    x8,x8,1
80001060:   3775                    jal 8000100c <dummy>
80001062:   fe941de3            bne x8,x9,8000105c <notmain+0x42>
80001066:   4581                    li  x11,0
80001068:   854a                    mv  x10,x18
8000106a:   3755                    jal 8000100e <PUT32>
8000106c:   4401                    li  x8,0
8000106e:   8522                    mv  x10,x8
80001070:   0405                    addi    x8,x8,1
80001072:   3f69                    jal 8000100c <dummy>
80001074:   fe941de3            bne x8,x9,8000106e <notmain+0x54>
80001078:   bff1                    j   80001054 <notmain+0x3a>

the disassembly spacing is a little broken but thats okay. The entry point IS NOT AT MAIN() for a normal program it is at the start in this case 0x80001000 NOT 0x8000101A which I intentionally name something other than main on purpose (for bare metal)...There should be no reason for you to to enter at main you should enter at the entry point...I will let you simply fail if you continue to try otherwise, you are on your own with that.

So this represents an srec of the above.

S00F00006E6F746D61696E2E737265631F
S3158000100037410080EF006001029001A0828023209A
S31580001010B500828003250500828001114AC83729E0
S31580001020011013058900B705680006CE26CA4EC68C
S3158000103022CCF13F1305C900B7056800C93F1305E7
S3158000104009048145B7841E00D937B709680031097C
S3158000105093840448CE854A855D3F014422850504F4
S315800010607537E31D94FE81454A85553701442285AF
S30F800010700504693FE31D94FEF1BFFD
S705800010006A

I/we assume you are not actually downloading that to ram as is, that will never execute, your bootloader has to parse that then write the program to ram, two different things (the program itself and a file format that describes that program).

Assuming you get to that point, all you need to do is branch to 0x80001000 in my case or 0x18000000 in yours.

so taking the answer already provided to you you can do this to launch the downloaded program

void hop ( void )
{
    void *func_ptr = (void *)0x80001000;
    goto *func_ptr;
}

which results in

Disassembly of section .text:

00000000 <hop>:
   0:   800017b7            lui x15,0x80001
   4:   8782                    jr  x15

Or my personal preference would be:

.globl HOP
HOP:
    jr x11

which from C I would call with

HOP(0x80001000);

that way I can insure the instruction I wanted is used. YMMV.

How far along this path have you gotten? Are you stuck at the last step? Simone provided an answer that should work just fine, there are other variations on that theme from C that you can use, but that one already appears to work.

查看更多
唯我独甜
4楼-- · 2019-06-14 20:08

GCC has an extension that allows jumping to an arbitrary address, so if you know the address of your led.c main you could do something like that:

void *func_ptr = (void *)0x1234567;  // address of your led routine
goto *func_ptr;                      

However, you probably don't have the address of the led routine and it is not a very safe operation. Jumping to some unknown address will probably result in a crash!!

查看更多
登录 后发表回答