您的位置 首页 产品

ARM规范汇编与GNU汇编

前段时间看arm的汇编,发现很多有一个小点,但是借来的书上的语法却没有,问同学也不知道,于是在网上查了一番才发现我书上看到的是arm的标…

前段时间看arm的汇编,发现许多有一个小点,可是借来的书上的语法却没有,问同学也不知道,所以在网上查了一番才发现我书上看到的是arm的规范汇编,而有小点的gnu的汇编,所以将收集到的材料收拾后放到这里来。


GNU汇编言语结构
首要包括三个常用的段:
data 数据段 声明带有初始值的元素
bss 数据段 声明运用0或许null初始化的元素
text 正文段 包括的指令, 每个汇编程序都有必要包括此段

运用.section 指令界说段, 如:
.section .data
.section .bss
.section .text

开端点:
gnu汇编器运用_start标签标明默许的开端点, 此外假如想要汇编内部的标签能够被外部程序拜访,
需求运用.globl 指令, 如:.globl _start


运用通用库函数时能够运用:
ld -dynamic-linker /lib/ld-linux.so.2

################################################################################################
# 四, 数据传递
################################################################################################
1, 数据段
运用.data声明数据段, 这个段中声明的任何数据元素都保存在内存中并能够被汇编程序的指令读取,
此外还能够运用.rodata声明只读的数据段, 在声明一个数据元素时, 需求运用标签和指令:

标签:用做引证数据元素所运用的符号, 它和c言语的变量很类似, 它关于处理器是没有意义的, 它仅仅用做汇编器企图拜访内存方位时用做引证指针的一个方位。

指令:指示汇编器为通过标签引证的数据元素保存特定数量的内存, 声明指令之后有必要给出一个或多个默许值。

声明指令:
.ascii 文本字符串
.asciz 以空字符完毕的字符串
.byte 字节值
.double 双精度浮点值
.float 单精度浮点值
.int 32位整数
.long 32位整数, 和int相同
.octa 16字节整数
.quad 8字节整数
.short 16位整数
.single 单精度浮点数(和float相同)


比如:
output:
.ascii “hello world.”

pi:
.float 2.14

声明能够在一行中界说多个值, 如:
ages:
.int 20, 10, 30, 40


界说静态符号:
运用.equ指令把常量值界说为能够在文本段中运用的符号,如:
.section .data
.equ LINUX_SYS_CALL, 0x80
.section .text
movl $LINUX_SYS_CALL, �x



2, bss段
和data段不同, 无需声明特定的数据类型, 只需声明为所需意图保存的原始内存部分即可。
GNU汇编器运用以下两个指令声明内存区域:
.comm 声明为未初始化的通用内存区域
.lcomm 声明为未初始化的本地内存区域

两种声明很类似,但.lcomm是为不会从本地汇编代码之外进行拜访的数据保存的, 格局为:
.comm/.lcomm symbol, length

比如:
.section .bss
.lcomm buffer, 1000
该句子把1000字节的内存地址赋予标签buffer, 在声明本地通用内存区域的程序之外的函数是不能拜访他们的.(不能在.globl指令中运用他们)

在bss段声明的优点是, 数据不包括在可执行文件中。在数据段中界说数据时, 它有必要被包括在可执行程序中, 由于有必要运用特定值初始化它。由于不运用数据初始化bss段中声明的数据区域,所以内存区域被保存在运行时运用, 而且不用包括在终究的程序中。

3, 传送数据
move 指令:
格局 movex 源操作数, 意图操作数。 其间x为要传送数据的长度, 取值有:
l 用于32位的长字节
w 用于16位的字
b 用于8位的字节值

当即数前面要加一个$符号, 寄存器前面要加%符号。

8个通用的寄存器是用于保存数据的最常用的寄存器, 这些寄存器的内容能够传递
给其他的任何可用的寄存器。 和通用寄存器不同, 专用寄存器(操控, 调试, 段)
的内容只能传送给通用寄存器, 或许接纳从通用寄存器传过来的内容。


在对标签进行引证时:
例:
.section .data
value:
.int 100
_start:
movl value, �x
movl $value, �x
movl �x, (�i)
movl �x, 4(�i)

其间:movl value, �x 仅仅把标签value当时引证的内存值传递给eax
movl $value, �x 把标签value当时引证的内存地址指针传递给eax
movl �x, (�i) 假如edi外面没有括号那么这个指令仅仅把ebx中的
值加载到edi中, 假如有了括号就标明把ebx中的内容
传送给edi中包括的内存方位。
movl �x, 4(�i) 标明把edi中的值放在edi指向的方位之后的4字节内存方位中
movl �x, -4(�i) 标明把edi中的值放在edi指向的方位之前的4字节内存方位中



cmove 指令(条件搬运):
cmovex 源操作数, 意图操作数. x的取值为:
无符号数:
a/nbe 大于/不小于或许等于
ae/nb 大于或许等于/不小于
nc 无进位
b/nae 小于/不大于等于
c 进位
be/na 小于或等于/不大于
e/z 等于/零
ne/nz 不等于/不为零
p/pe 奇偶校验/偶校验
np/po 非奇偶校验/奇校验

有符号数:
ge/nl 大于或许等于/不小于
l/nge 小于/不大于或许等于
le/ng 小于或许等于/不大于
o 溢出
no 未溢出
s 带符号(负)
ns 无符号(非负)

交流数据:
xchg 在两个寄存器之间或许寄存器和内存间交流值
如:
xchg 操作数, 操作数, 要求两个操作数有必要长度相同且不能一起都是内存方位
其间寄存器能够是32,16,8位的

bswap 回转一个32位寄存器的字节次序

如: bswap �x

xadd 交流两个值并把两个值只和存储在方针操作数中

如: xadd 源操作数,方针操作数
其间源操作数有必要是寄存器, 方针操作数能够是内存方位也能够是寄存器
其间寄存器能够是32,16,8位的

cmpxchg
cmpxchg source, destination
其间source有必要是寄存器, destination能够是内存或许寄存器, 用来比较
两者的值, 假如持平,就把源操作数的值加载到方针操作数中, 假如不等就把
方针操作数加载到源操作数中,其间寄存器能够是32,16,8位的, 其间源操作
数是EAX,AX或许AL寄存器中的值


cmpxchg8b 同cmpxchg, 可是它处理8字节值, 一起它只要一个操作数
cmpxchg8b destination
其间destination引证一个内存方位, 其间的8字节值会与EDX和EAX寄存器中
包括的值(EDX高位寄存器, EAX低位寄存器)进行比较, 假如方针值和EDX:EAX
对中的值持平, 就把EDX:EAX对中的64位值传递给内存方位, 假如不匹配就把
内存地址中的值加载到EDX:EAX对中



4, 仓库
ESP 寄存器保存了当时仓库的开端方位, 当一个数据压入栈时, 它就会主动递减,
反之其主动递加

压入仓库操作:
pushx source, x取值为:
l 32位长字
w 16位字

弹出仓库操作:
popx source
其间source有必要是16或32位寄存器或许内存方位, 当pop最终一个元素时ESP值应该
和曾经的持平


5,压入和弹出一切寄存器
pusha/popa 压入或许弹出一切16位通用寄存器
pushad/popad 压入或许弹出一切32位通用寄存器
pushf/popf 压入或许弹出EFLAGS寄存器的低16位
pushfd/popfd 压入或许弹出EFLAGS寄存器的悉数32位

6,数据地址对齐
gas 汇编器支撑.align 指令, 它用于在特定的内存鸿沟对准界说的数据元素, 在数据段中.align指令紧贴在数据界说的前面

比较:
cmp operend1, operend2

进位标志修正指令:
CLC 清空进位标志(设置为0)
CMC 对进位标志求反(把它改变为相反的值)
STC 设置进位标志(设置为1)


循环:
loop 循环直到ECX寄存器为0
loope/loopz 循环直到ecx寄存器为0 或许没有设置ZF标志
loopne/loopnz 循环直到ecx为0或许设置了ZF标志

指令格局为: loopxx address 留意循环指令只支撑8位偏移地址

还有一个比较篇的如下:

ARM汇编和Gnu汇编的转化

将ARM ADS下的汇编码移植到GCC for ARM编译器时,有如下规矩:
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,否则会导致主汇编程序完毕。

8, 符号界说加”:”号
Entry => Entry:
AREA Word, CODE, READONLY ==> .text
AREA Block, DATA, READWRITE ==> .data
CODE32 ==> .arm
CODE16 ==> .thumb

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

开端看start.s中的代码,又一句.balignl 16,0xdeadbeef,不知什么意思,网上搜了一下了解到这条

指令的效果如下:



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



添加方位计数器(在当时子段)使它指向规则的存储鸿沟。第一个表达式参数(成果有必要是朴实的数字)是必需参数:鸿沟基准,单位为字节。例如,‘.balign 8’向后移动方位计数器直至计数器的值等于8的倍数。假如方位计数器已经是8的倍数,则无需移动。第2个表达式参数(成果有必要是朴实的数字)给出填充字节的值,用这个值填充方位计数器越过的当地。第2个参数(和逗点)能够省掉。假如省掉它,填充字节的值通常是0。但在某些体系上,假如本段标识为包括代码,而填充值被省掉,则运用no-op指令填充空白区。第3个参数的成果也有必要是朴实的数字,这个参数是可选的。假如存在第3个参数,它代表本对齐指令答应越过字节数的最大值。假如完结这个对齐需求越过的字节数比规则的最大值还多,则底子无法完结对齐。您能够在鸿沟基准参数后简略地运用两个逗号,以省掉填充值参数(第二参数);假如您在想在恰当的时分,对齐操作主动运用no-op指令填充,本办法将十分见效。.balignw和.balignl是.balign指令的改变方法。.balignw运用2个字节来填充空白区。.balignl运用4字节来填充。例如,.balignw 4,0x368d将地址对齐到4的倍数,假如它越过2个字节,GAS将运用0x368d填充这2个字节(字节的切当寄存方位视处理器的存储方法而定)。

假如它越过1或3个字节,则填充值不明确。

GNU中的.word的另一种效果
标签: word 2011-04-13 18:13

不管是ARM的汇编仍是GNU的汇编,都有DCD或许.word指令,它是用来拓荒一个字空间。

如:标识1 .word 标识2 它标明将标识2的数据寄存在以标识1的地址上去。这个.word和DCD等指令,相当于C言语的指针(如 char * p)。那么在汇编顶用以上的代码声明的标识1不需求在该文件顶用extern的字段来标明是能够在外部引证的,它是内存空间,能够在每个文件中运用这个标识1.而ldr pc,内存地址 它标明将内存地址中的数据送入pc寄存器中去,而ldr pc,=内存地址它标明将内存地址放入pc寄存器中去。

这些是在剖析代码时分遇到的不明白的当地,通过查找材料的出来的。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/chanpin/262663.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部