-1

我正在为一个辅助项目制作一个引导加载程序。

我读入了一个十六进制文件,验证了校验和,并将所有内容存储在闪存中,对应的地址偏移为 0x4000。我在跳转到我的应用程序时遇到问题。我已经阅读、搜索并尝试了很多不同的东西,比如这里的代码。

http://www.keil.com/support/docs/3913.htm

我当前的代码是这样的;

int binary_exec(void * Address){
    int i;
    __disable_irq();
// Disable IRQs
for (i = 0; i < 8; i ++) NVIC->ICER[i] = 0xFFFFFFFF;
// Clear pending IRQs
for (i = 0; i < 8; i ++) NVIC->ICPR[i] = 0xFFFFFFFF;

// -- Modify vector table location
// Barriars
__DSB();
__ISB();
// Change the vector table
SCB->VTOR = ((uint32_t)0x4000 & 0x1ffff80);
// Barriars
__DSB();
__ISB();

__enable_irq();

// -- Load Stack & PC
binExec(Address);
return 0;
}

__asm void binexec(uint32_t *address)
{
    mov   r1, r0    
   ldr   r0, [r1, #4] 
   ldr   sp, [r1]     
   blx   r0"

}

这只是跳转到一个随机位置,不做任何事情。我已经使用 keil 的注册窗口手动将地址添加到 PC,它直接跳转到我的应用程序,但我还没有找到使用代码的方法。有任何想法吗?先感谢您。

十六进制文件的倒数第二行还有起始线性地址记录: http ://www.keil.com/support/docs/1584.htm

有谁知道这条线怎么办?

谢谢,

埃里克·米卡勒夫

4

1 回答 1

1

这就是我所说的,你能给我们展示一些看起来像这样的片段吗,这是一个完整的应用程序,只是没有做太多......

20004000 <_start>:
20004000:   20008000
20004004:   20004049
20004008:   2000404f
2000400c:   2000404f
20004010:   2000404f
20004014:   2000404f
20004018:   2000404f
2000401c:   2000404f
20004020:   2000404f
20004024:   2000404f
20004028:   2000404f
2000402c:   2000404f
20004030:   2000404f
20004034:   2000404f
20004038:   2000404f
2000403c:   20004055
20004040:   2000404f
20004044:   2000404f

20004048 <reset>:
20004048:   f000 f806   bl  20004058 <notmain>
2000404c:   e7ff        b.n 2000404e <hang>

2000404e <hang>:
2000404e:   e7fe        b.n 2000404e <hang>

20004050 <dummy>:
20004050:   4770        bx  lr
    ...

20004054 <systick_handler>:
20004054:   4770        bx  lr
20004056:   bf00        nop

20004058 <notmain>:
20004058:   b510        push    {r4, lr}
2000405a:   2400        movs    r4, #0
2000405c:   4620        mov r0, r4
2000405e:   3401        adds    r4, #1
20004060:   f7ff fff6   bl  20004050 <dummy>
20004064:   2c64        cmp r4, #100    ; 0x64
20004066:   d1f9        bne.n   2000405c <notmain+0x4>
20004068:   2000        movs    r0, #0
2000406a:   bd10        pop {r4, pc}

偏移量 0x00 是堆栈指针

20004000:   20008000

偏移量 0x04 是复位向量或该程序的入口点

20004004:   20004049

我填写了未使用的,因此它们陷入无限循环

20004008:   2000404f

并扔进一个不同的只是为了展示

2000403c:   20004055

在这种情况下,VTOR 将设置为 0x2004000,我将从 0x20004004 读取 0x20004049,然后将 BX 读取到该地址。

所以我的 binexec 将得到地址 0x20004000 我会做这样的事情

ldr r1,[r0]
mov sp,r1
ldr r2,[r0,#4]
bx r2

如果我想伪造该代码的重置。thumb2 的 thumb 方法我假设你可以 ldr sp,[r0],我不手动编码 thumb2,所以没有记住这些,并且有不同的 thumb2 扩展集,以及气体中的不同语法选项。

现在,如果您不打算支持中断,或者出于其他原因(可能在您的闪存中携带一些您想要更好地执行的二进制代码,然后将其从闪存复制到 ram 然后在 ram 中使用它),您可以下载到 ram 应用程序这只是在入口点有它的第一条指令,没有向量表:

20004000 <_start>:
20004000:   f000 f804   bl  2000400c <notmain>
20004004:   e7ff        b.n 20004006 <hang>

20004006 <hang>:
20004006:   e7fe        b.n 20004006 <hang>

20004008 <dummy>:
20004008:   4770        bx  lr
    ...

2000400c <notmain>:
2000400c:   b510        push    {r4, lr}
2000400e:   2400        movs    r4, #0
20004010:   4620        mov r0, r4
20004012:   3401        adds    r4, #1
20004014:   f7ff fff8   bl  20004008 <dummy>
20004018:   2c64        cmp r4, #100    ; 0x64
2000401a:   d1f9        bne.n   20004010 <notmain+0x4>
2000401c:   2000        movs    r0, #0
2000401e:   bd10        pop {r4, pc}

在这种情况下,需要同意下载的程序是为 0x20004000 构建的,您可以将数据下载到该地址,但是当您想运行它时,您可以这样做

.globl binexec
binexec:
  bx r0

在 C 中

binexec(0x20004000|1);

或者

.globl binexec
binexec:
  orr r0,#1
  bx r0

只是为了安全(r)。

在这两种情况下,如果您希望它们运行,您都需要正确构建二进制文件,两者都必须链接到目标地址,特别是向量表方法,因此问题是,您能否向我们展示您的一个示例向量表下载,程序,甚至前几句话就足够了......

于 2017-05-07T01:36:48.343 回答