assembly 链接两个.S文件时avr-gcc不遵守.org指令

yduiuuwa  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(152)

好的,这里有一个文件,tinyrom_2313.S

.text

.org 0
.global init

init:
    rjmp main

.org 0x0020
.global main

main:
    cli

    // Disable watchdog timer

    wdr
    ldi r16, 0x00
    out _SFR_IO_ADDR(MCUSR), r16
    in r17, _SFR_IO_ADDR(WDTCSR)
    ori r17, _BV(WDCE) | _BV(WDE)
    out _SFR_IO_ADDR(WDTCSR), r17
    out _SFR_IO_ADDR(WDTCSR), r16

    // Disable input pullups

    ldi r16, _BV(PUD)
    out _SFR_IO_ADDR(MCUCR), r16

    // Pin directions are all
    // inputs on reset.

    // Set pin directions:
    //   PA2 - PA0 are inputs
    //   PB7 - PB0 are inputs
    //   PD6 - PD0 are outputs

    ldi r16, 0xFF
    out _SFR_IO_ADDR(DDRD), r16

    // We store the data table at 0x0100.

    ldi ZH, 0x01
loop:
    in ZL, _SFR_IO_ADDR(PINB)
    lpm r0, Z
    out _SFR_IO_ADDR(PORTD), r0
    rjmp loop

下面是第二个文件single_step_rom.S

.text
.org 0x0100
//          / N     H    C
//          H E     O S  U
//          O X     LRT  R
//          L T     DUE  R
//          D___    ANP ___
.byte 0b00000000 // 000 000
.byte 0b00001010 // 000 001
.byte 0b00000011 // 000 010
.byte 0b00000011 // 000 011
.byte 0b00001101 // 000 100
.byte 0b00001110 // 000 101
.byte 0b00001110 // 000 110
.byte 0b00000011 // 000 111
.byte 0b00000001 // 001 000
.byte 0b00000001 // 001 001
.byte 0b00000011 // 001 010
.byte 0b00000011 // 001 011
.byte 0b00001101 // 001 100
.byte 0b00001110 // 001 101
.byte 0b00001111 // 001 110
.byte 0b00001111 // 001 111
.byte 0b00000100 // 010 000
.byte 0b00001010 // 010 001
.byte 0b00000011 // 010 010
.byte 0b00000011 // 010 011
.byte 0b00000100 // 010 100
.byte 0b00001110 // 010 101
.byte 0b00001110 // 010 110
.byte 0b00000011 // 010 111
.byte 0b00000001 // 011 000
.byte 0b00000001 // 011 001
.byte 0b00000011 // 011 010
.byte 0b00000011 // 011 011
.byte 0b00000100 // 011 100
.byte 0b00001110 // 011 101
.byte 0b00001111 // 011 110
.byte 0b00001111 // 011 111
.byte 0b00000000 // 100 000
.byte 0b00001010 // 100 001
.byte 0b00001010 // 100 010
.byte 0b00000000 // 100 011
.byte 0b00001101 // 100 100
.byte 0b00001101 // 100 101
.byte 0b00001110 // 100 110
.byte 0b00000011 // 100 111
.byte 0b00000001 // 101 000
.byte 0b00000001 // 101 001
.byte 0b00001010 // 101 010
.byte 0b00000000 // 101 011
.byte 0b00001101 // 101 100
.byte 0b00001101 // 101 101
.byte 0b00001111 // 101 110
.byte 0b00001111 // 101 111
.byte 0b00000100 // 110 000
.byte 0b00001010 // 110 001
.byte 0b00001010 // 110 010
.byte 0b00000000 // 110 011
.byte 0b00000100 // 110 100
.byte 0b00001101 // 110 101
.byte 0b00001110 // 110 110
.byte 0b00000011 // 110 111
.byte 0b00000001 // 111 000
.byte 0b00000001 // 111 001
.byte 0b00001010 // 111 010
.byte 0b00000000 // 111 011
.byte 0b00000100 // 111 100
.byte 0b00001101 // 111 101
.byte 0b00001111 // 111 110
.byte 0b00001111 // 111 111

现在,我编译:

avr-gcc -nostartfiles -mmcu=attiny2313 -Wl,-Map,map.txt -o single_step_rom.elf single_step_rom.S tinyrom_2313.S

我发现它把single_step_rom正确地放在了0x0100,但是它把tinyrom_2313固定在了0x0140。换句话说,看起来avr-gcc完全忽略了tinyrom_2313.S中的.org指令。
交换.S文件的顺序会产生相反的问题:tinyrom_2313正确地位于0x0000,但随后single_step_rom被放置在0x0142,就好像avr-gcc正在使用.org 0x0100作为前一文件停止处的 * 添加 *。
.orgdescription为:
.org *new-lc,填写 *:将目前区段的位置计数器前移至 new-lcnew-lc 是绝对运算式,或是与目前子区段具有相同区段的运算式。
显然我不明白“advance to”是什么意思。也许他们的意思是“advance by”。无论如何,我如何让avr-gcc把代码放在指定的地方呢?我希望有一个更简单的解决方案,而不是定义一个脚本文件并通过-Wl,-T传递它。
只要有人能向我解释.org指令描述中的“advance to”是什么意思,我就接受“是的,没有脚本文件就做不到”的回答。

carvr3hs

carvr3hs1#

在链接时的定位步骤中,有一个实体描述了“当前位置”,它的值是链接器描述文件中的简单点.。以./avr/lib/ldscripts/avr5.xn的这一部分为例,它定位了静态构造函数和析构函数,并定义了一些符号,如__ctors_start

__ctors_start = . ;
     *(.ctors)
     __ctors_end = . ;
     __dtors_start = . ;
     *(.dtors)
     __dtors_end = . ;

.的一个特性是它不能向后移动。

进入您的项目,您将通过
> avr-gcc ... single_step_rom.S tinyrom_2313.S
由于输入文件的顺序,链接器/定位器首先看到的是

.text
.org 0x100

single_step_rom.S(或从各自的.o) to be precise. Thus. is advanced to 0x100, the data is put there, and then comes tinyrom_2313.S 's

.text
.org 0

由于.不能向后移动,因此.org 0x0的效果无效。

如何修复

方式1:(错误)使用现有的输入区段。

.text输出节收集了许多输入节,只需查看设备的默认链接器描述文件即可。例如,在我的binutils版本中,*(.text*)后面是*(.hightext)。因此,您可以将代码定位到.text节,将表数据定位到.hightext,如

.section .hightext, "a", @progbits
.balign 0x100
.global my_data
my_data:
   .byte ...

然后加载地址,如下所示:

ldi ZH, hi8(my_data)

注意,.org将完全消失。此外,第一条跳转指令技术上将转到.vectors,因为它是第一个向量(重置),所有其他代码将转到.text

方式2:使用连接器指令码扩充

使用增强,如

SECTIONS
{
    .text :
    {
        . = ALIGN(0x100);
        *(.my_data*)
    }
}
INSERT AFTER .text

然后将这几行存储为my_data.ld,并在链接过程中通过-T mydata.ld提供。将您的表数据放入.my_data部分。要访问它,请定义一个适当的符号,如方式1。

相关问题