首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在ARM ABI中,如何访问全局变量?

在ARM ABI中,如何访问全局变量?
EN

Stack Overflow用户
提问于 2022-06-27 12:45:00
回答 1查看 82关注 0票数 1

我正在为ARM Cortex M3编写一个简单的多任务操作系统。我的线程总是使用进程堆栈指针运行。我继承了一个应用程序,它使用全局变量。我试图从线程代码中调用应用程序中的函数,但它没有正确地访问内存。下列陈述是否正确:

  1. --这些全局变量是通过某种相对地址访问的,该相对地址被放置在主堆栈上(使用MSP)?

使用PSP的

  1. 我的线程代码将永远无法访问它们

  1. 我需要在调用这些函数时切换到MSP,然后在使用我的线程?

时切换回PSP。

**编辑:澄清这是为一个皮质M

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-27 18:27:45

全局变量与堆栈无关,甚至与静态局部变量无关。

所以你只需要看看编译器的输出,它就会告诉你一切。

你的问题很模糊,你可以问许多不同的问题之一。我会展示一些基本知识,也许我会得到幸运。

请注意,一般来说,这应该与处理器、模式等无关--手臂、拇指、x86等等。与工具链有更多的关系。

如果这是太基本,而你是问一些非常高级的问题,这是不明显的,我将删除或重写,没有问题。

抛出代码总是一个解决问题的好主意。

flash.s

代码语言:javascript
复制
.thumb
.syntax unified

.word 0x20001000
.word reset

.thumb_func
reset:
    bl notmain
    b .

notmain.c

代码语言:javascript
复制
unsigned int x;
unsigned int y=5;

void notmain ( void )
{
    unsigned int z=7;
    x=++y;
    z--;
}

flash.ld

代码语言:javascript
复制
MEMORY
{
  rom     : ORIGIN = 0x00080000, LENGTH = 0x00001000
  ram     : ORIGIN = 0x20000000, LENGTH = 0x00001000
}

SECTIONS
{
    .text : { *(.text)   } > rom
    .bss : { *(.bss)   } > ram
    .data : { *(.data)   } > ram
}

构建

代码语言:javascript
复制
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m0 -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o notmain.o -o flash.elf
arm-none-eabi-objdump -D flash.elf > flash.list
arm-none-eabi-objcopy -O binary flash.elf flash.bin

检查

代码语言:javascript
复制
Disassembly of section .text:

00080000 <reset-0x8>:
   80000:   20001000    andcs   r1, r0, r0
   80004:   00080009    andeq   r0, r8, r9

00080008 <reset>:
   80008:   f000 f802   bl  80010 <notmain>
   8000c:   e7fe        b.n 8000c <reset+0x4>
    ...

00080010 <notmain>:
   80010:   4b04        ldr r3, [pc, #16]   ; (80024 <notmain+0x14>)
   80012:   4905        ldr r1, [pc, #20]   ; (80028 <notmain+0x18>)
   80014:   681a        ldr r2, [r3, #0]
   80016:   3201        adds    r2, #1
   80018:   601a        str r2, [r3, #0]
   8001a:   600a        str r2, [r1, #0]
   8001c:   685a        ldr r2, [r3, #4]
   8001e:   3a01        subs    r2, #1
   80020:   605a        str r2, [r3, #4]
   80022:   4770        bx  lr
   80024:   20000004    andcs   r0, r0, r4
   80028:   20000000    andcs   r0, r0, r0

Disassembly of section .bss:

20000000 <x>:
20000000:   00000000    andeq   r0, r0, r0

Disassembly of section .data:

20000004 <y>:
20000004:   00000005    andeq   r0, r0, r5

20000008 <z.3645>:
20000008:   00000007    andeq   r0, r0, r7

这是基本的,不可重定位的,等等。

代码语言:javascript
复制
   80010:   4b04        ldr r3, [pc, #16]   ; (80024 <notmain+0x14>)

   80014:   681a        ldr r2, [r3, #0]
   80016:   3201        adds    r2, #1
   80018:   601a        str r2, [r3, #0]

   80024:   20000004    andcs   r0, r0, r4


Disassembly of section .data:

20000004 <y>:
20000004:   00000005    andeq   r0, r0, r5

我们可以看到y++。r3获取y的地址,r2获取y r2增量的值,然后保存回内存。

你也可以看到x和z是如何处理的。

现在,由于以下几个原因,这对于mcu来说是行不通的。0x20000000地址信息将不存在。只有在非易失性存储器中的东西才会在芯片启动和复位后出现。根据你真正的问题是什么,上面的内容是相关的。

代码语言:javascript
复制
MEMORY
{
  rom     : ORIGIN = 0x00080000, LENGTH = 0x00001000
  ram     : ORIGIN = 0x20000000, LENGTH = 0x00001000
}

SECTIONS
{
    .text : { *(.text)   } > rom
    .bss : { *(.bss)   } > ram AT > rom
    .data : { *(.data)   } > ram AT > rom
}

程序没有改变,但是二进制文件改变了。

代码语言:javascript
复制
00000000  00 10 00 20 09 00 08 00  00 f0 02 f8 fe e7 00 00  |... ............|
00000010  04 4b 05 49 1a 68 01 32  1a 60 0a 60 5a 68 01 3a  |.K.I.h.2.`.`Zh.:|
00000020  5a 60 70 47 04 00 00 20  00 00 00 20 05 00 00 00  |Z`pG... ... ....|
00000030  07 00 00 00                                       |....|
00000034

在0x2C,我们看到y的预加载值和z的0x30。

.bss值不在这里。通常,您要做的是向链接器脚本中添加更多的内容,以获取内容的地址。数据开始和停止,和bss启动和大小或停止。然后,一个从flash复制到ram的引导程序,以便初始化的值在ram中,读/写工作。

因此,如果您的项目,无论是否称为操作系统,它只是一个庞大的代码体,被编译和链接在一起。然后不做一些特殊的事情,比如很多章节之类的。以上是您所看到的,堆栈与全局无关。因为它从来都不是正常的。

(msp/psp不像arm所暗示的那样工作,我还没有看到第二个堆栈指针的用例,如果处理器有它,它们也没有全部实现)

现在,如果您的线程实际上是单独构建的程序,您可以加载runtime...Then,那么它们完全位于ram中。所以

代码语言:javascript
复制
MEMORY
{
  rom     : ORIGIN = 0x00080000, LENGTH = 0x00001000
  ram     : ORIGIN = 0x20000000, LENGTH = 0x00001000
}

SECTIONS
{
    .text : { *(.text)   } > ram
    .bss : { *(.bss)   } > ram
    .data : { *(.data)   } > ram
}

我们加入了-fPIC

代码语言:javascript
复制
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m0 -fPIC -c notmain.c -o notmain.o

Disassembly of section .text:

20000000 <reset-0x8>:
20000000:   20001000    andcs   r1, r0, r0
20000004:   20000009    andcs   r0, r0, r9

20000008 <reset>:
20000008:   f000 f802   bl  20000010 <notmain>
2000000c:   e7fe        b.n 2000000c <reset+0x4>
    ...

20000010 <notmain>:
20000010:   4a07        ldr r2, [pc, #28]   ; (20000030 <notmain+0x20>)
20000012:   4b08        ldr r3, [pc, #32]   ; (20000034 <notmain+0x24>)
20000014:   447a        add r2, pc
20000016:   58d1        ldr r1, [r2, r3]
20000018:   680b        ldr r3, [r1, #0]
2000001a:   3301        adds    r3, #1
2000001c:   600b        str r3, [r1, #0]
2000001e:   4906        ldr r1, [pc, #24]   ; (20000038 <notmain+0x28>)
20000020:   5852        ldr r2, [r2, r1]
20000022:   6013        str r3, [r2, #0]
20000024:   4a05        ldr r2, [pc, #20]   ; (2000003c <notmain+0x2c>)
20000026:   447a        add r2, pc
20000028:   6813        ldr r3, [r2, #0]
2000002a:   3b01        subs    r3, #1
2000002c:   6013        str r3, [r2, #0]
2000002e:   4770        bx  lr
20000030:   00000034    andeq   r0, r0, r4, lsr r0
20000034:   00000004    andeq   r0, r0, r4
20000038:   00000000    andeq   r0, r0, r0
2000003c:   0000001a    andeq   r0, r0, sl, lsl r0

Disassembly of section .bss:

20000040 <x>:
20000040:   00000000    andeq   r0, r0, r0

Disassembly of section .data:

20000044 <z.3645>:
20000044:   00000007    andeq   r0, r0, r7

20000048 <y>:
20000048:   00000005    andeq   r0, r0, r5

Disassembly of section .got:

2000004c <.got>:
2000004c:   20000040    andcs   r0, r0, r0, asr #32
20000050:   20000048    andcs   r0, r0, r8, asr #32

Disassembly of section .got.plt:

20000054 <_GLOBAL_OFFSET_TABLE_>:
    ...

因为您可能需要能够在ram中的任何地方(在规则范围内)加载程序。

代码都是相对的,但是由于编译和链接的性质,数据需要一些硬编码。所以他们设置了一个全局偏移表。got的位置相对于代码,您不能更改它。

代码语言:javascript
复制
20000010:   4a07        ldr r2, [pc, #28]   ; (20000030 <notmain+0x20>)
20000012:   4b08        ldr r3, [pc, #32]   ; (20000034 <notmain+0x24>)
20000014:   447a        add r2, pc
20000016:   58d1        ldr r1, [r2, r3]
20000018:   680b        ldr r3, [r1, #0]
2000001a:   3301        adds    r3, #1
2000001c:   600b        str r3, [r1, #0]

这是您的y++时,建立独立的位置。

r2得到一个偏移量,r3得到另一个偏移量。r2是与代码之间的GOT的相对偏移量(您不能将它们分开,不能移动其中一个,而不是另一个位置独立的意思),所以现在r2指向got。r3是GOT到y地址的偏移量,r1得到y的地址,现在它就像以前在r3中得到y,添加一个,节省y到内存。

现在,如果您要将这个地址重新定位到一个不是0x20000000的地址,您的引导程序需要转到GOT并修补所有的地址,所以您需要链接魔法才能获得got的位置和它的位数,etc...Use会让pc知道您在哪里,然后进行调整。如果在0x20002000加载到内存中,则需要将0x2000添加到表中的每个条目中,然后所有这些都将正常工作。(仍然没有堆栈,堆栈不相关)。

如果你有空间的话,这是个小把戏。

请注意,我将bss放在数据之前,并且至少有一个.data项。如果您能够保证这一点(例如,在引导中强制一个.data )。

代码语言:javascript
复制
00000000  00 10 00 20 09 00 00 20  00 f0 02 f8 fe e7 00 00  |... ... ........|
00000010  07 4a 08 4b 7a 44 d1 58  0b 68 01 33 0b 60 06 49  |.J.KzD.X.h.3.`.I|
00000020  52 58 13 60 05 4a 7a 44  13 68 01 3b 13 60 70 47  |RX.`.JzD.h.;.`pG|
00000030  34 00 00 00 04 00 00 00  00 00 00 00 1a 00 00 00  |4...............|
00000040  00 00 00 00 07 00 00 00  05 00 00 00 40 00 00 20  |............@.. |
00000050  48 00 00 20 00 00 00 00  00 00 00 00 00 00 00 00  |H.. ............|
00000060

20000040 <x>:
20000040:   00000000    andeq   r0, r0, r0

Objdump将-O二进制的二进制与.bss的零放在一起,如果最后将它放在最后,则假定它不起作用。

因此,我不知道这段代码是如何使用线程和全局的,它是否试图保留每个线程的特定变量?如果是这样的话,它是否在前面使用静态局部变量,然后在堆栈上传递地址(即使在那里,您使用的堆栈指针也不重要,除非您通常没有正确地使用堆栈,如果没有,则全局值不是您的问题。)

如果在一个堆栈指针上启动线程或任何代码,并暗示完全独立的堆栈(内存地址空间)。然后切换,放弃代码进出函数所需的堆栈信息,然后如果在转换堆栈之后从函数返回,所有代码都会中断,而不仅仅是指向传递给静态局部变量的指针。

所以,一个很小的例子可以为我们证实到底发生了什么,你的问题到底是什么,问题是什么。如果您想使用两个堆栈指针作为皮层-m,您需要仔细阅读,您还需要编写一些丢弃的代码示例,看看它是如何工作的,然后将它应用到工具生成的代码中。

再一次,如果这是太基本,而我离真正的问题很远,我肯定会删除这个没有问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72772325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档