跳转到内联 AVR C 中的地址

问题描述 投票:0回答:2

我正在尝试为arduino编写一个程序,它可以可变地计算绝对地址,然后跳转到它(这是具有更大用途的更大程序的一部分),但是我遇到了一些麻烦。目前,我正在做类似以下的事情:

  uint16_t v_pc;
  uint16_t jmpAddress;

  jmpAddress = 0x00cf;
  v_pc = 0x01;


  jmpAddress = calc_address(jmpAddress, v_pc);

  asm("jmp %0" :: "r" (jmpAddress)); 

其中 calc_address 是:

uint16_t calc_address(uint16_t jmpAddress, uint16_t v_pc){
    return jmpAddress += v_pc;
}

但是,当我尝试链接该程序(即 avr-gcc -mmcu=atmega328p program.o -o program)时,出现以下错误:

对“r24”的未定义引用
collect2:错误:ld 返回 1 退出状态

是否有更好的方法可以实现此目的,或者有人可以描述为什么会发生此错误?

谢谢!

c assembly arduino memory-address avr-gcc
2个回答
1
投票

JMP
不将寄存器作为操作数。对于间接跳转,您可以使用
IJMP
但隐式使用
Z
寄存器。因此,您的内联汇编应该看起来更像:

asm("ijmp" :: "z" (jmpAddress)); 

0
投票

有两种情况需要考虑:程序内存为 128 KiB 或更少的设备,以及程序内存更大的设备。

具有 128 KiB 或更少程序内存的 AVR 设备

一开始就不需要内联汇编。 您只需计算字地址并通过该指针调用该函数即可。 从语法上讲,最简单的方法是

typedef
一个相应的函数指针类型,如下所示
func_t

typedef void (*func_t)(void);

extern func_t calc_address (uint16_t, uint16_t);

void my_code (void)
{
    // Compute word address.
    func_t pfunc = calc_address (0x00cf, 0x01);

    // Indirect call to computed word address.
    pfunc ();

    // Call word address 0x1234 (byte address 0x2468).
    pfunc = (func_t) 0x1234;
    pfunc ();
}

程序内存超过 128 KiB 的 AVR 设备

AVR 的 GNU 工具中的函数指针是 16 位宽,因此它们最多可以定位 64 KiWords = 128 KiB 的范围。 在较大的设备上,这些工具将使用所谓的 calles 链接器存根来促进超出 128 KiB 边界的间接调用。 请参阅 avr-gcc:

EIND
以及具有超过 128 Ki 字节闪存的设备

案例1:跳转到不同的代码标签

calc_address
只是返回某些标签的地址时,编译器将使用
gs()
修饰符计算它们的地址。 这将根据需要弹出链接器存根,并且可以像 <= 128 KiB case.

中一样使用 16 位地址

案例 2:针对任意地址

这更复杂,因为

calc_address
不会返回某个标签的地址,而是返回任意代码位置。 这意味着您必须使用宽度超过 16 位的实体来保存地址。 并且您必须使用内联汇编来跳转到该地址。 请注意,
EIND
寄存器没有任何帮助,因为您可以跳转到任何位置,但无法在被调用者中重置
EIND
。 因此下面的代码使用
RET
来完成间接跳转:

typedef uint32_t xfunc_t;

void my_code (void)
{
    // Word address 0x12345 (byte address 0x2468a).
    xfunc_t pfunc = 0x12345;

    // Indirect jump to address.
    __asm volatile ("push %A0"   "\n\t"
                    "push %B0"   "\n\t"
                    "push %C0"   "\n\t"
                    "ret" :: "r" (pfunc) : "memory");
}
© www.soinside.com 2019 - 2024. All rights reserved.