(转) 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,排版格式会发生很大的变化,比如行距过窄.内嵌字 ...
随机推荐
- 关于WEB前端开发的工具
俗话说:"工谷善其事,先必利其器."一个用得顺手的工具,确实能为我们的开发带来方 便,更重要的是会让我们更加享受工具开发过程中所带来的乐趣. 1.编码工具: 记事本之类的编辑器都可 ...
- C# 的枚Enum
简短的解释: enum 关键字用来声明枚举,一种包含一组被称为枚举数列表的 enum myType{ a, b, c,} int num = 1;Console.Write((myType)num); ...
- Cocos Creator代码编辑环境配置
1,可以使用较为适合js的webstorm,亦可以采用VS: 2,若需要webstorm,在下载之后,在文件,设置内外部编辑器选用webstorm.exe,即可: 3,Visual Studio Co ...
- [原创]Eclipse Memory Analyzer tool(MAT)工个使用介绍
[原创]Eclipse Memory Analyzer tool(MAT)工个使用介绍
- FXAA,FSAA与MSAA有什么区别?效果和性能上哪个好
而MSAA基本上只对画面中物体的边缘进行放大.混合的抗锯操作,因为边缘是锯齿最明显的地方(注意不是所有的边缘).提取边缘,主要是结合深度技术.MSAA是种硬件AA.我们一般说的4x.8x,就是放大倍数 ...
- Chart-template
ylbtech-Chart: 1.返回顶部 1-1. 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返回顶部 8.返回顶部 9.返回顶部 ...
- Springboot打包支持第三方jar
有时候我们需要的jar在maven里不存在,需要手动引入.比如,钉钉sdk <dependency> <groupId>com.aliyun</groupId> & ...
- [Python设计模式] 第7章 找人帮忙追美眉——代理模式
github地址:https://github.com/cheesezh/python_design_patterns 题目1 Boy追求Girl,给Girl送鲜花,送巧克力,送洋娃娃. class ...
- weex开发错误汇总
weex run serve 报UglifyJS错 ANDROID_HOME环境变量 weex build android需要ANDROID_HOME, 请配置 D:\adt-windows-x86_ ...
- 基于Python使用Redis的一些想法和建议
目录 1关于Redis使用的一点想法 1.1进行缓存前,需考虑 1.2进行缓存后,需考虑 1.3缓存使用一段时间后 2编写Redis数据库层规范建议 2.1选择适合的redis客户端 2.2规范化定义 ...