Linux 汇编语言(GNU GAS汇编)区别
2014-01-13 08:31
246 查看
二、Linux 汇编语法格式
绝大多数 Linux 程序员以前只接触过DOS/Windows 下的汇编语言,这些汇编代码都是 Intel 风格的。但在 Unix 和 Linux 系统中,更多采用的还是 AT&T 格式,两者在语法格式上有着很大的不同:
在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。例如:
在 AT&T 汇编格式中,用 '$' 前缀表示一个立即操作数;而在 Intel 汇编格式中,立即数的表示不用带任何前缀。例如:
AT&T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。在 Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边。例如:
在 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀'b'、'w'、'l'分别表示操作数为字节(byte,8 比特)、字(word,16 比特)和长字(long,32比特);而在 Intel 汇编格式中,操作数的字长是用 "byte ptr" 和 "word ptr" 等前缀来表示的。例如:
在 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上'*'作为前缀,而在 Intel 格式中则不需要。
远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为 "ljump" 和 "lcall",而在 Intel 汇编格式中则为 "jmp far" 和 "call far",即:
与之相应的远程返回指令则为:
在 AT&T 汇编格式中,内存操作数的寻址方式是
而在 Intel 汇编格式中,内存操作数的寻址方式为:
由于 Linux 工作在保护模式下,用的是 32 位线性地址,所以在计算地址时不用考虑段基址和偏移量,而是采用如下的地址计算方法:
下面是一些内存操作数的例子:
GNU ARM汇编伪操作(Directives) 命令集
1.符号定义伪操作
操作符 语法格式 说明
.equ .equ symbol,expr 将symbol定义为expr
.set .set symbol,expr 和equ相同(.set=.equ)
.equiv .equiv symbol 将symbol定义为expr,若symbol已定义则出错
.global .global symbol 将symbol定义为全局标号
.globl .globl symbol 和.global相同(.globl=.global)
.extern .extern symbol 声明symbol为一个外部变量
2.数据定义伪操作
.byte .byte expr {,expr}…
分配一段字节内存单元,并用expr初始化字节内存单元(8bit)
.hword .bword expr {,expr}…
分配一段半字内存单元,并用expr初始化半字内存单元 (16bit)
.short .short expr {,expr}…
同.hword(16bit)
.word .word expr {,expr}…
分配一段字内存单元,并用expr初始化字内存单元(32bit)
.int .int expr {,expr}…
同.word(32bit)
.long .long expr {,expr}…
同.word(32bit)
.ascii .ascii expr{,expr}… 分配一段字符串内存单元,并用expr初始化字符串内存单元(非零结束符)
.asciz .asciz expr{,expr}… 分配一段字符串内存单元,并用expr初始化字符串内存单元(零结束符)
.string .string expr {,expr}…
同.asciz(零结束符)
.quad .qua expr {,expr}…
分配一段双字内存单元,并用expr初始化双字内存单元
.octa .octa expr{,expr}…
分配一段四字内存单元,并用expr初始化四字内存单元
.float .float expr{,expr}…
分配一段字内存单元,并用32位IEEE单精度浮点数expr初始化内存单元
.single .single expr{,expr}… 同.float
.double .double expr{,expr}… 分配一段双字内存单元,并用64位IEEE双精度浮点数expr初始化内存单元
.fill .fill repeat{,size}{,value} 用size个字节value填充repeat次(size默认为1,value默认为0)
.zero .zreo size
用0填充size个字节的内存单元
.space .space size{,value}
用value填充size个字节的内存单元(value默认为0)
.skip .space size{,value}
同.space
.ltorg .ltorg
声明一个数据缓冲池(literal pool)
3.汇编与反汇编代码控制伪操作
.arm .arm
定义一下代码使用ARM指令集编译
.code 32 .code 32
作用同.arm
.thumb .thumb
定义一下代码使用Thumb指令集编译
.code 16 .code 16
作用同.thumb
.section .section expr
定义域中包含的段。expr可以使.text,.data.,.bss
.text .text {subsection}
将定义符开始的代码编译到代码段或代码子段(subsection)
.data .data {subsection}
将定义符开始的代码编译到数据段或数据子段(subsection)
.bss .bss {subsection}
将变量存放到.bss段或.bss的子段(subsection)
.align .align{alignment}{,fill}{,max}
通过用零或指定的数据进行填充来使当前位置与指定边界对齐
.balign .balign{alignment}{,fill}{,max}
作用同.align
.org .org offset{,expr}
指定从当前地址加上offset开始存放代码,并且从当前地址到当前
地址加上offset之间的内存单元,用零或指定的数据进行填充
org=origin
其他汇编与反汇编
.end .end
标记汇编文件的结束行,即标记后的代码不做处理
.err .err
使编译结果产生错误报告
.eject .eject
在汇编符号列表文件中插入一分页符
.list .list
.产生汇编列表(从.list到.nolist)
.nolist .nolist
汇编列表结束处。再次使用.list产生汇编列表
.title .title "title_name"
使用heading作为标题(位于汇编列表文件中文件名下一行)
.sbttl .sbttl "title_name"
使用heading作为子标题(位于.title标题下一行)
.print .print string
打印输出信息到标准输出
4.预定义控制操作
.if 条件判断语句
.else 条件判断语句
.endif 条件结束语句
.macro 标识宏定义的开始
.endm 标识宏定义的结束
.exitm .exitm 中途跳转出宏
.include .include "file_name" 包含文件标识
绝大多数 Linux 程序员以前只接触过DOS/Windows 下的汇编语言,这些汇编代码都是 Intel 风格的。但在 Unix 和 Linux 系统中,更多采用的还是 AT&T 格式,两者在语法格式上有着很大的不同:
在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。例如:
AT&T 格式 | Intel 格式 |
pushl %eax | push eax |
AT&T 格式 | Intel 格式 |
pushl $1 | push 1 |
AT&T 格式 | Intel 格式 |
addl $1, %eax | add eax, 1 |
AT&T 格式 | Intel 格式 |
movb val, %al | mov al, byte ptr val |
远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为 "ljump" 和 "lcall",而在 Intel 汇编格式中则为 "jmp far" 和 "call far",即:
AT&T 格式 | Intel 格式 |
ljump $section, $offset | jmp far section:offset |
lcall $section, $offset | call far section:offset |
AT&T 格式 | Intel 格式 |
lret $stack_adjust | ret far stack_adjust |
section:disp(base, index, scale) |
section:[base + index*scale + disp] |
disp + base + index * scale |
AT&T 格式 | Intel 格式 |
movl -4(%ebp), %eax | mov eax, [ebp - 4] |
movl array(, %eax, 4), %eax | mov eax, [eax*4 + array] |
movw array(%ebx, %eax, 4), %cx | mov cx, [ebx + 4*eax + array] |
movb $4, %fs:(%eax) | mov fs:eax, 4 |
1.符号定义伪操作
操作符 语法格式 说明
.equ .equ symbol,expr 将symbol定义为expr
.set .set symbol,expr 和equ相同(.set=.equ)
.equiv .equiv symbol 将symbol定义为expr,若symbol已定义则出错
.global .global symbol 将symbol定义为全局标号
.globl .globl symbol 和.global相同(.globl=.global)
.extern .extern symbol 声明symbol为一个外部变量
2.数据定义伪操作
.byte .byte expr {,expr}…
分配一段字节内存单元,并用expr初始化字节内存单元(8bit)
.hword .bword expr {,expr}…
分配一段半字内存单元,并用expr初始化半字内存单元 (16bit)
.short .short expr {,expr}…
同.hword(16bit)
.word .word expr {,expr}…
分配一段字内存单元,并用expr初始化字内存单元(32bit)
.int .int expr {,expr}…
同.word(32bit)
.long .long expr {,expr}…
同.word(32bit)
.ascii .ascii expr{,expr}… 分配一段字符串内存单元,并用expr初始化字符串内存单元(非零结束符)
.asciz .asciz expr{,expr}… 分配一段字符串内存单元,并用expr初始化字符串内存单元(零结束符)
.string .string expr {,expr}…
同.asciz(零结束符)
.quad .qua expr {,expr}…
分配一段双字内存单元,并用expr初始化双字内存单元
.octa .octa expr{,expr}…
分配一段四字内存单元,并用expr初始化四字内存单元
.float .float expr{,expr}…
分配一段字内存单元,并用32位IEEE单精度浮点数expr初始化内存单元
.single .single expr{,expr}… 同.float
.double .double expr{,expr}… 分配一段双字内存单元,并用64位IEEE双精度浮点数expr初始化内存单元
.fill .fill repeat{,size}{,value} 用size个字节value填充repeat次(size默认为1,value默认为0)
.zero .zreo size
用0填充size个字节的内存单元
.space .space size{,value}
用value填充size个字节的内存单元(value默认为0)
.skip .space size{,value}
同.space
.ltorg .ltorg
声明一个数据缓冲池(literal pool)
3.汇编与反汇编代码控制伪操作
.arm .arm
定义一下代码使用ARM指令集编译
.code 32 .code 32
作用同.arm
.thumb .thumb
定义一下代码使用Thumb指令集编译
.code 16 .code 16
作用同.thumb
.section .section expr
定义域中包含的段。expr可以使.text,.data.,.bss
.text .text {subsection}
将定义符开始的代码编译到代码段或代码子段(subsection)
.data .data {subsection}
将定义符开始的代码编译到数据段或数据子段(subsection)
.bss .bss {subsection}
将变量存放到.bss段或.bss的子段(subsection)
.align .align{alignment}{,fill}{,max}
通过用零或指定的数据进行填充来使当前位置与指定边界对齐
.balign .balign{alignment}{,fill}{,max}
作用同.align
.org .org offset{,expr}
指定从当前地址加上offset开始存放代码,并且从当前地址到当前
地址加上offset之间的内存单元,用零或指定的数据进行填充
org=origin
其他汇编与反汇编
.end .end
标记汇编文件的结束行,即标记后的代码不做处理
.err .err
使编译结果产生错误报告
.eject .eject
在汇编符号列表文件中插入一分页符
.list .list
.产生汇编列表(从.list到.nolist)
.nolist .nolist
汇编列表结束处。再次使用.list产生汇编列表
.title .title "title_name"
使用heading作为标题(位于汇编列表文件中文件名下一行)
.sbttl .sbttl "title_name"
使用heading作为子标题(位于.title标题下一行)
.print .print string
打印输出信息到标准输出
4.预定义控制操作
.if 条件判断语句
.else 条件判断语句
.endif 条件结束语句
.macro 标识宏定义的开始
.endm 标识宏定义的结束
.exitm .exitm 中途跳转出宏
.include .include "file_name" 包含文件标识
相关文章推荐
- CentOS 6.3下部署LVS(NAT)+keepalived实现高性能高可用负载均衡
- CentOS LVS安装配置
- linux下利用curses设置终端颜色显示实例
- 如何在Linux桌面环境下自动启动程序?
- linux标准daemon编写方式
- centos安装ghost.org博客笔记
- centos下Angularjs尝试笔记
- linux命令 Curl
- 用UNetBootin制作CentOS的USB安装盘
- Linux 的源码安装工具 CheckInstall
- 应该知道的Linux技巧
- linux screen 命令 :离线运行程序
- Linux切换进程机制主流程
- Linux终端程序用c语言实现改变输出的字的颜色
- 怎么实现Linux下的逆波兰计算器dc?
- 05-Linux-文件基本操作管理
- Debugging Portal for linux
- Linux命令详解之序
- PrintkTimes for linux
- LINUX TOP,不是这样玩地!!!