c和汇编混编语法Word格式.docx
- 文档编号:15396533
- 上传时间:2022-10-30
- 格式:DOCX
- 页数:30
- 大小:36.36KB
c和汇编混编语法Word格式.docx
《c和汇编混编语法Word格式.docx》由会员分享,可在线阅读,更多相关《c和汇编混编语法Word格式.docx(30页珍藏版)》请在冰豆网上搜索。
%es,%fs,%gs;
3个控制寄存器:
%cr0,%cr2,%cr3;
6个debug寄存器:
%db0,%db1,%db2,%db3,%db6,%db7;
2个测试寄存器:
%tr6,%tr7;
8个浮点寄存器栈:
%st(0),%st
(1),%st
(2),%st(3),%st(4),%st(5),%st(6),%st(7)。
2.
操作数顺序
操作数排列是从源(左)到目的(右),如“movl
%eax(源),
%ebx(目的)”
3.
立即数
使用立即数,要在数前面加符号$,
如“movl$0x04,
%ebx”
或者:
para
=0x04
movl$para,%ebx
指令执行的结果是将立即数04h装入寄存器ebx。
4.
符号常数
符号常数直接引用
如
value:
.long
0x12a3f2de
movlvalue,
%ebx
指令执行的结果是将常数0x12a3f2de装入寄存器ebx。
引用符号地址在符号前加符号$,
如“movl$value,%
ebx”则是将符号value的地址装入寄存器ebx。
5.
操作数的长度
操作数的长度用加在指令后的符号表示b(byte,
8-bit),w(word,16-bits),l(long,32-bits),如“movb
%al,%bl”,“movw
%ax,%bx”,“movl
%eax,%ebx”。
如果没有指定操作数长度的话,编译器将按照目标操作数的长度来设置。
比如指令“mov
%ax,%bx”,由于目标操作数bx的长度为word,那么编译器将把此指令等同于“movw
%ax,%bx”。
同样道理,指令“mov
$4,%ebx”等同于指令“movl
$4,%ebx”,“push
%al”等同于“pushb
%al”。
对于没有指定操作数长度,但编译器又无法猜测的指令,编译器将会报错,比如指令“push
$4”。
6.
符号扩展和零扩展指令
绝大多数面向80386的AT&
T汇编指令与Intel格式的汇编指令都是相同的,符号扩展指令和零扩展指令则是仅有的不同格式指令。
符号扩展指令和零扩展指令需要指定源操作数长度和目的操作数长度,即使在某些指令中这些操作数是隐含的。
在AT&
T语法中,符号扩展和零扩展指令的格式为,基本部分"
movs"
和"
movz"
(对应Intel语法的movsx和movzx),后面跟上源操作数长度和
目的操作数长度。
movsbl意味着movs
(from)byte
(to)long;
movbw意味着movs
(to)word;
movswl意味着movs
(from)word
(to)long。
对于movz指令也一样。
比如指令“movsbl
%al,%edx”意味着将al寄存器的内容进行符号扩展后放置到edx寄存器中。
其它的Intel格式的符号扩展指令还有:
cbw
--sign-extendbytein%altowordin%ax;
cwde
--sign-extendwordin%axtolongin%eax;
cwd
--sign-extendwordin%axtolongin%dx:
%ax;
cdq
--sign-extenddwordin%eaxtoquadin
%edx:
%eax;
对应的AT&
T语法的指令为cbtw,cwtl,cwtd,cltd。
7.
调用和跳转指令
段内调用和跳转指令为"
call"
,"
ret"
jmp"
,段间调用和跳转指令为"
lcall"
lret"
ljmp"
。
段间调用和跳转指令的格式为“lcall/ljmp
$SECTION,$OFFSET”,而段间返回指令则为“lret
$STACK-ADJUST”。
8.
前缀
操作码前缀被用在下列的情况:
字符串重复操作指令(rep,repne);
指定被操作的段(cs,ds,ss,es,fs,gs);
进行总线加锁(lock);
指定地址和操作的大小(data16,addr16);
T汇编语法中,操作码前缀通常被单独放在一行,后面不跟任何操作数。
例如,对于重复scas指令,其写法为:
repne
scas
上述操作码前缀的意义和用法如下:
指定被操作的段前缀为cs,ds,ss,es,fs,和gs。
T语法中,只需要按照section:
memory-operand的格式就指定了相应的段前缀。
比如:
lcall
%cs:
realmode_swtch
操作数/地址大小前缀是“data16”和"
addr16"
,它们被用来在32-bit操作数/地址代码中指定16-bit的操作数/地址。
总
线加锁前缀“lock”,它是为了在多处理器环境中,保证在当前指令执行期间禁止一切中断。
这个前缀仅仅对ADD,
ADC,AND,BTC,BTR,BTS,CMPXCHG,DEC,INC,NEG,NOT,OR,SBB,SUB,
XOR,XADD,XCHG指令有效,如果将Lock前缀用在其它指令之前,将会引起异常。
字符串重复操作前缀"
rep"
"
repe"
repne"
用来让字符串操作重复“%ecx”次。
9.
内存引用
Intel语法的间接内存引用的格式为:
section:
[base+index*scale+displacement]
而在AT&
T语法中对应的形式为:
displacement(base,index,scale)
其
中,base和index是任意的32-bit
base和index寄存器。
scale可以取值1,2,4,8。
如果不指定scale值,则默认值为1。
section可以指定任意的段寄存器作为段前
缀,默认的段寄存器在不同的情况下不一样。
如果你在指令中指定了默认的段前缀,则编译器在目标代码中不会产生此段前缀代码。
下面是一些例子:
-4(%ebp):
base=%ebp,displacement=-4,section没有指定,由于base=%ebp,所以默认的section=%ss,index,scale没有指定,则index为0。
foo(,%eax,4):
index=%eax,scale=4,displacement=foo。
其它域没有指定。
这里默认的section=%ds。
foo(,1):
这个表达式引用的是指针foo指向的地址所存放的值。
注意这个表达式中没有base和index,并且只有一个逗号,这是一种异常语法,但却合法。
%gs:
foo:
这个表达式引用的是放置于%gs段里变量foo的值。
如果call和jump操作在操作数前指定前缀“*”,则表示是一个绝对地址调用/跳转,也就是说jmp/call指令指定的是一个绝对地址。
如果没有指定"
*"
,则操作数是一个相对地址。
任何指令如果其操作数是一个内存操作,则指令必须指定它的操作尺寸(byte,word,long),也就是说必须带有指令后缀(b,w,l)。
.3
GCCInlineASM
GCC支持在C/C++代码中嵌入汇编代码,这些汇编代码被称作GCC
Inline
ASM——GCC内联汇编。
这是一个非常有用的功能,有利于我们将一些C/C++语法无法表达的指令直接潜入C/C++代码中,另外也允许我们直接写
C/C++代码中使用汇编编写简洁高效的代码。
1.基本内联汇编
GCC中基本的内联汇编非常易懂,我们先来看两个简单的例子:
__asm__("
movl
%esp,%eax"
);
//看起来很熟悉吧!
或者是
$1,%eax//SYS_exit
xor%ebx,%ebx
int
$0x80
"
或
__asm__(
$1,%eax\r\t"
\
xor%ebx,%ebx\r\t"
$0x80"
基本内联汇编的格式是
__asm__
__volatile__("
Instruction
List"
1、__asm__
__asm__是GCC关键字asm的宏定义:
#define
asm
__asm__或asm用来声明一个内联汇编表达式,所以任何一个内联汇编表达式都是以它开头的,是必不可少的。
2、Instruction
List
InstructionList是汇编指令序列。
它可以是空的,比如:
或__asm__
("
都是完全合法的内联汇编表达式,只不过这两条语句没有什么意义。
但并非所有Instruction
List为空的内联汇编表达式都是没有意义的,比如:
:
memory"
就非常有意义,它向GCC声明:
“我对内存作了改动”,GCC在编译的时候,会将此因素考虑进去。
我们看一看下面这个例子:
$
catexample1.c
intmain(int__argc,char*__argv[])
{
int*__p=(int*)__argc;
(*__p)=9999;
//__asm__("
if((*__p)
==9999)
return5;
return(*__p);
}
在
这段代码中,那条内联汇编是被注释掉的。
在这条内联汇编之前,内存指针__p所指向的内存被赋值为9999,随即在内联汇编之后,一条if语句判断__p
所指向的内存与9999是否相等。
很明显,它们是相等的。
GCC在优化编译的时候能够很聪明的发现这一点。
我们使用下面的命令行对其进行编译:
gcc-O-S
example1.c
选项-O表示优化编译,我们还可以指定优化等级,比如-O2表示优化等级为2;
选项-S表示将C/C++源文件编译为汇编文件,文件名和C/C++文件一样,只不过扩展名由.c变为.s。
我们来查看一下被放在example1.s中的编译结果,我们这里仅仅列出了使用gcc
2.96在redhat
7.3上编译后的相关函数部分汇编代码。
为了保持清晰性,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 汇编 混编 语法