(转) at&T语法格式 与 at&T - intel格式对比
movl (%ebp), %eax,
等同于Intel格式中的
mov EAX, [EBP + ]
,AT&T中,源操作数在左,目的操作数在右。“l”是Longword,相当于Intel格式中的dword ptr操作限定符;
表示将地址SS:[EBP +12]指向的双字数据传送至EAX寄存器。
addl (%ebp), %eax,
等同于Intel格式中的
add EAX, [EBP + ],
表示将SS:[EBP + 8]指向的一个双字数据同寄存器EAX中的原值相加,所得的结果保存在EAX寄存器。
ebp+xx是参数偏移,ebp-xx是局部变量偏移
参数 N <--- [ebp+4*N+4]
参数 2 <--- [ebp+12]
参数 1 <--- [ebp+8]
返回地址 <--- [ebp+4]
旧的ebp值(调用者的ebp) <--- [ebp]
局部变量 1 <---[ebp-4]
局部变量 2 <--- [ebp-8]
所以
- 在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。例如:
|
AT&T 格式
|
Intel 格式
|
|
pushl %eax
|
push eax
|
- 在 AT&T 汇编格式中,用 '$' 前缀表示一个立即操作数;而在 Intel 汇编格式中,立即数的表示不用带任何前缀。例如:
|
AT&T 格式
|
Intel 格式
|
|
pushl $1
|
push 1
|
- AT&T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。在 Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边。例如:
|
AT&T 格式
|
Intel 格式
|
|
addl $1, %eax
|
add eax, 1
|
- 在 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀'b'、'w'、'l'分别表示操作数为字节(byte,8 比特)、字(word,16 比特)和长字(long,32比特);而在 Intel 汇编格式中,操作数的字长是用 "byte ptr" 和 "word ptr" 等前缀来表示的。例如:
|
AT&T 格式
|
Intel 格式
|
|
movb val, %al
|
mov al, byte ptr val
|
- 在 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上'*'作为前缀,而在 Intel 格式中则不需要。
- 远程转移指令和远程子调用指令的操作码,在 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
|
- 在 AT&T 汇编格式中,内存操作数的寻址方式是
section:disp(base, index, scale)
- 而在 Intel 汇编格式中,内存操作数的寻址方式为:
section:[base + index*scale + disp]
- 由于 Linux 工作在保护模式下,用的是 32 位线性地址,所以在计算地址时不用考虑段基址和偏移量,而是采用如下的地址计算方法:
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
|
#hello.s
.data # 数据段声明
msg : .string "Hello, world!\\n" # 要输出的字符串
len = . - msg # 字串长度
.text # 代码段声明
.global _start # 指定入口函数
_start: # 在屏幕上显示一个字符串
movl $len, %edx # 参数三:字符串长度
movl $msg, %ecx # 参数二:要显示的字符串
movl $, %ebx # 参数一:文件描述符(stdout)
movl $, %eax # 系统调用号(sys_write)
int $0x80 # 调用内核功能
# 退出程序
movl $,%ebx # 参数一:退出代码
movl $,%eax # 系统调用号(sys_exit)
int $0x80 # 调用内核功能
; hello.asm
section .data ; 数据段声明
msg db "Hello, world!", 0xA ; 要输出的字符串
len equ $ - msg ; 字串长度
section .text ; 代码段声明
global _start ; 指定入口函数
_start: ; 在屏幕上显示一个字符串
mov edx, len ; 参数三:字符串长度
mov ecx, msg ; 参数二:要显示的字符串
mov ebx, ; 参数一:文件描述符(stdout)
mov eax, ; 系统调用号(sys_write)
int 0x80 ; 调用内核功能
; 退出程序
mov ebx, ; 参数一:退出代码
mov eax, ; 系统调用号(sys_exit)
int 0x80 ; 调用内核功能
平台下有两种方式来使用系统调用:利用封装后的
C
库(libc)或者通过汇编直接调用。其中通过汇编语言来直接调用系统调用,是最高效地使用
Linux
内核服务的方法,因为最终生成的程序不需要与任何库进行链接,而是直接和内核通信。
下的系统调用也是通过中断(int
0x80)来实现的。在执行 int 80 指令时,寄存器 eax
中存放的是系统调用的功能号,而传给系统调用的参数则必须按顺序放到寄存器
ebx,ecx,edx,esi,edi
中,当系统调用完成之后,返回值可以在寄存器 eax
中获得。
/usr/include/bits/syscall.h
中找到,为了便于使用,它们是用
SYS_<name>
这样的宏来定义的,如 SYS_write、SYS_exit
等。例如,经常用到的 write
函数是如下定义的:
ssize_t write(int fd, const void *buf, size_t count);
void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);c
# args.s
.text
.globl _start
_start:
popl %ecx # argc
vnext:
popl %ecx # argv
test %ecx, %ecx # 空指针表明结束
jz exit
movl %ecx, %ebx
xorl %edx, %edx
strlen:
movb (%ebx), %al
inc %edx
inc %ebx
test %al, %al
jnz strlen
movb $, -(%ebx)
movl $, %eax # 系统调用号(sys_write)
movl $, %ebx # 文件描述符(stdout)
int $0x80
jmp vnext
exit: movl $,%eax # 系统调用号(sys_exit)
xorl %ebx, %ebx # 退出代码
int $0x80
ret
C
语言程序中,从而充分利用高级语言和汇编语言各自的特点。但一般来讲,在
C
代码中嵌入汇编语句要比"纯粹"的汇编语言代码复杂得多,因为需要解决如何分配寄存器,以及如何与C代码中的变量相结合等问题。
提供了很好的内联汇编支持,最基本的格式是:
|
__asm__("asm statements");
|
|
__asm__("nop");
|
|
__asm__( "pushl %%eax \\n\\t"
"movl $0, %%eax \\n\\t"
"popl %eax");
|
代码中的汇编语句很难做到与其它部分没有任何关系,因此更多时候需要用到完整的内联汇编格式:
|
__asm__("asm statements" : outputs : inputs :
registers-modified); |
代码中的汇编语句是以":"分隔的四个部分,其中第一部分就是汇编代码本身,通常称为指令部,其格式和在汇编语言中使用的格式基本相同。指令部分是必须的,而其它部分则可以根据实际情况而省略。
内联汇编语句的指令部中,加上前缀''%''的数字(如%0,%1)表示的就是需要使用寄存器的"样板"操作数。指令部中使用了几个样板操作数,就表明有几个变量需要与寄存器相结合,这样GCC和GAS在编译和汇编时会根据后面给定的约束条件进行恰当的处理。由于样板操作数也使用''
%''作为前缀,因此在涉及到具体的寄存器时,寄存器名前面应该加上两个''%'',以免产生混淆。
int main()
{
int a = , b = ;
__asm__ __volatile__("movl %1, %%eax;\\n\\r"
"movl %%eax, %0;"
:"=r"(b)
:"r"(a)
:"%eax");
printf("Result: %d, %d\\n", a, b);
}
- 变量b是输出操作数,通过%0来引用,而变量a是输入操作数,通过%1来引用。
- 输入操作数和输出操作数都使用r进行约束,表示将变量a和变量b存储在寄存器中。输入约束和输出约束的不同点在于输出约束多一个约束修饰符''=''。
- 在内联汇编语句中使用寄存器eax时,寄存器名前应该加两个''%'',即%%eax。内联汇编中使用%0、%1等来标识变量,任何只带一个''%''的标识符都看成是操作数,而不是寄存器。
- 内联汇编语句的最后一个部分告诉GCC它将改变寄存器eax中的值,GCC在处理时不应使用该寄存器来存储任何其它的值。
- 由于变量b被指定成输出操作数,当内联汇编语句执行完毕后,它所保存的值将被更新。
|
限定符
|
意义
|
|
"m"、"v"、"o"
|
内存单元
|
|
"r"
|
任何寄存器
|
|
"q"
|
寄存器eax、ebx、ecx、edx之一
|
|
"i"、"h"
|
直接操作数
|
|
"E"和"F"
|
浮点数
|
|
"g"
|
任意
|
|
"a"、"b"、"c"、"d"
|
分别表示寄存器eax、ebx、ecx和edx
|
|
"S"和"D"
|
寄存器esi、edi
|
|
"I"
|
常数(0至31)
|
(转) at&T语法格式 与 at&T - intel格式对比的更多相关文章
- Motorola和Intel格式报文解析的区别
结论:无论用的Motorola,还是Intel格式,只在单个信号跨字节时解析才有区别. 先看下Vector的CANoe中dbc编辑器是如何呈现报文的: 图1 CAN报文中byte与bit顺序 从图 ...
- Intel格式和AT&T格式汇编区别
一.AT&T 格式Linux 汇编语法格式 在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀:而在 Intel 汇编格式中,寄存器名不需要加前缀.例如: AT&T 格 ...
- web字体格式及几种在线格式转换工具介绍
原文地址:http://blog.csdn.net/xiaolongtotop/article/details/8316554 目前,文字信息仍是网站最主要的内容,随着CSS3技术的不断成熟,Web字 ...
- [转] Java程序员学C#基本语法两个小时搞定(对比学习)
Java程序员学C#基本语法两个小时搞定(对比学习) 对于学习一门新的语言,关键是学习新语言和以前掌握的语言的区别,但是也不要让以前语言的东西,固定了自己的思维模式,多看一下新的语言的编程思想. ...
- JavaScript中,JSON格式的字符串与JSON格式的对象相互转化
前言:JSON是一个独立于任何语言的数据格式,因此,严格来说,没有“JSON对象”和“JSON字符串”这个说法(然而”菜鸟教程“和”W3school“使用了“JSON对象”和“JSON字符串”这个说法 ...
- 让gcc和gdb支持intel格式的汇编
Linux下的gdb和gcc默认输出的汇编都是AT&T格式的,但是它们都有方式来转换为Intel格式. -masm=[intel|att] 选择intel或AT&T的汇编语法 gcc ...
- [转] 将DOS格式文本文件转换成UNIX格式
点击此处阅读原文 用途说明 dos2unix命令用来将DOS格式的文本文件转换成UNIX格式的(DOS/MAC to UNIX text file format converter).DOS下的文本文 ...
- Linux C++ 调试神技--如何将Linux C++ 可执行文件逆向工程到Intel格式汇编
Linux C++ 调试神技--如何将Linux C++ 可执行文件逆向工程到Intel格式汇编 对于许多在windows 上调试代码的人而言, Intel IA32格式的汇编代码可能并不陌生,因为种 ...
- 【转】将 azw3 格式转换为 mobi 格式并保持原有排版格式
小伙伴多次向 Kindle 伴侣提出一个问题,那就是通过 Calibre 将排版精美的 azw3 格式电子书转换成 mobi 格式后推送到 Kindle,排版格式会发生很大的变化,比如行距过窄.内嵌字 ...
随机推荐
- Git问题Everything up-to-date解决
Git问题Everything up-to-date解决 [自己的亲身错误体验] 我的上一篇博客,说了怎么上传一个项目到git远程上面.今天我写好一个小栗子,准备再次上传的时候.我依旧是放在我的F:\ ...
- CocosCreator编辑器界面
1,资源管理器[参考来源:官方文档] 资源管理器 里显示了项目资源文件夹(assets)中的所有资源.这里会以树状结构显示文件夹并自动同步在操作系统中对项目资源文件夹内容的修改.您可以将文件从项目外面 ...
- 几种Unity运行平台的判断
这里就介绍几种常见的,也是便于使用的几种平台判断的方法. 1.先说第一种,也是我用的顺手的一个.利用RuntimePlatform判断,API上的解释是[The platform applicatio ...
- ftp命令详解补充
下面我来详细地介绍一个登陆FTP的命令和步骤吧: FTP命令是Internet用户使用最频繁的命令之一,不论是在DOS还是UNIX操作系统下使用FTP,都会遇到大量的FTP内部命令.熟悉并灵活应用F ...
- Asp.Net Mvc项目初始化说明
文件夹说明: App_Start 项目的启动配置 Content css以及图片资源存放位置 Controllers.Models.View控制器.模型.视图存放位置 Scripts js以及js插件 ...
- Class.forName和ClassLoader.loadClass的区别
Class的装载分了三个阶段,loading,linking和initializing,分别定义在The Java Language Specification的12.2,12.3和12.4. Cla ...
- 【Android】Android传感器
1.加速度传感器2.磁场传感器3.方向传感器4.陀螺仪传感器5.重力传感器6.线性加速度传感器7.温度传感器8.光线传感器9.距离传感器10.压力传感器11.计步传感器 首先先查看测试的安卓机拥有的传 ...
- 【CLR】详解CLR中的程序集
目录结构: contents structure [+] 程序集的简介 为程序集分配强名称 如何指定程序集的版本资源信息 如何对程序集签名 全局程序集缓存 如何查看程序集的信息 强命名程序集防串改 1 ...
- C#:文件夹匹配
//文件夹匹配:对比文件夹,相同的目录结构.所有文件名称小写相同,制定文件外的MD5值相同 ,则两个文件夹匹配成功! /// <summary> /// 批量匹配书籍H5资源包 /// & ...
- 设置Nginx以列表方式显示网站内容
服务器目录内容: 访问该页面时,将所有文件和目录按列表方式显示 nginx配置文件