在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,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>

            新聞中心

            EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM標(biāo)準(zhǔn)匯編與GNU匯編

            ARM標(biāo)準(zhǔn)匯編與GNU匯編

            作者: 時(shí)間:2016-11-21 來(lái)源:網(wǎng)絡(luò) 收藏
            前段時(shí)間看arm的匯編,發(fā)現(xiàn)很多有一個(gè)小點(diǎn),但是借來(lái)的書(shū)上的語(yǔ)法卻沒(méi)有,問(wèn)同學(xué)也不知道,于是在網(wǎng)上查了一番才發(fā)現(xiàn)我書(shū)上看到的是arm的標(biāo)準(zhǔn)匯編,而有小點(diǎn)的gnu的匯編,于是將收集到的資料整理后放到這里來(lái)。


            GNU匯編語(yǔ)言結(jié)構(gòu)
            主要包括三個(gè)常用的段:
            data 數(shù)據(jù)段 聲明帶有初始值的元素
            bss 數(shù)據(jù)段 聲明使用0或者null初始化的元素
            text 正文段 包含的指令, 每個(gè)匯編程序都必須包含此段

            使用.section 指令定義段, 如:
            .section .data
            .section .bss
            .section .text

            起始點(diǎn):
            gnu匯編器使用_start標(biāo)簽表示默認(rèn)的起始點(diǎn), 此外如果想要匯編內(nèi)部的標(biāo)簽?zāi)軌虮煌獠砍绦蛟L問(wèn),
            需要使用.globl 指令, 如:.globl _start


            使用通用庫(kù)函數(shù)時(shí)可以使用:
            ld -dynamic-linker /lib/ld-linux.so.2

            本文引用地址:http://www.biyoush.com/article/201611/319125.htm

            ################################################################################################
            # 四, 數(shù)據(jù)傳遞
            ################################################################################################
            1, 數(shù)據(jù)段
            使用.data聲明數(shù)據(jù)段, 這個(gè)段中聲明的任何數(shù)據(jù)元素都保留在內(nèi)存中并可以被匯編程序的指令讀取,
            此外還可以使用.rodata聲明只讀的數(shù)據(jù)段, 在聲明一個(gè)數(shù)據(jù)元素時(shí), 需要使用標(biāo)簽和命令:

            標(biāo)簽:用做引用數(shù)據(jù)元素所使用的標(biāo)記, 它和c語(yǔ)言的變量很相似, 它對(duì)于處理器是沒(méi)有意義的, 它只是用做匯編器試圖訪問(wèn)內(nèi)存位置時(shí)用做引用指針的一個(gè)位置。

            指令:指示匯編器為通過(guò)標(biāo)簽引用的數(shù)據(jù)元素保留特定數(shù)量的內(nèi)存, 聲明命令之后必須給出一個(gè)或多個(gè)默認(rèn)值。

            聲明指令:
            .ascii 文本字符串
            .asciz 以空字符結(jié)尾的字符串
            .byte 字節(jié)值
            .double 雙精度浮點(diǎn)值
            .float 單精度浮點(diǎn)值
            .int 32位整數(shù)
            .long 32位整數(shù), 和int相同
            .octa 16字節(jié)整數(shù)
            .quad 8字節(jié)整數(shù)
            .short 16位整數(shù)
            .single 單精度浮點(diǎn)數(shù)(和float相同)


            例子:
            output:
            .ascii "hello world."

            pi:
            .float 2.14

            聲明可以在一行中定義多個(gè)值, 如:
            ages:
            .int 20, 10, 30, 40


            定義靜態(tài)符號(hào):
            使用.equ命令把常量值定義為可以在文本段中使用的符號(hào),如:
            .section .data
            .equ LINUX_SYS_CALL, 0x80
            .section .text
            movl $LINUX_SYS_CALL, ?x



            2, bss段
            和data段不同, 無(wú)需聲明特定的數(shù)據(jù)類型, 只需聲明為所需目的保留的原始內(nèi)存部分即可。
            GNU匯編器使用以下兩個(gè)命令聲明內(nèi)存區(qū)域:
            .comm 聲明為未初始化的通用內(nèi)存區(qū)域
            .lcomm 聲明為未初始化的本地內(nèi)存區(qū)域

            兩種聲明很相似,但.lcomm是為不會(huì)從本地匯編代碼之外進(jìn)行訪問(wèn)的數(shù)據(jù)保留的, 格式為:
            .comm/.lcomm symbol, length

            例子:
            .section .bss
            .lcomm buffer, 1000
            該語(yǔ)句把1000字節(jié)的內(nèi)存地址賦予標(biāo)簽buffer, 在聲明本地通用內(nèi)存區(qū)域的程序之外的函數(shù)是不能訪問(wèn)他們的.(不能在.globl命令中使用他們)

            在bss段聲明的好處是, 數(shù)據(jù)不包含在可執(zhí)行文件中。在數(shù)據(jù)段中定義數(shù)據(jù)時(shí), 它必須被包含在可執(zhí)行程序中, 因?yàn)楸仨毷褂锰囟ㄖ党跏蓟?。因?yàn)椴皇褂脭?shù)據(jù)初始化bss段中聲明的數(shù)據(jù)區(qū)域,所以內(nèi)存區(qū)域被保留在運(yùn)行時(shí)使用, 并且不必包含在最終的程序中。

            3, 傳送數(shù)據(jù)
            move 指令:
            格式 movex 源操作數(shù), 目的操作數(shù)。 其中x為要傳送數(shù)據(jù)的長(zhǎng)度, 取值有:
            l 用于32位的長(zhǎng)字節(jié)
            w 用于16位的字
            b 用于8位的字節(jié)值

            立即數(shù)前面要加一個(gè)$符號(hào), 寄存器前面要加%符號(hào)。

            8個(gè)通用的寄存器是用于保存數(shù)據(jù)的最常用的寄存器, 這些寄存器的內(nèi)容可以傳遞
            給其他的任何可用的寄存器。 和通用寄存器不同, 專用寄存器(控制, 調(diào)試, 段)
            的內(nèi)容只能傳送給通用寄存器, 或者接收從通用寄存器傳過(guò)來(lái)的內(nèi)容。


            在對(duì)標(biāo)簽進(jìn)行引用時(shí):
            例:
            .section .data
            value:
            .int 100
            _start:
            movl value, ?x
            movl $value, ?x
            movl ?x, (?i)
            movl ?x, 4(?i)

            其中:movl value, ?x 只是把標(biāo)簽value當(dāng)前引用的內(nèi)存值傳遞給eax
            movl $value, ?x 把標(biāo)簽value當(dāng)前引用的內(nèi)存地址指針傳遞給eax
            movl ?x, (?i) 如果edi外面沒(méi)有括號(hào)那么這個(gè)指令只是把ebx中的
            值加載到edi中, 如果有了括號(hào)就表示把ebx中的內(nèi)容
            傳送給edi中包含的內(nèi)存位置。
            movl ?x, 4(?i) 表示把edi中的值放在edi指向的位置之后的4字節(jié)內(nèi)存位置中
            movl ?x, -4(?i) 表示把edi中的值放在edi指向的位置之前的4字節(jié)內(nèi)存位置中



            cmove 指令(條件轉(zhuǎn)移):
            cmovex 源操作數(shù), 目的操作數(shù). x的取值為:
            無(wú)符號(hào)數(shù):
            a/nbe 大于/不小于或者等于
            ae/nb 大于或者等于/不小于
            nc 無(wú)進(jìn)位
            b/nae 小于/不大于等于
            c 進(jìn)位
            be/na 小于或等于/不大于
            e/z 等于/零
            ne/nz 不等于/不為零
            p/pe 奇偶校驗(yàn)/偶校驗(yàn)
            np/po 非奇偶校驗(yàn)/奇校驗(yàn)

            有符號(hào)數(shù):
            ge/nl 大于或者等于/不小于
            l/nge 小于/不大于或者等于
            le/ng 小于或者等于/不大于
            o 溢出
            no 未溢出
            s 帶符號(hào)(負(fù))
            ns 無(wú)符號(hào)(非負(fù))

            交換數(shù)據(jù):
            xchg 在兩個(gè)寄存器之間或者寄存器和內(nèi)存間交換值
            如:
            xchg 操作數(shù), 操作數(shù), 要求兩個(gè)操作數(shù)必須長(zhǎng)度相同且不能同時(shí)都是內(nèi)存位置
            其中寄存器可以是32,16,8位的

            bswap 反轉(zhuǎn)一個(gè)32位寄存器的字節(jié)順序

            如: bswap ?x

            xadd 交換兩個(gè)值并把兩個(gè)值只和存儲(chǔ)在目標(biāo)操作數(shù)中

            如: xadd 源操作數(shù),目標(biāo)操作數(shù)
            其中源操作數(shù)必須是寄存器, 目標(biāo)操作數(shù)可以是內(nèi)存位置也可以是寄存器
            其中寄存器可以是32,16,8位的

            cmpxchg
            cmpxchg source, destination
            其中source必須是寄存器, destination可以是內(nèi)存或者寄存器, 用來(lái)比較
            兩者的值, 如果相等,就把源操作數(shù)的值加載到目標(biāo)操作數(shù)中, 如果不等就把
            目標(biāo)操作數(shù)加載到源操作數(shù)中,其中寄存器可以是32,16,8位的, 其中源操作
            數(shù)是EAX,AX或者AL寄存器中的值


            cmpxchg8b 同cmpxchg, 但是它處理8字節(jié)值, 同時(shí)它只有一個(gè)操作數(shù)
            cmpxchg8b destination
            其中destination引用一個(gè)內(nèi)存位置, 其中的8字節(jié)值會(huì)與EDX和EAX寄存器中
            包含的值(EDX高位寄存器, EAX低位寄存器)進(jìn)行比較, 如果目標(biāo)值和EDX:EAX
            對(duì)中的值相等, 就把EDX:EAX對(duì)中的64位值傳遞給內(nèi)存位置, 如果不匹配就把
            內(nèi)存地址中的值加載到EDX:EAX對(duì)中



            4, 堆棧
            ESP 寄存器保存了當(dāng)前堆棧的起始位置, 當(dāng)一個(gè)數(shù)據(jù)壓入棧時(shí), 它就會(huì)自動(dòng)遞減,
            反之其自動(dòng)遞增

            壓入堆棧操作:
            pushx source, x取值為:
            l 32位長(zhǎng)字
            w 16位字

            彈出堆棧操作:
            popx source
            其中source必須是16或32位寄存器或者內(nèi)存位置, 當(dāng)pop最后一個(gè)元素時(shí)ESP值應(yīng)該
            和以前的相等


            5,壓入和彈出所有寄存器
            pusha/popa 壓入或者彈出所有16位通用寄存器
            pushad/popad 壓入或者彈出所有32位通用寄存器
            pushf/popf 壓入或者彈出EFLAGS寄存器的低16位
            pushfd/popfd 壓入或者彈出EFLAGS寄存器的全部32位

            6,數(shù)據(jù)地址對(duì)齊
            gas 匯編器支持.align 命令, 它用于在特定的內(nèi)存邊界對(duì)準(zhǔn)定義的數(shù)據(jù)元素, 在數(shù)據(jù)段中.align命令緊貼在數(shù)據(jù)定義的前面

            比較:
            cmp operend1, operend2

            進(jìn)位標(biāo)志修改指令:
            CLC 清空進(jìn)位標(biāo)志(設(shè)置為0)
            CMC 對(duì)進(jìn)位標(biāo)志求反(把它改變?yōu)橄喾吹闹?
            STC 設(shè)置進(jìn)位標(biāo)志(設(shè)置為1)


            循環(huán):
            loop 循環(huán)直到ECX寄存器為0
            loope/loopz 循環(huán)直到ecx寄存器為0 或者沒(méi)有設(shè)置ZF標(biāo)志
            loopne/loopnz 循環(huán)直到ecx為0或者設(shè)置了ZF標(biāo)志

            指令格式為: loopxx address 注意循環(huán)指令只支持8位偏移地址

            另有一個(gè)比較篇的如下:

            ARM匯編和Gnu匯編的轉(zhuǎn)換

            將ARM ADS下的匯編碼移植到GCC for ARM編譯器時(shí),有如下規(guī)則:
            1, 注釋行以"@"或""代替";"

            2, GET或INCLUDE => .INCLUDE
            如:get option.a => .include "option.a"

            3, EQU => .equ
            TCLK2 EQU PB25 => .equ TCLK2, PB25
            SETA ==> .equ
            SETL ==> .equ
            BUSWIDTH SETA 16 => .equ BUSWIDTH, 16

            4, EXPORT => .global
            IMPORT => .extern
            GBLL => .global
            GBLA => .global

            5, DCD => .long

            6, IF :DEF: => .IFDEF
            ELSE => .ELSE
            ENDIF => .ENDIF
            :OR: => |
            :SHL: => <<

            7, END =>.end
            NOTE:在被include的頭文件中,如"option.a"中,不再需要.end,否則會(huì)導(dǎo)致主匯編程序結(jié)束。

            8, 符號(hào)定義加":"號(hào)
            Entry => Entry:
            AREA Word, CODE, READONLY ==> .text
            AREA Block, DATA, READWRITE ==> .data
            CODE32 ==> .arm
            CODE16 ==> .thumb

            9, MACRO ==> .macro
            MEND ==> .endm

            開(kāi)始看start.s中的代碼,又一句.balignl 16,0xdeadbeef,不知什么意思,網(wǎng)上搜了一下了解到這條


            命令的作用如下:



            .balign[wl] abs-expr, abs-expr, abs-expr



            增加位置計(jì)數(shù)器(在當(dāng)前子段)使它指向規(guī)定的存儲(chǔ)邊界。第一個(gè)表達(dá)式參數(shù)(結(jié)果必須是純粹的數(shù)字)是必需參數(shù):邊界基準(zhǔn),單位為字節(jié)。例如,‘.balign 8’向后移動(dòng)位置計(jì)數(shù)器直至計(jì)數(shù)器的值等于8的倍數(shù)。如果位置計(jì)數(shù)器已經(jīng)是8的倍數(shù),則無(wú)需移動(dòng)。第2個(gè)表達(dá)式參數(shù)(結(jié)果必須是純粹的數(shù)字)給出填充字節(jié)的值,用這個(gè)值填充位置計(jì)數(shù)器越過(guò)的地方。第2個(gè)參數(shù)(和逗點(diǎn))可以省略。如果省略它,填充字節(jié)的值通常是0。但在某些系統(tǒng)上,如果本段標(biāo)識(shí)為包含代碼,而填充值被省略,則使用no-op指令填充空白區(qū)。第3個(gè)參數(shù)的結(jié)果也必須是純粹的數(shù)字,這個(gè)參數(shù)是可選的。如果存在第3個(gè)參數(shù),它代表本對(duì)齊命令允許跳過(guò)字節(jié)數(shù)的最大值。如果完成這個(gè)對(duì)齊需要跳過(guò)的字節(jié)數(shù)比規(guī)定的最大值還多,則根本無(wú)法完成對(duì)齊。您可以在邊界基準(zhǔn)參數(shù)后簡(jiǎn)單地使用兩個(gè)逗號(hào),以省略填充值參數(shù)(第二參數(shù));如果您在想在適當(dāng)?shù)臅r(shí)候,對(duì)齊操作自動(dòng)使用no-op指令填充,本方法將非常奏效。.balignw和.balignl是.balign命令的變化形式。.balignw使用2個(gè)字節(jié)來(lái)填充空白區(qū)。.balignl使用4字節(jié)來(lái)填充。例如,.balignw 4,0x368d將地址對(duì)齊到4的倍數(shù),如果它跳過(guò)2個(gè)字節(jié),GAS將使用0x368d填充這2個(gè)字節(jié)(字節(jié)的確切存放位置視處理器的存儲(chǔ)方式而定)。

            如果它跳過(guò)1或3個(gè)字節(jié),則填充值不明確。

            GNU中的.word的另一種作用
            標(biāo)簽: word 2011-04-13 18:13


            不管是ARM的匯編還是GNU的匯編,都有DCD或者.word命令,它是用來(lái)開(kāi)辟一個(gè)字空間。

            如:標(biāo)識(shí)1 .word 標(biāo)識(shí)2 它表示將標(biāo)識(shí)2的數(shù)據(jù)存放在以標(biāo)識(shí)1的地址上去。這個(gè).word和DCD等指令,相當(dāng)于C語(yǔ)言的指針(如 char * p)。那么在匯編中用以上的代碼聲明的標(biāo)識(shí)1不需要在該文件中用extern的字段來(lái)表明是可以在外部引用的,它是內(nèi)存空間,可以在每個(gè)文件中使用這個(gè)標(biāo)識(shí)1.而ldr pc,內(nèi)存地址 它表示將內(nèi)存地址中的數(shù)據(jù)送入pc寄存器中去,而ldr pc,=內(nèi)存地址它表示將內(nèi)存地址放入pc寄存器中去。

            這些是在分析代碼時(shí)候遇到的不明白的地方,經(jīng)過(guò)查找資料的出來(lái)的。



            評(píng)論


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

            關(guān)閉