【问题标题】:ARM assembly not working without .type macroARM 程序集在没有 .type 宏的情况下无法工作
【发布时间】:2020-04-17 18:03:01
【问题描述】:

我正在为 STM32F0 (ARM Cortex M0) 微控制器学习一些 (ARMv6-M) 汇编程序。对于初学者,我编写了一个脚本,将寄存器r0 初始化为0,将r1 初始化为1,最后,r0 在循环中递增1。使用调试器,即gdb,我可以使用si 运行一步,使用info reg 输出寄存器。汇编代码如下,

.syntax unified
.cpu cortex-m0
.fpu softvfp
.thumb

.global vector_table
.global reset_handler

.type vector_table, %object
vector_table:
    .word _estack
    .word reset_handler

.type reset_handler, %function
reset_handler:
    LDR r0, =0
    LDR r1, =1

    main_loop:
        ADDS r0, r0, 1
    B main_loop

并且基于this excellent tutorial

当我删除.type x 宏时,我通过调试器看不到寄存器有任何变化,但是根据this stackoverflow post .type-macro 应该没有效果。

当我删除.type-宏时,为什么寄存器r0r1保持不变?

【问题讨论】:

  • 验证您的向量表。我的猜测是,如果没有.type,该条目就没有将函数标记为拇指所需的 LSB 集。所以它将被解释为 ARM,它可能会解码为一些完全不相关的指令。
  • @Jester 你能详细说明一下吗?我只有一个链接器脚本,我在其中定义 MEMORY { ... }_estack
  • 是armv6-m绝对不是armv6

标签: assembly arm stm32


【解决方案1】:
.syntax unified
.cpu cortex-m0
.fpu softvfp
.thumb

.global vector_table
.global reset_handler

.type vector_table, %object
vector_table:
    .word 0x20001000
    .word reset_handler

.type reset_handler, %function
reset_handler:
    LDR r0, =0
    LDR r1, =1

使用 .type 函数

Disassembly of section .text:

00001000 <vector_table>:
    1000:   20001000    andcs   r1, r0, r0
    1004:   00001009    andeq   r1, r0, r9

00001008 <reset_handler>:
    1008:   4800        ldr r0, [pc, #0]    ; (100c <reset_handler+0x4>)
    100a:   4901        ldr r1, [pc, #4]    ; (1010 <reset_handler+0x8>)
    100c:   00000000    andeq   r0, r0, r0
    1010:   00000001    andeq   r0, r0, r1

用于复位的向量表具有正确的地址 ORRed 和 1 0x1009。如果删除函数声明

disassembly of section .text:

00001000 <vector_table>:
    1000:   20001000    andcs   r1, r0, r0
    1004:   00001008    andeq   r1, r0, r8

00001008 <reset_handler>:
    1008:   4800        ldr r0, [pc, #0]    ; (100c <reset_handler+0x4>)
    100a:   4901        ldr r1, [pc, #4]    ; (1010 <reset_handler+0x8>)
    100c:   00000000    andeq   r0, r0, r0
    1010:   00000001    andeq   r0, r0, r1

您会得到一个无法在 cortex-m 上启动的二进制文件。对于 thumb 你也可以使用 .thumb_func 并且找到的下一个标签被认为是一个函数:

.thumb_func
reset_handler:
    LDR r0, =0
    LDR r1, =1

你又好了,二进制文件可以工作了:

so.elf:     file format elf32-littlearm


Disassembly of section .text:

00001000 <vector_table>:
    1000:   20001000    andcs   r1, r0, r0
    1004:   00001009    andeq   r1, r0, r9

00001008 <reset_handler>:
    1008:   4800        ldr r0, [pc, #0]    ; (100c <reset_handler+0x4>)
    100a:   4901        ldr r1, [pc, #4]    ; (1010 <reset_handler+0x8>)
    100c:   00000000    andeq   r0, r0, r0
    1010:   00000001    andeq   r0, r0, r1

如果您希望 gnu(s 链接器) 为您在函数之间进行蹦床,这也是 thumb interwork 所必需的:

.syntax unified
.cpu arm7tdmi
.thumb

.global vector_table
.global reset_handler

.type vector_table, %object
vector_table:
    .word 0x20001000
    .word reset_handler

.thumb_func
reset_handler:
    LDR r0, =0
    LDR r1, =1
    bl hello

.arm

.type hello, %function
hello:
    b reset_handler

给予

Disassembly of section .text:

00001000 <vector_table>:
    1000:   20001000    andcs   r1, r0, r0
    1004:   00001009    andeq   r1, r0, r9

00001008 <reset_handler>:
    1008:   4802        ldr r0, [pc, #8]    ; (1014 <hello+0x4>)
    100a:   4903        ldr r1, [pc, #12]   ; (1018 <hello+0x8>)
    100c:   f000 f80e   bl  102c <__hello_from_thumb>

00001010 <hello>:
    1010:   ea000002    b   1020 <__reset_handler_from_arm>
    1014:   00000000    andeq   r0, r0, r0
    1018:   00000001    andeq   r0, r0, r1
    101c:   00000000    andeq   r0, r0, r0

00001020 <__reset_handler_from_arm>:
    1020:   e59fc000    ldr r12, [pc]   ; 1028 <__reset_handler_from_arm+0x8>
    1024:   e12fff1c    bx  r12
    1028:   00001009    andeq   r1, r0, r9

0000102c <__hello_from_thumb>:
    102c:   4778        bx  pc
    102e:   e7fd        b.n 102c <__hello_from_thumb>
    1030:   eafffff6    b   1010 <hello>
    1034:   00000000    andeq   r0, r0, r0

否则

.arm

hello:
    b reset_handler

给出非功能代码

Disassembly of section .text:

00001000 <vector_table>:
    1000:   20001000    andcs   r1, r0, r0
    1004:   00001009    andeq   r1, r0, r9

00001008 <reset_handler>:
    1008:   4802        ldr r0, [pc, #8]    ; (1014 <hello+0x4>)
    100a:   4903        ldr r1, [pc, #12]   ; (1018 <hello+0x8>)
    100c:   f000 f800   bl  1010 <hello>

00001010 <hello>:
    1010:   ea000002    b   1020 <__reset_handler_from_arm>
    1014:   00000000    andeq   r0, r0, r0
    1018:   00000001    andeq   r0, r0, r1
    101c:   00000000    andeq   r0, r0, r0

00001020 <__reset_handler_from_arm>:
    1020:   e59fc000    ldr r12, [pc]   ; 1028 <__reset_handler_from_arm+0x8>
    1024:   e12fff1c    bx  r12
    1028:   00001009    andeq   r1, r0, r9
    102c:   00000000    andeq   r0, r0, r0

现在在 cortex-m 上,您没有 arm 模式,因此没有互通,但是对于要从 C 或其他高级调用的向量表和汇编语言中的任何其他函数,您需要具有函数声明。

我从未见过的对象声明,自从添加 arm 以来一直在使用 gnu 工具,并且一直在不需要它的情况下进行裸机引导芯片的东西......所以无法帮助你。

它们保持不变的原因是因为您将筹码挂起或将其强制放入您未定义的处理程序中,因此再次挂起筹码。处理器状态应该已更改以指示您所处的故障模式。

【讨论】:

  • 大声笑,你链接了我的答案,我通常从不关注问题中的链接,但回来后感到好奇,也许有一天我会再次阅读我之前的答案......也许我与我的观点相矛盾以前的自己和现在的自己……
  • 在您的回答中,您写道:“用于复位的向量表具有正确的地址 ORRed 和 1 0x1009”。 ARM 标准是否要求复位处理程序地址必须是 ORRed?我在哪里可以找到这方面的规范?
  • 它位于核心的 arm 架构参考手册中。是的,所有向量。
  • 暗示你应该在提问之前阅读文档而不是之后。您可能不知道的是,您应该坚持内核的 ARM TRM 技术参考手册,以及架构的架构参考手册 ARM ARM。他们的其他手册,例如我认为不正确或具有误导性的程序员/用户指南。 (正如其他 SO 问题所证明的那样)YMMV。
  • 偏移 0 处的条目用于初始化 SP_main 的值,请参见第 B1-186 页的 SP 寄存器。所有其他条目必须将位 [0] 设置为 1
猜你喜欢
  • 2012-04-22
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-21
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多