好的,这里有一个文件,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
作为前一文件停止处的 * 添加 *。.org
的description为:
.org *new-lc,填写 *:将目前区段的位置计数器前移至 new-lc。new-lc 是绝对运算式,或是与目前子区段具有相同区段的运算式。
显然我不明白“advance to”是什么意思。也许他们的意思是“advance by”。无论如何,我如何让avr-gcc把代码放在指定的地方呢?我希望有一个更简单的解决方案,而不是定义一个脚本文件并通过-Wl,-T
传递它。
只要有人能向我解释.org
指令描述中的“advance to”是什么意思,我就接受“是的,没有脚本文件就做不到”的回答。
1条答案
按热度按时间carvr3hs1#
在链接时的定位步骤中,有一个实体描述了“当前位置”,它的值是链接器描述文件中的简单点
.
。以./avr/lib/ldscripts/avr5.xn
的这一部分为例,它定位了静态构造函数和析构函数,并定义了一些符号,如__ctors_start
:.
的一个特性是它不能向后移动。进入您的项目,您将通过
> avr-gcc ... single_step_rom.S tinyrom_2313.S
由于输入文件的顺序,链接器/定位器首先看到的是
从
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由于
.
不能向后移动,因此.org 0x0
的效果无效。如何修复
方式1:(错误)使用现有的输入区段。
.text输出节收集了许多输入节,只需查看设备的默认链接器描述文件即可。例如,在我的binutils版本中,
*(.text*)
后面是*(.hightext)
。因此,您可以将代码定位到.text
节,将表数据定位到.hightext
,如然后加载地址,如下所示:
注意,
.org
将完全消失。此外,第一条跳转指令技术上将转到.vectors
,因为它是第一个向量(重置),所有其他代码将转到.text
。方式2:使用连接器指令码扩充
使用增强,如
然后将这几行存储为
my_data.ld
,并在链接过程中通过-T mydata.ld
提供。将您的表数据放入.my_data
部分。要访问它,请定义一个适当的符号,如方式1。