理解ARM矢量表程序集声明的语法



我正在自学一些ARM汇编,并且很难找到描述重置向量表声明的特定形式的资源。

CODE32
Vector_Table
reset_vector
b reset_handler
undefined_exception
b reset_handler
svc_exception
b reset_handler
etc...

我感到困惑的是;Vector_Table";语句,乍一看我以为这是一个标签,但在查看了文档后,我意识到标签以":&";。以前有人见过这种形式并能解释其语法吗?我在谷歌搜索中找不到任何有用的东西。

我天真的猜测是链接器将分配";Vector_Table";以及";reset_ vector";符号到相同地址,使得它们等于第一个分支指令。

这些都是标签:

Vector_Table
reset_vector
reset_handler
undefined_exception
svc_exception

汇编语言是特定于工具而非目标(ARM)的。一些汇编程序(用于ARM或一般)不使用冒号来标记标签,其他汇编程序则使用冒号,而其他汇编程序有不同的解决方案。请注意,这与英特尔和AT&T和x86。汇编程序的作者可以完全自由地发明他们想要的任何语言,只要它能产生可用的机器代码(好吧,它甚至不必这样做,但如果你不能用它编写程序,它会有多有用)。

ARM本身至少有三代组装商,如果不是更多的话,他们收购了在MCU和多个目标方面实力强大的Keil,你会发现很多公司和政府机构都在使用专业工具中的大人物之一(他们更喜欢花很多钱来获得一个可以拨打的电话号码,而不是一个无法轻松获得同等支持的免费工具)。我使用了ARM的至少三代工具,但现在已经无法访问,也根本没有使用过Keil工具,我怀疑他们的工具已经换成了ARM的味道。GNU的汇编程序在执行程序时被称为本地目标,因此GNU汇编程序通常被缩短为gas。Llvm没有用于目标的汇编程序,它有用于内部字节码语言的汇编程序。Llvm是gnu在免费工具选项方面的主要竞争对手,clang是他们的主要C编译器,不幸的是,也是他们的汇编程序,声称支持gnu对事物的解释,尽管正如Stack Overflow问题所示,这其中存在漏洞。

汇编语言的变化不限于指令,也不特定于指令

mov r0,r1

你会在那里发现差异,但有时你会发现语言中的大多数差异都是非指令区域,如标签、注释、数据声明(.byte、DB等)、宏等。ARM的经典工具你会在Stack Overflow中看到很多,没有GNU汇编程序那么多,但仍然足够多,没有使用很多冒号和句点标签:,在GNU汇编程序中看到的.section.text,.word等。历史上,许多用于各种目标的汇编语言都使用分号;征求意见。用于ARM的GNU汇编程序使用at符号@。冒号是一种在每行mov r0,r1中添加一条以上指令的方法;添加r3、r0、r3,这在许多其他汇编语言中是闻所未闻的。

将其称为向量表是误导性的,因为它是ARM处理器的这一代/风格的异常表,而不是向量。你在神奇的地址执行指令,你找不到向量(地址),这通常意味着你需要使用b指令(分支)或ldr-pc,标签在单个指令中从4字节表位置分支出来。异常表和处理程序记录在ARM体系结构参考手册中,如果没有参考,则应从armv5版本开始。如果你的问题与标签严格相关,那么你可能在阅读或编写汇编语言之前就已经掌握了这份文档。

标记为yes Vector_Table和reset_Vector将具有与写入的地址相同的地址。

使用GNU汇编程序(gas),语法看起来像这样:

.code 32
Vector_Table:
reset_vector:
b reset_handler
undefined_instruction:
b reset_handler

当链接时

Disassembly of section .text:
00000000 <Vector_Table>:
0:   ea000000    b   8 <reset_handler>
00000004 <undefined_instruction>:
4:   eaffffff    b   8 <reset_handler>
00000008 <reset_handler>:
8:   eafffffe    b   8 <reset_handler>

nm工具显示

00000008 t reset_handler
00000000 t reset_vector
00000004 t undefined_instruction
00000000 t Vector_Table

在这种情况下,Vector_Table和reset_Vector位于相同的地址,并且对于异常表的低/正常位置,该地址将是0x00000000。

如果这个其他汇编程序或带有这个汇编程序的工具链具有与GNU binutils相同的丰富工具,或者文件格式使得您可以使用binutils,那么您也可以检查这些工具产生了什么,并看到这些相同的东西。

虽然这个链接可能会在某个时候过时,但很容易在谷歌上搜索一个示例

https://www.keil.com/support/man/docs/armasm/armasm_dom1359731144051.htm

AREA     ARMex, CODE, READONLY
; Name this block of code ARMex
ENTRY                   ; Mark first instruction to execute
start
MOV      r0, #10        ; Set up parameters
MOV      r1, #3
ADD      r0, r0, r1     ; r0 = r0 + r1
stop
MOV      r0, #0x18      ; angel_SWIreason_ReportException
LDR      r1, =0x20026   ; ADP_Stopped_ApplicationExit
SVC      #0x123456      ; ARM semihosting (formerly SWI)
END                     ; Mark end of file

注释用分号,标签上没有冒号等。

注意,如果你必须来回移植,我倾向于使用;@在行的末尾标记注释,使其适用于两种语言。少了一件你必须移植的东西。YMMV。

有趣的是,同样的代码块可以追溯到ARM ADS(早于ADT和RealView工具的ARM Developers Suite),你也可以在谷歌上查看ARM ADS工具文档,包括语法。

它们实际上是Intel syntax(Keil,armasm)中的标签
AT&T syntax(GCC,LLVM等)中的标签以:结尾

而那些b指令只是每个中断/异常向量的空间持有者。

最新更新