把握了底子的ARM汇编指令后,要写出简略的ARM汇编程序,还有必要要把握底子的ARM汇编伪操作(directive)。现在咱们来看一个简略的汇编程序,该程序调用子程序完结了加法操作。
1 ;文件名:TEST.S
2 ;功用:完结两个寄存器相加
3
4
5
6
7
8
9
10 ADD_SUB
11
12
13
第6、7即将传递给子程序的参数寄存在r0和r1中,第8行调用子程序。第11、12行是子程序的代码,完结了2个参数相加,并将成果放在r0后回来主程序。第6、8、10行的START、LOOP、ADD_SUB是标号,最常常用于跳转指令B和BL,因为汇编语法要求的原因,标号有必要顶格写(即:不能内行首有空格),不然编译器会报错。与之对应的是,汇编指令必定不能顶格写。
很明显分号(;)在汇编程序中是注释符号,相当于C言语的//号。除此之外,当然咱们留意到了第3、4、5、13行是咱们没学习过的符号,其实它们便是本文的要点——ARM汇编伪操作。首要我先来解说这几个伪操作,第3行界说了一个代码段,其段名为Example,特点为只读,然后表明第6——12行是程序代码(而不是程序数据)。第4行表明整个程序的进口点(即:程序运转的第一条指令)是第6行的MOV指令(注1)。第5行表明第6——12行的程序代码是ARM指令,而不是thumb指令。第13行表明源代码文件完毕,其背面的意义便是:假如程序员在第13行后还写有汇编指令,编译器也底子不会理睬这些代码,更不会去编译它们,当然这些代码也就不行能呈现在终究的可履行文件中。哈哈,所以请有必要记住,在END伪操作的后边再写代码,那是无用功,写了也白写。不要不以为然哟,依据经历,初学者总是会犯这样的过错。
特别阐明:第9行的意义是要让程序在运转完毕后,在第9行进行死循环,然后让整个程序定格在第9行。这一点或许你很困惑:在写应用程序时,程序完毕就完毕了,源代码底子不需要再去写个死循环。但你现在要弄清楚:你写应用程序时,有OS为你处理程序完毕后的若干工作。但是,你现在现已得不到OS服务。假如你不自己写第9行的代码,那么当你以为程序现已运转完毕(第8行履行完结)的时分,CPU不会聪明地停下来,它会持续勤勤恳恳地去取指第11行,持续运转,这不是你所期望的。其实这还不是最糟糕的,最糟糕的是,假如你的程序没有11-13行,那么CPU勤勤恳恳取出的指令其实是内存中的随机数,但CPU却会把它当作指令来履行,那么,你以为此刻会呈现什么情况呢?哈哈,只要天知道。
当然,伪操作远不止这几条,下面咱们再来介绍常常运用的若干伪操作。
GBLA:界说大局算术变量(精确说,应该是大局符号),例如:GBLA testval
SETA:对大局算术符号进行赋值,例如:testval
DCD:在编译时为整数分配字存储空间,例如:DCD 0x123456ab,这条伪操作将导致编译器在终究的二进制可履行文件中分配一个字的空间,并在该空间中寄存整数0x123456ab
DCB:在编译时为整数分配字节存储空间,例如:DCB ‘a’,这条伪操作将导致编译器在终究的二进制可履行文件中分配一个字节的空间,并在该空间中寄存字符a的ASCII码
IF,ELSE及ENDIF:相当于C言语的条件编译,例如:
testval
编译器编译该段代码的成果是:
mov r1, #9
mov r2, #9
WHILE及WEND:例如
testval SETA 1
testval SETA testval + 1
编译器编译该段代码的成果是:
mov r0, #2
mov r0, #3
mov r0, #4
MACRO、MEND及MEXIT:相当于C言语的宏替换,例如:
$label xmac $p1,$p2
; code1
$label.loop1
;code2
$label.loop2
;code3
; code4
;code5
;主程序
abc xmac subr1,de
编译器编译该段代码的成果是:
;code1
abc.loop1
;code2
abc.loop2
;code3
;code4
;code5
EQU:相当于C言语的宏界说,例如:testval EQU 4
EXPORT: 见“ATPCS与混合编程”一文
IMPORT:见“ATPCS与混合编程”一文
非常重要的一点是:有必要深刻理解汇编伪操作是给编译器供给某些必要的信息,以协助编译器正确完结程序的编译。当编译完结后,汇编伪操作就完结了它的历史使命,它不行能在终究的可履行程序的二进制代码中留下哪怕是一点点痕迹,当然也就不行能在程序运转时遭到CPU的“喜爱”。总归记住一句话,汇编伪操作是给编译器看的,而不是给CPU看的。这是汇编伪操作与汇编指令最大的差异。