在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            GNU ARM 匯編指令

            作者: 時(shí)間:2016-11-21 來源:網(wǎng)絡(luò) 收藏
            第一部分 Linux下ARM匯編語法盡管在Linux下使用C或C++編寫程序很方便,但匯編源程序用于系統(tǒng)最基本的初始化,如初始化堆棧指針、設(shè)置頁表、操作 ARM的協(xié)處理器等。初始化完成后就可以跳轉(zhuǎn)到C代碼執(zhí)行。需要注意的是,GNU的匯編器遵循AT&T的匯編語法,可以從GNU的站點(diǎn)(www.gnu.org)上下載有關(guān)規(guī)范。

            一. Linux匯編行結(jié)構(gòu)
            任何匯編行都是如下結(jié)構(gòu):
            [:] [} @ comment
            [:] [} @ 注釋
            Linux ARM 匯編中,任何以冒號(hào)結(jié)尾的標(biāo)識(shí)符都被認(rèn)為是一個(gè)標(biāo)號(hào),而不一定非要在一行的開始。
            【例1】定義一個(gè)"add"的函數(shù),返回兩個(gè)參數(shù)的和。
            .section .text, “x”
            .global add @ give the symbol add external linkage
            add:
            ADD r0, r0, r1 @ add input arguments
            MOV pc, lr @ return from subroutine
            @ end of program

            二. Linux 匯編程序中的標(biāo)號(hào)
            標(biāo)號(hào)只能由a~z,A~Z,0~9,“.”,_等字符組成。當(dāng)標(biāo)號(hào)為0~9的數(shù)字時(shí)為局部標(biāo)號(hào),局部標(biāo)號(hào)可以重復(fù)出現(xiàn),使用方法如下:
            標(biāo)號(hào)f: 在引用的地方向前的標(biāo)號(hào)
            標(biāo)號(hào)b: 在引用的地方向后的標(biāo)號(hào)
            【例2】使用局部符號(hào)的例子,一段循環(huán)程序
            1:
            subs r0,r0,#1 @每次循環(huán)使r0=r0-1
            bne 1f @跳轉(zhuǎn)到1標(biāo)號(hào)去執(zhí)行
            局部標(biāo)號(hào)代表它所在的地址,因此也可以當(dāng)作變量或者函數(shù)來使用。

            三. Linux匯編程序中的分段
            (1).section偽操作
            用戶可以通過.section偽操作來自定義一個(gè)段,格式如下:
            .section section_name [, "flags"[, %type[,flag_specific_arguments]]]
            每一個(gè)段以段名為開始, 以下一個(gè)段名或者文件結(jié)尾為結(jié)束。這些段都有缺省的標(biāo)志(flags),連接器可以識(shí)別這些標(biāo)志。(與armasm中的AREA相同)。

            下面是ELF格式允許的段標(biāo)志
            <標(biāo)志> 含義
            a 允許段
            w 可寫段
            x 執(zhí)行段

            【例3】定義段
            .section .mysection @自定義數(shù)據(jù)段,段名為 “.mysection”
            .align 2
            strtemp:
            .ascii "Temp string n"


            (2)匯編系統(tǒng)預(yù)定義的段名
            .text @代碼段
            .data @初始化數(shù)據(jù)段
            .bss @未初始化數(shù)據(jù)段
            .sdata @
            .sbss @
            需要注意的是,源程序中.bss段應(yīng)該在.text之前。
            四. 定義入口點(diǎn)
            匯編程序的缺省入口是 start標(biāo)號(hào),用戶也可以在連接腳本文件中用ENTRY標(biāo)志指明其它入口點(diǎn)。
            【例4】定義入口點(diǎn)
            .section.data
            < initialized data here>
            .section .bss
            < uninitialized data here>
            .section .text
            .globl _start
            _start:


            五. Linux匯編程序中的宏定義
            格式如下:
            .macro 宏名 參數(shù)名列表 @偽指令.macro定義一個(gè)宏
            宏體
            .endm @.endm表示宏結(jié)束
            如果宏使用參數(shù),那么在宏體中使用該參數(shù)時(shí)添加前綴“”。宏定義時(shí)的參數(shù)還可以使用默認(rèn)值。
            可以使用.exitm偽指令來退出宏。
            【例5】宏定義
            .macro SHIFTLEFT a, b
            .if b < 0
            MOV a, a, ASR #-b
            .exitm
            .endif
            MOV a, a, LSL #b
            .endm

            六. Linux匯編程序中的常數(shù)
            (1)十進(jìn)制數(shù)以非0數(shù)字開頭,如:123和9876;
            (2)二進(jìn)制數(shù)以0b開頭,其中字母也可以為大寫;
            (3)八進(jìn)制數(shù)以0開始,如:0456,0123;
            (4)十六進(jìn)制數(shù)以0x開頭,如:0xabcd,0X123f;
            (5)字符串常量需要用引號(hào)括起來,中間也可以使用轉(zhuǎn)義字符,如: “You are welcome!n”;
            (6)當(dāng)前地址以“.”表示,在匯編程序中可以使用這個(gè)符號(hào)代表當(dāng)前指令的地址;
            (7)表達(dá)式:在匯編程序中的表達(dá)式可以使用常數(shù)或者數(shù)值, “-”表示取負(fù)數(shù), “~”表示取補(bǔ),“<>”表示不相等,其他的符號(hào)如:+、-、*、 /、%、<、<<、>、>>、|、&、^、!、==、>=、<=、&&、|| 跟C語言中的用法相似。

            七. Linux下ARM匯編的常用偽操作
            在前面已經(jīng)提到過了一些為操作,還有下面一些為操作:
            數(shù)據(jù)定義偽操作: .byte,.short,.long,.quad,.float,.string/.asciz/.ascii,重復(fù)定義偽操作.rept,賦值語句.equ/.set ;
            函數(shù)的定義 ;
            對(duì)齊方式偽操作 .align;
            源文件結(jié)束偽操作.end;
            .include偽操作;
            if偽操作;
            .global/ .globl 偽操作 ;
            .type偽操作 ;
            列表控制語句 ;
            區(qū)別于gas匯編的通用偽操作,下面是ARM特有的偽操作 :.reg ,.unreq ,.code ,.thumb ,.thumb_func ,.thumb_set, .ltorg ,.pool
            1. 數(shù)據(jù)定義偽操作
            (1) .byte:單字節(jié)定義,如:.byte 1,2,0b01,0x34,072,s ;
            (2) .short:定義雙字節(jié)數(shù)據(jù),如:.short 0x1234,60000 ;
            (3) .long:定義4字節(jié)數(shù)據(jù),如:.long 0x12345678,23876565
            (4) .quad:定義8字節(jié),如:.quad 0x1234567890abcd
            (5) .float:定義浮點(diǎn)數(shù),如:
            .float 0f-314159265358979323846264338327
            95028841971.693993751E-40 @ - pi
            (6) .string/.asciz/.ascii:定義多個(gè)字符串,如:
            .string "abcd", "efgh", "hello!"
            .asciz "qwer", "sun", "world!"
            .ascii "welcome"
            需要注意的是:.ascii偽操作定義的字符串需要自行添加結(jié)尾字符。
            (7) .rept:重復(fù)定義偽操作, 格式如下:
            .rept 重復(fù)次數(shù)
            數(shù)據(jù)定義
            .endr @結(jié)束重復(fù)定義
            例如:
            .rept 3
            .byte 0x23
            .endr
            (8) .equ/.set: 賦值語句, 格式如下:
            .equ(.set) 變量名,表達(dá)式
            例如:
            .equ abc 3 @讓abc=3

            2.函數(shù)的定義偽操作
            (1)函數(shù)的定義,格式如下:
            函數(shù)名:
            函數(shù)體
            返回語句
            一般的,函數(shù)如果需要在其他文件中調(diào)用, 需要用到.global偽操作將函數(shù)聲明為全局函數(shù)。為了不至于在其他程序在調(diào)用某個(gè)C函數(shù)時(shí)發(fā)生混亂,對(duì)寄存器的使用我們需要遵循APCS準(zhǔn)則。函數(shù)編譯器將處理為函數(shù)代碼為一段.global的匯編碼。
            (2)函數(shù)的編寫應(yīng)當(dāng)遵循如下規(guī)則:
            ? a1-a4寄存器(參數(shù)、結(jié)果或暫存寄存器,r0到r3 的同義字)以及浮點(diǎn)寄存器f0-f3(如果存在浮點(diǎn)協(xié)處理器)在函數(shù)中是不必保存的;
            ? 如果函數(shù)返回一個(gè)不大于一個(gè)字大小的值,則在函數(shù)結(jié)束時(shí)應(yīng)該把這個(gè)值送到 r0 中;
            ? 如果函數(shù)返回一個(gè)浮點(diǎn)數(shù),則在函數(shù)結(jié)束時(shí)把它放入浮點(diǎn)寄存器f0中;
            ?如果函數(shù)的過程改動(dòng)了sp(堆棧指針,r13)、fp(框架指針,r11)、sl(堆棧限制,r10)、lr(連接寄存器,r14)、v1-v8(變量寄存器,r4 到 r11)和 f4-f7,那么函數(shù)結(jié)束時(shí)這些寄存器應(yīng)當(dāng)被恢復(fù)為包含在進(jìn)入函數(shù)時(shí)它所持有的值。

            3. .align .end .include .incbin偽操作
            (1).align:用來指定數(shù)據(jù)的對(duì)齊方式,格式如下:
            .align [absexpr1, absexpr2]
            以某種對(duì)齊方式,在未使用的存儲(chǔ)區(qū)域填充值. 第一個(gè)值表示對(duì)齊方式,4, 8,16或 32. 第二個(gè)表達(dá)式值表示填充的值。
            (2).end:表明源文件的結(jié)束。
            (3).include:可以將指定的文件在使用.include 的地方展開,一般是頭文件,例如:
            .include “myarmasm.h”
            (4).incbin偽操作可以將原封不動(dòng)的一個(gè)二進(jìn)制文件編譯到當(dāng)前文件中,使用方法如下:
            .incbin "file"[,skip[,count]]
            skip表明是從文件開始跳過skip個(gè)字節(jié)開始讀取文件,count是讀取的字?jǐn)?shù).

            4. .if偽操作
            根據(jù)一個(gè)表達(dá)式的值來決定是否要編譯下面的代碼, 用.endif偽操作來表示條件判斷的結(jié)束, 中間可以使用.else來決定.if的條件不滿足的情況下應(yīng)該編譯哪一部分代碼。
            .if有多個(gè)變種:
            .ifdef symbol @判斷symbol是否定義
            .ifc string1,string2 @字符串string1和string2是否相等,字符串可以用單引號(hào)括起來
            .ifeq expression @判斷expression的值是否為0
            .ifeqs string1,string2 @判斷string1和string2是否相等,字符 串必須用雙引號(hào)括起來
            .ifge expression @判斷expression的值是否大于等于0
            .ifgt absolute expression @判斷expression的值是否大于0
            .ifle expression @判斷expression的值是否小于等于0
            .iflt absolute expression @判斷expression的值是否小于0
            .ifnc string1,string2 @判斷string1和string2是否不相等, 其用法跟.ifc恰好相反。
            .ifndef symbol, .ifnotdef symbol @判斷是否沒有定義symbol, 跟.ifdef恰好相反
            .ifne expression @如果expression的值不是0, 那么編譯器將編譯下面的代碼
            .ifnes string1,string2 @如果字符串string1和string2不相 等, 那么編譯器將編譯下面的代碼.

            5. .global .type .title .list
            (1).global/ .globl :用來定義一個(gè)全局的符號(hào),格式如下:
            .global symbol 或者 .globl symbol
            (2).type:用來指定一個(gè)符號(hào)的類型是函數(shù)類型或者是對(duì)象類型, 對(duì)象類型一般是數(shù)據(jù), 格式如下:
            .type 符號(hào), 類型描述
            【例6】
            .globl a
            .data
            .align 4
            .type a, @object
            .size a, 4
            a:
            .long 10
            【例7】
            .section .text
            .type asmfunc, @function
            .globl asmfunc
            asmfunc:

            mov pc, lr

            (3)列表控制語句:
            .title:用來指定匯編列表的標(biāo)題,例如:
            .title “my program”
            .list:用來輸出列表文件.

            6. ARM特有的偽操作
            (1) .reg: 用來給寄存器賦予別名,格式如下:
            別名 .req 寄存器名
            (2) .unreq: 用來取消一個(gè)寄存器的別名,格式如下:
                   .unreq 寄存器別名
              注意被取消的別名必須事先定義過,否則編譯器就會(huì)報(bào)錯(cuò),這個(gè)偽操作也可以用來取消系統(tǒng)預(yù)制的別名, 例如r0, 但如果沒有必要的話不推薦那樣做。
            (3) .code偽操作用來選擇ARM或者Thumb指令集,格式如下:
                       .code 表達(dá)式
              如果表達(dá)式的值為16則表明下面的指令為Thumb指令,如果表達(dá)式的值為32則表明下面的指令為ARM指令.
            (4) .thumb偽操作等同于.code 16, 表明使用Thumb指令, 類似的.arm等同于.code 32
            (5) .force_thumb偽操作用來強(qiáng)制目標(biāo)處理器選擇thumb的指令集而不管處理器是否支持
            (6) .thumb_func偽操作用來指明一個(gè)函數(shù)是thumb指令集的函數(shù)
            (7) .thumb_set偽操作的作用類似于.set, 可以用來給一個(gè)標(biāo)志起一個(gè)別名, 比.set功能增加的一點(diǎn)是可以把一個(gè)標(biāo)志標(biāo)記為thumb函數(shù)的入口, 這點(diǎn)功能等同于.thumb_func
            (8) .ltorg用于聲明一個(gè)數(shù)據(jù)緩沖池(literal pool)的開始,它可以分配很大的空間。
            (9) .pool的作用等同.ltorg
            (9).space {,}
            分配number_of_bytes字節(jié)的數(shù)據(jù)空間,并填充其值為fill_byte,若未指定該值,缺省填充0。(與armasm中的SPACE功能相同)
            (10).word {,} …
            插入一個(gè)32-bit的數(shù)據(jù)隊(duì)列。(與armasm中的DCD功能相同)
            可以使用.word把標(biāo)識(shí)符作為常量使用
            例如:
            Start:
            valueOfStart:
            .word Start
            這樣程序的開頭Start便被存入了內(nèi)存變量valueOfStart中。
            (11).hword {,} …
            插入一個(gè)16-bit的數(shù)據(jù)隊(duì)列。(與armasm中的DCW相同)

            八. GNU ARM匯編特殊字符和語法
            代碼行中的注釋符號(hào): ‘@’
            整行注釋符號(hào): ‘#’
            語句分離符號(hào): ‘;’
            直接操作數(shù)前綴: ‘#’ 或 ‘$’

            第二部分 GNU的編譯器和調(diào)試工具

            一. 編譯工具
            1.編輯工具介紹
            GNU 提供的編譯工具包括匯編器as、C編譯器gcc、C++編譯器g++、連接器ld和二進(jìn)制轉(zhuǎn)換工具objcopy。基于ARM平臺(tái)的工具分別為arm- linux-as、arm-linux-gcc、arm-linux-g++、arm-linux-ld和arm-linux- objcopy。GNU的編譯器功能非常強(qiáng)大,共有上百個(gè)操作選項(xiàng),這也是這類工具讓初學(xué)者頭痛的原因。不過,實(shí)際開發(fā)中只需要用到有限的幾個(gè),大部分可以采用缺省選項(xiàng)。GNU工具的開發(fā)流程如下:編寫C、C++語言或匯編源程序,用gcc或g++生成目標(biāo)文件,編寫連接腳本文件,用連接器生成最終目標(biāo)文件(elf格式),用二進(jìn)制轉(zhuǎn)換工具生成可下載的二進(jìn)制代碼。
            (1)編寫C、C++語言或匯編源程序
            通常匯編源程序用于系統(tǒng)最基本的初始化,如初始化堆棧指針、設(shè)置頁表、操作ARM的協(xié)處理器等。初始化完成后就可以跳轉(zhuǎn)到C代碼執(zhí)行。需要注意的是,GNU的匯編器遵循AT&T的匯編語法,讀者可以從GNU的站點(diǎn)(www.gnu.org)上下載有關(guān)規(guī)范。匯編程序的缺省入口是 start標(biāo)號(hào),用戶也可以在連接腳本文件中用ENTRY標(biāo)志指明其它入口點(diǎn)(見下文關(guān)于連接腳本的說明)。

            (2)用gcc或g++生成目標(biāo)文件
            如果應(yīng)用程序包括多個(gè)文件,就需要進(jìn)行分別編譯,最后用連接器連接起來。如筆者的引導(dǎo)程序包括3個(gè)文件:init.s(匯編代碼、初始化硬件)xmrecever.c(通信模塊,采用Xmode協(xié)議)和flash.c(Flash擦寫模塊)。
            分別用如下命令生成目標(biāo)文件: arm-linux-gcc-c-O2-oinit.oinit.s arm-linux-gcc-c-O2-oxmrecever.oxmrecever.c arm-linux-gcc-c-O2-oflash.oflash.c 其中-c命令表示只生成目標(biāo)代碼,不進(jìn)行連接;-o命令指明目標(biāo)文件的名稱;-O2表示采用二級(jí)優(yōu)化,采用優(yōu)化后可使生成的代碼更短,運(yùn)行速度更快。如果項(xiàng)目包含很多文件,則需要編寫makefile文件。關(guān)于makefile的內(nèi)容,請感興趣的讀者參考相關(guān)資料。
            (3)編寫連接腳本文件
            gcc 等編譯器內(nèi)置有缺省的連接腳本。如果采用缺省腳本,則生成的目標(biāo)代碼需要操作系統(tǒng)才能加載運(yùn)行。為了能在嵌入式系統(tǒng)上直接運(yùn)行,需要編寫自己的連接腳本文件。編寫連接腳本,首先要對(duì)目標(biāo)文件的格式有一定了解。GNU編譯器生成的目標(biāo)文件缺省為elf格式。elf文件由若干段(section)組成,如不特殊指明,由C源程序生成的目標(biāo)代碼中包含如下段:.text(正文段)包含程序的指令代碼;.data(數(shù)據(jù)段)包含固定的數(shù)據(jù),如常量、字符串;.bss(未初始化數(shù)據(jù)段)包含未初始化的變量、數(shù)組等。C++源程序生成的目標(biāo)代碼中還包括.fini(析構(gòu)函數(shù)代碼)和. init(構(gòu)造函數(shù)代碼)等。連接器的任務(wù)就是將多個(gè)目標(biāo)文件的.text、.data和.bss等段連接在一起,而連接腳本文件是告訴連接器從什么地址開始放置這些段。例如連接文件link.lds為:
            ENTRY(begin)
            SECTION
            {
            .=0x30000000;
            .text:{*(.text)}
            .data:{*(.data)}
            .bss:{*(.bss)}
            }
            其中,ENTRY(begin)指明程序的入口點(diǎn)為begin標(biāo)號(hào);.=0x00300000指明目標(biāo)代碼的起始地址為0x30000000,這一段地址為 MX1的片內(nèi)RAM;.text:{*(.text)}表示從0x30000000開始放置所有目標(biāo)文件的代碼段,隨后的.data:{* (.data)}表示數(shù)據(jù)段從代碼段的末尾開始,再后是.bss段。
            (4)用連接器生成最終目標(biāo)文件
            有了連接腳本文件,如下命令可生成最終的目標(biāo)文件:
            arm-linux-ld –no stadlib –o bootstrap.elf -Tlink.lds init.o xmrecever.o flash.o
            其中,ostadlib表示不連接系統(tǒng)的運(yùn)行庫,而是直接從begin入口;-o指明目標(biāo)文件的名稱;-T指明采用的連接腳本文件(也可以使用-Ttext address,address表示執(zhí)行區(qū)地址);最后是需要連接的目標(biāo)文件列表。
            (5)生成二進(jìn)制代碼
            連接生成的elf文件還不能直接下載執(zhí)行,通過objcopy工具可生成最終的二進(jìn)制文件:
            arm-linux-objcopy –O binary bootstrap.elf bootstrap.bin
            其中-O binary指定生成為二進(jìn)制格式文件。Objcopy還可以生成S格式的文件,只需將參數(shù)換成-O srec。還可以使用-S選項(xiàng),移除所有的符號(hào)信息及重定位信息。如果想將生成的目標(biāo)代碼反匯編,還可以用objdump工具:
            arm-linux-objdump -D bootstrap.elf
            至此,所生成的目標(biāo)文件就可以直接寫入Flash中運(yùn)行了。

            2.Makefile實(shí)例
            example: head.s main.c
            arm-linux-gcc -c -o head.o head.s
            arm-linux-gcc -c -o main.o main.c
            arm-linux-ld -Tlink.lds head.o ain.o -o example.elf
            arm-linux-objcopy -O binary -S example_tmp.o example
            arm-linux-objdump -D -b binary -m arm example >ttt.s

            二. 調(diào)試工具
            Linux 下的GNU調(diào)試工具主要是gdb、gdbserver和kgdb。其中g(shù)db和gdbserver可完成對(duì)目標(biāo)板上Linux下應(yīng)用程序的遠(yuǎn)程調(diào)試。 gdbserver是一個(gè)很小的應(yīng)用程序,運(yùn)行于目標(biāo)板上,可監(jiān)控被調(diào)試進(jìn)程的運(yùn)行,并通過串口與上位機(jī)上的gdb通信。開發(fā)者可以通過上位機(jī)的gdb輸入命令,控制目標(biāo)板上進(jìn)程的運(yùn)行,查看內(nèi)存和寄存器的內(nèi)容。gdb5.1.1以后的版本加入了對(duì)ARM處理器的支持,在初始化時(shí)加入- target==arm參數(shù)可直接生成基于ARM平臺(tái)的gdbserver。gdb工具可以從ftp: //ftp.gnu.org/pub/gnu/gdb/上下載。
            對(duì)于Linux內(nèi)核的調(diào)試,可以采用kgdb工具,同樣需要通過串口與上位機(jī)上的gdb通信,對(duì)目標(biāo)板的Linux內(nèi)核進(jìn)行調(diào)試??梢詮膆ttp://oss.sgi.com/projects/kgdb/上了解具體的使用方法。


            參考資料:
            1. Richard Blum,Professional Assembly Language
            2. GNU ARM 匯編快速入門,http://blog.chinaunix.net/u/31996/showart.php?id=326146
            3. ARM GNU 匯編偽指令簡介,http://www.cppblog.com/jb8164/archive/2008/01/22/41661.aspx
            4. GNU匯編使用經(jīng)驗(yàn),http://blog.chinaunix.net/u1/37614/showart_390095.html
            5. GNU的編譯器和開發(fā)工具,http://blog.ccidnet.com/blog-htm-do-showone-uid-34335-itemid-81387-type-blog.html
            6. 用GNU工具開發(fā)基于ARM的嵌入式系統(tǒng),http://blog.163.com/liren0@126/blog/static/32897598200821211144696/
            7. objcopy命令介紹,http://blog.csdn.net/junhua198310/archive/2007/06/27/1669545.aspx


            關(guān)鍵詞: GNUARM匯編指

            評(píng)論


            技術(shù)專區(qū)

            關(guān)閉