GNU ARM汇编语法入门


GNU汇编器是GNU工具套件之一,其作用是把ARM汇编源代码转换成二进制对象文件。该汇编器的详细资料请参见GNU Assembler Manual,本文是该手册的摘要。

 

例子和模板文件

    Examples 文件夹和他的子文件夹包含很多汇编语言程序例子,你可以学习它们。

Examples 有一个子文件是templates在你开始写程序之前,强烈建议你使用那个文件夹提供的模板做为起点。特别的,template.s 文件应该在你所有的ARM程序中使用。在去除大部分该文件的注释后,内容如下:

          .text                  ; 以下为可执行代码

_start: .global _start       ; "_start" 是连接器所必须的

          .global main         ; "main" 是主程序

           b main               ; 跳转到主程序

main:                           ; "main" 程序入口

          ; 这里添加你自己的程序

          mov pc,lr            ; 返回

.end

 

调用汇编器

    你可以使用arm-elf-as工具来编译任何ARM汇编代码,该工具的调用方式如下:

    arm-elf-as -marm7tdmi --gdwarf2 -o filename.o filename.s

其中:

    Filename    需要编译的文件。

    -marm7tdmi 告诉GNU汇编器你的CPU内型是ARM7TDMI(ARMv4T 版本)

    --gdwarf2  让汇编器附带输出DEBUG信息

    GNU Assembler Reference的第一章,第二章以及8.4节列出了其他选项。对于大的工程来说,必须按模块划分成多个源文件。每个源文件(后缀为.s)的编译方法和上面所示的单个文件的方法一样。

    当你已经把源文件编译成二进制目标文件(后缀名.o),可以使用GNU链接器生成最终的可执行文件(后缀.elf),调用方式如下:

    arm-elf-ld -o filename.elf filename.o

    一次又一次的输入命令行将十分枯燥(尽管Unix Shell允许你使用方向键的向上键来显示上一次的命令),为了解决上述问题,你可以修改GNU提供的Makefile模板来达到你自己的目的(该模板的路径为:examples/templates/Makefile.template-asm)。一旦修改完该文件(并且重新命名该文件:Makefile),接下来所要做的就是输入命令:

    Make

 

汇编语言语法

    GNU汇编器支持多种架构的CPU而不仅仅是ARM。正因为如此,它的汇编语法和其他的ARM汇编器有细微的区别。GNU汇编器对于其支持的45CPU架构采用相同的汇编语法。汇编源文件由声明(每行一个)组成,声明格式如下,声明的每个部分都是可选的。

    label: instruction ; comment

label可以确定其所在位置的程序计数器(pc),然后你就可以使用它。例子:在分支或者loadstore指令中的目标。一个标号可以由任何有效的字符和冒号组成,所谓有效的字符包含以下字符:字母A-Z,a-z,数字0-9,符号"_",".","$"。但是要注意的是标号不能以数字开头(更多信息请看GNU Assembler Reference3.45.3)

Comment";"开头,不管是什么内容。除了在字符串中出现的分号,系统将忽律整行。C语言风格的注释(/*……*/)也同样被支持,同样的你也可以使用"@"来代替分号";"

Instruction区域是你的程序的主要组成:你可以使用任何你想用的ARM汇编语言指令。 同样包括所谓的伪指令或者汇编命令(用来告诉汇编器自己干某些特殊的事)。这些汇编命令将在下面做详细介绍。

 

汇编命令

    所有的汇编命令都是以"."开头。这些命令在GNU Assembler Reference的第七章做了更加详细的介绍。下面所列出的这些命令(按字母排列)是在程序中最常用的。

 

.align

    插入03个字节的0x00,,这样下一个位置将是4字节的整数倍。特别的,ARM微控制器总是按字(4字节)读取数据。下面的例子中,输出对象文件中将被插入8字节的内容,假设第一行代码的位置是4字节的整数倍。

    .byte 0x55         ; 插入1个字节 0x55

    .align              ; 顺次插入3个字节: 0x00 0x00 0x00

    .word 0xAA55EE11  ; 插入内容 0x11 0xEE 0x55 0xAA (小端模式)

     顺便说一下,前缀0x表示这个数是个16进制数,这个文档后面的表达式部分将对此做详细介绍。这个汇编命令还可以带选项,不过这儿不做介绍。如果你想使用它们,建议你用.balign命令代替。更多信息请看GNU Assembler Reference7.3

 

.ascii "string"

    在对象文件中按照指定的方法插入数字字符串,该字符串末尾没有NUL字符。该命令一次可以插入多个字符串,字符串之间用","分隔。下面的例子在对象文件中插入3个字节长的字符串。

    .ascii "JNZ"      ; 插入3个字节: 0x4A 0x4E 0x5A

 

.asciz "string"

    .ascii相似,只是生成的字符串以NUL(0x00)结尾。下面的例子在对象文件中插入4个字节长的字符串。

    .ascii "JNZ"      ; 插入4个字节: 0x4A 0x4E 0x5A 0x00

 

.byte expression

    在对象文件中插入一个字节,内容为expression的值。可以一次插入多个表达式,","分隔。下面的例子中共向对象文件中插入了5个字节内容。

    .byte 64, 'A'              ; 插入2字节 0x40 0x41

    .byte 0x42                  ; 插入字节 0x42

    .byte 0b1000011, 0104    ; 插入2字节 0x43 0x44

 

注意以0x0X开头的数字表示该数字是十六进制,0b0B开头的数字表示该数字是二进制,0开头的数字表示该数字是八进制。这个文档后面的表达式部分将对此做详细介绍,同时请看.hword .word 汇编命令部分。

 

.data

选择该命令以下的内容位于最终可执行文件的数据段。所有的可执行程序至少包含两个段,.我们称之为.text.data段。(缺一段)

技术上来讲,意味着只有可执行的代码才能出现在.text(尽管只读恒量也同样适合),可读写的数据才能出现在.data,不过对于GNU汇编器来说,这并不是强制的。GNU Assembler Reference的第四章将深入讨论这个主题。

 

.end

标记一个源代码文件的结尾。所有的在这个命令之后的内容将被汇编器忽略。这个命令完全可选,但强烈建议使用。

 

.equ symbol, expression

设置symbol的值为expression。这个汇编指令和.set,"="完全一样。下面的例子admas的值都是42:

    .equ adams, (5 * 8) + 2

    .set adams, 0x2A

    adams = 0b00101010

 

.extern symbol

声明symbol的定义在其他源文件中这个命令是可选的,因为汇编器对于任何未定义的标号都默认为是外部定义的。不过仍然建议使用。

  • 1
  • 2
  • 3
  • 下一页

相关内容