GNU for x86汇编语法
作者:冯老师,华清远见嵌入式学院讲师。
译自“Using as The GNU Assembler January 1994”。
参考Tornado随机文档“GNU Toolkit User's Guide"。
GNU Assembler
80386 Dependent Features
■ AT&T语法 vs. Intel语法
为了保持和gcc的输出的兼容性,as支持AT&T System V/386汇编语法,它和Intel语法有相当大的差别。强调这个是因为几乎所有的80386文档只使用Intel语法。两者之间的显著区别是:
● AT&T的立即数有前缀'$',Intel的立即数没有前缀(Intel 'push 4'为AT&T 'push Û)。AT&T的寄存器有前缀'%',Intel的寄存器没有前缀。AT&T的绝对跳转(和相对PC的跳转相反)jump/call操作 数有前缀'*',Intel没有前缀。
● AT&T和Intel语法的源和目的操作数的顺序相反。Intel的'add eax, 4'等效于AT&T的'addl Û, %eax'。使用'source, dest'规范的目标是为了和以前的Unix汇编器保持兼容。
● AT&T语法中的内存操作数的宽度是根据操作码名称的最后一个字符决定的。操作码后缀'b','w',和'l'指定了byte(8- bit),word(16-bit),和long(32-bit)的内存引用。Intel语法则对内存操作数(不是操作码)加前缀:'byte ptr','word ptr'和'dword ptr'。这样,Intel 'mov al, byte ptr foo'等效于AT&T的'movb foo, $al'。
● AT&T中的long jumps和calls的立即形式为'lcall/ljmp $section, $offset';Intel语法为'call/jmp far section:offset'。同样,AT&T的远程返回指令为'lret $stack-adjust',而Intel格式为'ret far stack-adjust'。
● AT&T汇编器不提供对多节(multiple section)程序的支持。Unix风格的系统希望所有的程序都是单节的。
■ 操作码命名(opcode naming)
操作码前有一个字符的后缀,指定了操作数的宽度。字母'b','w',和'l'指定了byte,word, 和long型的操作数。如果指令中没有后缀并且不包含内存操作数,那么as将基于目标寄存器操作数(指令中的最后一个寄存器)填充这个缺少的后缀。所 以,'mov %ax, %bx'等效于'movw %ax, %bx';同样,'mov Û, %bx'等效于'movw Û, %bx'。注意这个特点不和AT&T的Unix汇编器兼容,后者假定缺少的后缀为long型操作数宽度。(这个不兼容型并不影响编译器的输出,因 为编译器总是显式地指定操作码后缀。)
AT&T和Intel中的操作码的格式几乎全部一样,但有一个例外。AT&T的符号扩展 (sign extend)和零扩展(zero exten)指令需要指定2个宽度,一个宽度用来指定sign/zero扩展的from,另一个用来零扩展to。在AT&T语法中使用2个操作码 后缀。符号扩展和零扩展的基本名称是'movs...'和'movz...'(Intel格式为'movsx'和'movzx')。操作码后缀加在这个基 本名称后,from在之前。所以,AT&T语法中'movxbl %al, %edx'意思为”move sign extend from %al to %edx“。所以可能的后缀有'bl'(从byte到long),'bw'(从byte到word),和'wl'(从word到long)。
Intel风格的指令:
● 'cbw' - 符号扩展byte '%al'到word '%ax',
● 'cwde' - 符号扩展word '%ax'到long '%eax',
● 'cwd' - 符号扩展word '%ax'到long '%dx:%ax',
● 'cdq' - 符号扩展dword '%eax'到quad '%edx:%eax',
在AT&T中分别叫'cbtw','cwtl','cwtd',和'cltd'。
远程call/jump指令在AT&T中分别为'lcall'和'ljmp',而Intel的格式为'call far'和'jump far'。
■ 寄存器命名(register naming)
寄存器操作数总有前缀'%'。80386的寄存器包括:
● 8个32-bit寄存器 '%eax'(accumulator),'%ebx','%ecx','%edx','%edi','%esi','%ebp'(<I>frame</I> pointer),和'%esp'(stack pointer)。
● 8个低16-bit的以上寄存器:'%ax','%bx','%cx','%dx','%di','%si','%bp',和'%sp'。
● 6个节寄存器'%cs'(代码节),'%ds'(数据节),'%ss'(堆栈节),'%es', '%fs',和'%gs'。
● 3个处理器控制寄存器'%cr0','%cr2',和'%cr3'。
● 6个调试寄存器'%db0','%db1','%db2','%db3','%db6',和'%db7'。
● 2个测试寄存器'%tr6'和'%tr7'。
● 8个浮点寄存器栈'%st'或等效的'%st(0)','%st(1)','%st(2)','%st(3)','%st(4)','%st(5)','%st(6)',和'%st(7)'。
■ 操作码前缀(opcode prefixes)
操作码前缀用于修改以下操作码。它们用于重复字符串指令,提供节覆盖(section overrides),执行总线锁定操作,以及给出操作数和地址的宽度(对于通常的32-bit操作数,可以使用一个”操作数宽度“操作码前缀,来指定 16-bit的操作数)。操作码前缀通常占据一行,没有操作数,并且必须直接位于它们所作用于的指令之前。例如'scas'(字符串扫描)指令可以这样重 复:
repne
scas
下面列出操作码前缀:
● 节覆盖前缀'cs','ds','ss','es','fs','gs'。
● 操作数/地址宽度前缀'data16'和'addr16',将32-bit的操作数/地址改变为16-bit的操作数/地址。注:16-bit寻址模式(即8086和80286寻址模式)还没有支持。
● 总线锁定前缀'lock',在执行它修饰的指令时禁止中断。(只对特定指令有效,参考80386指令手册。)
● 等待协处理器指令'wait',等待协处理器完成当前指令。对于80386/80387组合这不再需要。
● 'rep','repe',和'repne'前缀用来修饰字符串指令,使它们重复'%ecx'次。
注:操作码前缀(1字节):
0xF0 - LOCK;
0xF2 - REPNE/REPNZ(只用于字符串指令);
0xF3 - REP(只用于字符串指令);
0xF3 - REPE/REPZ(只用于字符串指令);
0xF3 - Streaming SIMD扩展指令;
段前缀:
0x2E - CS段覆盖;
0x36 - SS段覆盖;
0x3E - DS段覆盖;
0x26 - ES段覆盖;
0x64 - FS段覆盖;
0x65 - GS段覆盖。
操作数宽度覆盖:0x66
操作数宽度覆盖:0x66
■ 内存引用(memory references)
Intel语法中间接内存引用的形式为:
section:[base + index*scale + disp]
等效的AT&T语法为:
section:disp(base, index, scale)
其中base和index分别为可选的、32-bit的基址和索引寄存器;disp为可选的偏移 (displacement),scale的取值为1,2,4,和8,乘以index计算操作数的地址。如果不指定scale,scale取值为1。 section指定了内存操作数的可选的节寄存器,它可以覆盖缺省的节寄存器(参考80386手册中的节寄存器的缺省值)。注意AT&T语法中的 节覆盖必须有'%'前缀。如果指定的节覆盖碰巧和缺省的节寄存器相同,那么as并不输出任何节寄存器覆盖前缀。所以,可以使用节寄存器覆盖来强调给定的内 存操作数的节寄存器。
下面是Intel和AT&T的内存引用的例子:
AT&T:'-4(%ebp)',Intel:'[ebp-4]';
base是'%ebp',disp为'-4'。使用缺省的节(%ss)。index和scale缺省。
AT&T:'foo(,%eax,4)',Intel:'[foo + eax*4]';
index为%eax(scale为4),disp为'foo'。节寄存器缺省为%ds。
AT&T:'foo(,1)',Intel:'[foo]';
使用foo指向的值当作内存操作数。注意base和index都缺省,但只有一个',',这是一个语法例外。
AT&T:'%gs:foo',Intel:'gs:foo'。
绝对的call和jump的操作数必须有前缀'*'。如果不指定前缀,as选择PC(program counter)相对寻址。
任何有内存操作数的指令必须指定它的宽度(byte,word,long),使用操作码后缀('b','w','l')。
■ 跳转指令的处理(handling of jump instrucion)
跳转指令总是使用最小可能的偏移(displacement)进行优化。处理方法是,如果目标地址足够近, 那么使用字节(8-bit)偏移的跳转。如果字节偏移不够,那么使用long(32-bit)偏移。不支持word(16-bit)偏移跳转(即在跳转指 令前加'addr16'操作码前缀),这是因为80386坚持,如果使用word偏移那么%eip将被掩码为16-bit。
注意'jcxz','jecxz','loop','loopz','loope','loopnz'和 'loopne'指令只使用byte偏移,所以如果你使用这些指令(gcc不使用),你会得到一个错误消息(以及不正确的代码)。AT&T对这个 问题的解决是扩展'jcxz foo'为:
jcxz cx_zero
jmp cx_nonzero
cx_zero:
jmp foo
cx_nonzero:
■ 浮点(floating point)
(omitted)
■ 写16-bit代码(wrting 16-bit code)
GAS除了支持”纯“32-bit i386代码外,还提供对实模式和16-bit保护模式代码段的有限支持。
(to be continued)
文章来源:华清远见嵌入式学院,原文地址:http://www.embedu.org/Column/Column854.htm
GNU for x86汇编语法的更多相关文章
- GNU风格 ARM汇编语法指南
汇编源程序一般用于系统最基本的初始化:初始化堆栈指针.设置页表.操作 ARM的协处理器等.这些初始化工作完成后就可以跳转到C代码main函数中执行. 1. GNU汇编语言语句格式 任何Linux汇编 ...
- GNU风格 ARM汇编语法5
. GNU汇编程序中的常数 <>十进制数以非0数字开头,如:123和9876: <>二进制数以0b开头,其中字母也可以为大写: <>八进制数以0开始,如:,: &l ...
- GNU风格 ARM汇编语法2
.GNU汇编程序中的标号symbol(或label) 标号只能由a-z,A-Z,-,".",_等(由点.字母.数字.下划线等组成,除局部标号外,不能以数字开头)字符组成. Symb ...
- (转)GNU风格ARM汇编语法指南(非常详细)5
原文地址:http://zqwt.012.blog.163.com/blog/static/120446842010111482417545/ 6.GNU汇编程序中的常数 <1> 十 ...
- (转)GNU风格ARM汇编语法指南(非常详细)2
原文地址:http://zqwt.012.blog.163.com/blog/static/120446842010111481828392/ 2.GNU汇编程序中的标号symbol(或label) ...
- GNU风格 ARM汇编语法1
汇编源程序一般用于系统最基本的初始化:初始化堆栈指针.设置页表.操作 ARM的协处理器等. 这些初始化工作完成后就可以跳转到C代码main函数中执行. 1.GNU汇编语言语句格式 任何Linux汇编行 ...
- (转)GNU风格ARM汇编语法指南(非常详细)1
原文地址:http://zqwt.012.blog.163.com/blog/static/120446842010111481551809/ 汇编源程序一般用于系统最基本的初始化:初始化堆栈指针.设 ...
- GNU风格 ARM汇编语法4
.GNU汇编语言定义入口点 汇编程序的缺省入口是_start标号,用户也可以在连接脚本文件中用ENTRY标志指明其它入口点. 例:定义入口点 .section .data < initializ ...
- GNU风格 ARM汇编语法3
. GNU汇编程序中的分段 <1>.section伪操作 .section <section_name> {,”<flags>”} Starts a new cod ...
随机推荐
- 扩展LV
LVM最大的特性就是可以弹性调整磁盘容量下面扩展一个已经存在的LV [root@ol6--rac1 mnt]# lvdisplay --- Logical volume --- LV Path /de ...
- revert merge会出现的问题
比如当我们git revert的时候, git revert Git会抱怨: is a merge but no -m option was given 这是因为你revert的那个commit是一个 ...
- Spring XML配置文件示例(二)——web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" ...
- 网站通用登录模块代码 分类: ASP.NET 2014-12-06 10:49 615人阅读 评论(0) 收藏
1.HTML部分: <form id="form1" runat="server"> <script src=".. ...
- Win10 UI线程
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => UpdateButtonOrientation());
- PowerDesigner(PowerDesigner15.1.0.2850)下载、安装以及破解
转自:http://www.cnblogs.com/Fonkie/articles/1600662.html 一.先安装PowerDesigner15(PowerDesigner15.1.0.2850 ...
- sidt十六进制代码
00121453 0F010D 40441200 sidt fword ptr ds:[gliu]0012145A 0F014D B0 sidt fword ptr ss:[ebp-0x50]0012 ...
- background为圆角的表框,dp转Px,Px转dp
圆角边框<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="ht ...
- Android Manifest 权限描述大全
权限 名称 描述 android.permission.ACCESS_CHECKIN_PROPERTIES 访问登记属性 读取或写入登记check-in数据库属性表的权限 android.permis ...
- JSON语法简介 介绍 json
JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation),类似 XML,但比 XML 更小.更快,更易解析. 实例 { "employees ...