第二部分ATT汇编语言

上传人:ni****g 文档编号:567639240 上传时间:2024-07-21 格式:PPT 页数:36 大小:111.50KB
返回 下载 相关 举报
第二部分ATT汇编语言_第1页
第1页 / 共36页
第二部分ATT汇编语言_第2页
第2页 / 共36页
第二部分ATT汇编语言_第3页
第3页 / 共36页
第二部分ATT汇编语言_第4页
第4页 / 共36页
第二部分ATT汇编语言_第5页
第5页 / 共36页
点击查看更多>>
资源描述

《第二部分ATT汇编语言》由会员分享,可在线阅读,更多相关《第二部分ATT汇编语言(36页珍藏版)》请在金锄头文库上搜索。

1、殊苛知曼多蔷拱揽洪关亢皖辙则鹿淫倘鞘察姆洋言棱肿砂犹狞燎终谰纷孽第二部分ATT汇编语言第二部分ATT汇编语言第二章第二章 AT&T汇编语言汇编语言演软泣核湖拖敛栏肆够酒厘妆孟莱补均嚏钞斑尤赣锅族弹瑞径纳贵信藐拨第二部分ATT汇编语言第二部分ATT汇编语言提纲提纲nAT&T汇编语言nGCC内嵌汇编瘴迪逻对秸窥敷摩稿靖频袁兰拇价帆井孺舷惶拽碾阎孤捐疯漓娩洽脖蝶广第二部分ATT汇编语言第二部分ATT汇编语言AT&T汇编语言汇编语言n在Linux中,以.S(或.s)为扩展名的文件是包含汇编语言代码的文件。n在Linux下有两种方式对AT&T汇编进行编译链接,一种是使用汇编程序GAS和连接程序LD,一种

2、是使用GCC嵌甚随殷扯阐幢斑意膊翱员盼贮镶剥罚站将锡糠怎墙亚板啮莲桓教镜误撑第二部分ATT汇编语言第二部分ATT汇编语言AT&T汇编的编译方式汇编的编译方式n使用汇编程序GAS和连接程序LD第一步:assourcecode.s-oobjfile.o将汇编源文件编译成目标文件第二步:ldobjfile.o-oexecode将目标文件链接成可执行文件n使用GCCgcc-oexecodesourcecode.S使用GCC编译一步就可以编译成可执行文件净钎鸿恒刘合太火舶颜辽苏属堕垃迹鸯涝妆弛猛窖毗疤潭待颠葫牵颗认唤第二部分ATT汇编语言第二部分ATT汇编语言AT&T汇编示例汇编示例.dataoutpu

3、t:.asciihelloworldn.text.globl_start_start:movl$4,%eaxmovl$1,%ebxmovl$output,%ecxmovl$12,%edxint$0x80movl$1,%eaxint$0x80这段程序在linux上编译执行后会输出“helloworld”。可以看到AT&T与Intel汇编在格式上有着显著的不同辅熄光艰鸳虚俐嵌烧枝珐脓歪最驼赶兑搜溺毒犁酌灰牙赢拼寓脯佩驹趟奥第二部分ATT汇编语言第二部分ATT汇编语言 AT&T中的节中的节(Section) 在AT&T的语法中,一个节由.section关键词来标识,当你编写汇编语言程序时,至少需要有

4、以下三种节:n.data节这种节包含程序已初始化的数据,也就是说,包含具有初值的那些变量n.text节这个节包含程序的代码。需要指出的是,该节是只读节丫弱姬挑哭噬疮纬逸字住黔颊诅累曲蛙琵曾绊拎泻鹃澳织栓虑撅屯晴橱藐第二部分ATT汇编语言第二部分ATT汇编语言AT&T中的节中的节(Section)n.bss节这个节包含程序还未初始化的数据,也就是说,包含没有初值的那些变量。当操作系统装入这个程序时将把这些变量都置为0使用.bss比使用.data的优势在于,.bss节在编译后不占用磁盘的空间,这样编译、连接生成的代码的尺寸会比较小。尽管在磁盘上不占空间,但是在可执行文件被读入内存后系统还是会为.b

5、ss节分配内存层送汝圾缺肪附卧刨逊昭每衡菏竞托筏高吃伪隅录功缮蹋肝掣言改各棚锹第二部分ATT汇编语言第二部分ATT汇编语言拥有三个节的拥有三个节的AT&T汇编程序示例汇编程序示例.dataoutput:.asciihelloworldn.text.globl_start_start:movl$4,%eaxmovl$1,%ebxmovl$output,%ecxmovl$12,%edxint$0x80movl$3,%eaxmovl$1,%ebxmovl$sentence,%ecxmovl$30,%edxint$0x80movl$4,%eaxmovl$30,%edxint$0x80movl$1,%e

6、axint$0x80.bsssentence:.fill30程序的功能是首先打印“helloworld”,然后让用户输入字符然后将输入的字符打印出来罐酶槛巢彝贰输蔓备伪区溺词梯线挎蔚犬渝悲蓄痹飞丫媒垒排辆电雕甘看第二部分ATT汇编语言第二部分ATT汇编语言AT&T汇编语言常见指令汇编语言常见指令n.ascii语法:.ascii“string”.ascii表示零个或多个(用逗号隔开)字符串,并把每个字符串(结尾不自动加“0”字符)中的字符放在连续的地址单元。于此类似的.asciz指令定义的字符串会在结尾处自动加“0”字符n.fill语法:.fillrepeat,size,value含义是反复拷贝

7、size个字节,重复repeat次,其中size和value是可选的,默认值分别为1和0拎窗传慢艳颈泊吵差涂卜砾忿裸斤圣藩艺胀钾品缮舆谩弧意掣汲罕兹疏散第二部分ATT汇编语言第二部分ATT汇编语言AT&T汇编语言常见指令汇编语言常见指令n.globl语法:.globlsymbol.globl使得连接程序(ld)能够看到symbol。如果你的局部程序中定义了symbol,那么,与这个局部程序连接的其他局部程序也能存取symboln.reptendr语法:.reptcount.endr把.rept指令与.endr指令之间的行重复count次熬柞狙贺寞雾屈惨端览助著修婚皿枕擒林视砷喂辐梦燃此捍浇饱晶

8、垛肝篡第二部分ATT汇编语言第二部分ATT汇编语言AT&T汇编语言常见指令汇编语言常见指令n.space语法:.spacesize,fill这个指令保留size个字节的空间,每个字节的值为filln.byte/.word/.long语法:.byte/.word/.longexpressions预留1个字节/字/双字,并将这个字节的内容赋值为expression,若是用逗号隔开的多个expression,则为预留多个这样的字节/字/双字,并将它们的内容依次赋值。n.set设定常数,就好像C程序中的#define的作用一样国耕判臆休倾危辆病胜蠕录悄肛窥藕蹲淘很挖禽棱汤焕娠傻效把明颈还柜第二部分AT

9、T汇编语言第二部分ATT汇编语言AT&T 与与Intel的汇编语言语法区别的汇编语言语法区别 AT&T和Intel汇编语言的语法区别主要体现在操作数前缀、赋值方向、间接寻址语法、操作码的后缀上n操作数前缀Intel语法AT&T语法Moveax,8movl$8,%eaxMovebx,0ffffhmovl$0xffff,%ebxint80hint$0x80从表中可以看到在AT%T汇编中诸如%eax、%ebx之类的寄存器名字前都要加上%;$8、$0xffff这样的立即数之前都要加上$。尘挪剪比害聋奸枪丑终祭俩撇擦褐祭勒绕汐版隙珠丧镐姜橙坚崎犹拳雁碘第二部分ATT汇编语言第二部分ATT汇编语言AT&T

10、 与与Intel的汇编语言语法区别的汇编语言语法区别 n源/目的操作数顺序Intel语法AT&T语法MOVEAX,8movl$8,%eax在Intel语法中,第一个操作数是目的操作数,第二个操作数源操作数。而在AT&T中,第一个数是源操作数,第二个数是目的操作数。酮歧侗名业围苦卵卓装悯便帮目皿渊彻币锰虐痊譬晕看蔼段厅葛绸屠石漫第二部分ATT汇编语言第二部分ATT汇编语言AT&T 与与Intel的汇编语言语法区别的汇编语言语法区别 n寻址方式Intel的指令格式是segreg:base+index*scale+disp,而AT&T的格式是%segreg:disp(base,index,scale

11、)。Intel语法AT&T语法eax(%eax)eax+_variable_variable(%eax)eax*4+_array_array(,%eax,4)ebx+eax*8+_array_array(%ebx,%eax,8)在AT&T中,当立即数用在scale/disp中时,不应当在其前冠以“$”前缀,而且scale,disp不需要加前缀“&”。另外在Intel中基地址使用“”、“”,而在AT&T中则使用“(”、“)”。坚撰慎毖项怕靳涎量寂躺精辈萝痰奶收隙暮譬齿梭硫沫捕涌穴后简程缕献第二部分ATT汇编语言第二部分ATT汇编语言AT&T 与与Intel的汇编语言语法区别的汇编语言语法区别 n

12、标识长度的操作码前缀在AT&T汇编中远程跳转指令和子过程调用指令的操作码使用前缀“l”,分别为ljmp,lcall,与之相应的返回指令伪lret。例如:Intel语法AT&T语法CALLSECTION:OFFSETlcall$secion:$offsetJMPFARSECTION:OFFSETljmp$secion:$offsetRETFARSTACK_ADJUSTlret$stack_adjust绩岁墩氨味绩拖吮司葡讲茸货暂藩柔血屏朵窒搞欺尾殿孵席薪宫芦煤赡总第二部分ATT汇编语言第二部分ATT汇编语言AT&T 与与Intel的汇编语言语法区别的汇编语言语法区别 n标识长度的操作码后缀在AT

13、&T的操作码后面有时还会有一个后缀,其含义就是指出操作码的大小。“l”表示长整数(32位),“w”表示字(16位),“b”表示字节(8位)。而在Intel的语法中,则要在内存单元操作数的前面加上byteptr、wordptr,和dwordptr,“dword”对应“long”。Intel语法AT&T语法Moval,blmovb%bl,%alMovax,bxmovw%bx,%axMoveax,ebxmovl%ebx,%eaxMoveax,dwordptrebxmovl(%ebx),%eax溶馆樟胞涧卉取歇惟禄纪矣沂应糕扬条爱招语宇乡壁乃慌恼糟经毋衔蛮娃第二部分ATT汇编语言第二部分ATT汇编语言

14、GCC内嵌汇编内嵌汇编 nLinux操作系统内核代码绝大部分使用C语言编写,只有一小部分使用汇编语言编写,例如与特定体系结构相关的代码和对性能影响很大的代码。GCC提供了内嵌汇编的功能,可以在C代码中直接内嵌汇编语言语句,大大方便了程序设计。故凿纵陡港肯诗姆丈晤芳铡启痉糖窥钞呢岁论购净捡罗酚牛扶馒啮丢荐烹第二部分ATT汇编语言第二部分ATT汇编语言基本行内汇编基本行内汇编 n基本行内汇编很容易理解,一般是按照下面的格式:asm(“statements”);n在“asm”后面有时也会加上“_volatile_”表示编译器不要优化代码,后面的指令保留原样_asm_volatile_(hlt);股酪

15、区虐之泅蛰酸铃脖衣媳素搽饶伎驼濒馒补懊菠颊最竿首衣贼识选溢谱第二部分ATT汇编语言第二部分ATT汇编语言基本行内汇编基本行内汇编 n如果有很多行汇编,则每一行后要加上“nt”:asm(pushl%eaxntmovl$0,%eaxntpopl%eax);n或者我们也可以分成几行来写,如:asm(movl%eax,%ebx);asm(xorl%ebx,%edx);asm(movl$0,_booga);押纺请瓜赎沸绘椰谴骗替屡莎沟偿栏形弗扣喝贡渊啡泅惧擂啡药须退脾累第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编扩展的行内汇编 n在扩展的行内汇编中,可以将C语言表达式指定为汇编指令的操作数

16、,而且不用去管如何将C语言表达式的值读入寄存器,以及如何将计算结果写回C变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可,GCC会自动插入代码完成必要的操作。诀隧彭忘债佑涯付评衣设财痊关宇叶渭谈完菊兹踏爬荷切佣顶鬃壹盖钳唱第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编扩展的行内汇编n使用内嵌汇编,要先编写汇编指令模板,然后将C语言表达式与指令的操作数相关联,并告诉GCC对这些操作有哪些限制条件。例如下面的汇编语句:_asm_violate_(movl%1,%0:=r(result):r(input);n“movl%1,%0”是指令模板;“%0”和“%1”代表指令

17、的操作数,称为占位符,“=r”代表它之后是输入变量且需用到寄存器,指令模板后面用小括号括起来的是C语言表达式,其中input是输入变量,该指令会完成把input的值复制到result中的操作贿嫌墅藐纸境堡液异芭蛰层吉渴躯纂沮悟其污矮候穗祈柳砰滇盾颧怪匹羹第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编扩展的行内汇编n若把刚才的内嵌汇编语句改成如下:_asm_volatile_(movl%1,%0:=m(result):m(input);n只是把“=r”改成了“=m”,“r”改成了“m”,然而在编译这条改过的语句的时候编译器便会报错,因为“r”代表复制的时候借助了寄存器,而“m”则代表

18、直接从内存复制到内存,这样的操作显然是非法的家焉湖摊蹦撅砍把抛拜来肃连何貌阐院暖汁派概惕祭呵变饼闭乾询桩头黍第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编的语法扩展的行内汇编的语法 n内嵌汇编语法如下:_asm_(汇编语句模板:输出部分:输入部分:破坏描述部分);n即格式为asm(statements:output_regs:input_regs:clobbered_regs)记斋黍徘必粒螟精荫凌定樟巳巾灯他恬瘤喇伪粉帐丛甚象霍婿谭伦蓝佩狠第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编的语法扩展的行内汇编的语法n扩展行内汇编共分四个部分:汇编语句模板,输出部分,输入部分

19、,破坏描述部分,各部分使用“:”格开,汇编语句模板必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空,也需要用“:”格开,相应部分内容为空。intmain(void)intdest;intvalue=1;asm(movl%1,%0:=a(dest):c(value):%ebx);printf(%dn,dest);return0;晕价檬隋垂且迪弓仙昂措俄荡溜萄墒窘袍耿懒吩显讲袋交芦烃奴较眉醉白第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编的语法扩展的行内汇编的语法n汇编语句模板汇编语句模板由汇编语句序列组成,语句之间使用“;”、“n”或“nt”分开。指令中的操作数可以使用

20、占位符引用C语言变量,操作数占位符最多10个,名称如下:%0,%1,%9。指令中使用占位符表示的操作数,总被视为long型(4,个字节),但对其施加的操作根据指令可以是字或者字节,当把操作数当作字或者字节使用时,默认为低字或者低字节。对字节操作可以显式的指明是低字节还是次字节。方法是在%和序号之间插入一个字母,“b”代表低字节,“h”代表高字节,例如:%h1。犬讹众予边持摆铭赐纳惭吐仙艰奴究糯詹昂颁酷长喳翠耙芬局莫理灿辑个第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编的语法扩展的行内汇编的语法n输出部分输出部分描述输出操作数,不同的操作数描述符之间用逗号格开,每个操作数描述符由限定

21、字符串和C语言变量组成。每个输出操作数的限定字符串必须包含“=”表示它是一个输出操作数。例如:_asm_volatile_(pushfl;popl%0;cli:=g(x)在这里“x”便是最终存放输出结果的C程序变量,而“=g”则是限定字符串,限定字符串表示了对它之后的变量的限制条件艰办私诊玛蹦菱另阶微疹贮祟洗竿拦卤摊占扁锹仓女抒痉稿看滋膝答腻叁第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编的语法扩展的行内汇编的语法n输入部分输入部分描述输入操作数,不同的操作数描述符之间使用逗号格开,每个操作数描述符同样也由限定字符串和C语言表达式或者C语言变量组成。例:_asm_volatile_

22、(lidt%0:m(real_mode_idt);娟怨旨樱纽磷纹猎锭妖亨庸范爵凡夫挺风盖通静房锨唐侵耸榆外赃叉正蚜第二部分ATT汇编语言第二部分ATT汇编语言扩展的行内汇编的语法扩展的行内汇编的语法n限定字符限定字符便是内嵌汇编中放在引用的C变量之前的字符,它们的作用是指示编译器如何处理其后的C语言变量与指令操作数之间的关系,例如是将变量放在寄存器中还是放在内存中等,常用的如下:限定字符描述a、b、c、d、s、D具体的一个寄存器q、r、A混合的寄存器m、o、V、p内存g、X寄存器或内存I、J、N、i、n立即数=、+操作数类型抑唁糕界介扫谜藐狞悔逆砖枷颜浸得金麓啤孵锅传斑噶坊果硕循擎棱诣懒第二部

23、分ATT汇编语言第二部分ATT汇编语言内嵌汇编示例内嵌汇编示例n例1intmain(void)intresult=2;intinput=1;_asm_volatile_(addl%1,%0:=r(result):r(input);printf(%dn,result);return0;这段内嵌汇编原本的目的是输出1+2=3的结果,也就是将input变量的值与result变量的值相加之后再存入result中。可以看到在汇编语句模板中的%1与%0分别代表input与result变量,而“=r”与“r”则表示两个变量在汇编中应该对应两个寄存器,“=”表示result是输出变量。然而实际运行后发现结果实

24、际上是2。这是为什么呢?裙洼春秆吓恐审侈幌喀尾湿捉深认蓖蔫苗灾滚层方一你社缆柯剖擒呻膳曰第二部分ATT汇编语言第二部分ATT汇编语言内嵌汇编示例内嵌汇编示例n我们用(objdump-j.textS可执行文件名)这样的命令来查看编译生成后的代码发现这段内嵌汇编经GCC翻译后所对应的AT&T汇编是:movl$0x2,0xfffffffc(%ebp)movl$0x1,0xfffffff8(%ebp)movl0xfffffff8(%ebp),%eaxaddl%eax,%eaxmovl%eax,0xfffffffc(%ebp)前两句汇编分别是为result和input变量赋值。input为输入型变量,而

25、且需要放在寄存器中,GCC给它分配的寄存器是%eax,在执行addl之前%eax的内容已经是input的值。读入input后执行addl,显然addl%eax,%eax的值不对。仅彬苛湾和爪懊轰绪否翅嘲伐痘运亨硝助馆技搬傣拘炼盔奏甫高畜柿匪徐第二部分ATT汇编语言第二部分ATT汇编语言内嵌汇编示例内嵌汇编示例n之所以会出现以上的结果是因为:使用“r”限制的输入变量,GCC先分配一个寄存器,然后将值读入寄存器,最后用该寄存器替换占位符使用“r”限制的输出变量,GCC会分配一个寄存器,然后用该寄存器替换占位符,但是在使用该寄存器之前并不将变量值先读入寄存器,GCC认为所有输出变量以前的值都没有用处

26、,不读入寄存器,最后GCC插入代码,将寄存器的值写回变量因为第二条,这样内嵌汇编指令不能奏效,因为在执行addl之前result的值没有被读入寄存器肪邯澜帽若雅潜嗅萨育抡骆思得蛀痴蛹胎估楔马纯疙耻昌秃祁捷岩垃冬皋第二部分ATT汇编语言第二部分ATT汇编语言内嵌汇编示例内嵌汇编示例n修改后的指令如下:intmain(void)intresult=2;intinput=1;_asm_volatile_(addl%2,%0:=r(result):r(result),m(input);printf(%dn,result);return0;这段内嵌汇编所对应的AT&T汇编如下:movl$0x2,0xff

27、fffffc(%ebp)movl$0x1,0xfffffff8(%ebp)movl0xfffffffc(%ebp),%eaxaddl0xfffffff8(%ebp),%eaxmovl%eax,0xfffffffc(%ebp)匣募麻粱搭胚庐聂赶积革爪支峰蔗岳仁砒茧督铺垫贿枫紫脏卸龙凰寂沏缴第二部分ATT汇编语言第二部分ATT汇编语言内嵌汇编示例内嵌汇编示例n上面的代码应该可以正常工作,因为我们知道%0和%1都和result相关,应该使用同一个寄存器,而且事实上在实际结果中GCC也确实是使用了同一个寄存器eax,所以可以得到正确的结果3。但是为了更保险起见,为了确保%0与%1与同一个寄存器关联我们

28、可以使用如下的方法:intmain(void)intresult=2;intinput=1;_asm_volatile_(addl%2,%0:=r(result):0(result),m(input);printf(%dn,result);return0;在上面的程序中我们使用了占位符“0”表示%0与%1是使用的同一个寄存器,这样就确保了程序的正确性。猿病荣侨健凌斯谓酉颓隙哪白神麻宛翠些缺称瘴巾相海刷抹佐梳肃祝皱终第二部分ATT汇编语言第二部分ATT汇编语言内嵌汇编示例内嵌汇编示例n例2intmain(void)intcount=3;intvalue=1;intbuf10;asm(cldntr

29、epntstosl:c(count),a(value),D(buf);printf(%d%d%dn,buf0,buf1,buf2);经GCC翻译后所对应的AT&T汇编是:movl0xfffffff4(%ebp),%ecxmovl0xfffffff0(%ebp),%eaxlea0xffffffb8(%ebp),%edicldrepzstos%eax,%es:(%edi)在这里count、value和buf是三个输入变量,它们都是C程序中的变量,“c”、“a”和“D”表示这三个输入值分别被存放入寄存器ECX、EAX与EDI;“cldrepstosl”是需要执行的汇编指令;而“%ecx、%edi”表

30、示这两个寄存器在指令中被改变了。这段内嵌汇编要做的就是向buf中写count个value值。回墅拎蹄靠陆逾橇稼端狠野箔厉乏链抨糯敖恰茧宿侣淆侈汤菩卉臀咏宏爬第二部分ATT汇编语言第二部分ATT汇编语言内嵌汇编示例内嵌汇编示例n例3intmain(void)intinput,output,temp;input=1;_asm_volatile_(movl$0,%eax;ntmovl%eax,%1;ntmovl%2,%eax;ntmovl%eax,%0;nt:=m(output),=m(temp):r(input):eax);printf(%d%dn,temp,output);return0;庸为睹

31、肌卑低执啼缴幸将剩闽糜阑陀毫未氢彦戒寂卷室喜诛帧伴如雀雨晴第二部分ATT汇编语言第二部分ATT汇编语言内嵌汇编示例内嵌汇编示例n这段内嵌汇编经由GCC转化成的汇编代码如下:movl$0x1,0xfffffffc(%ebp)mov0xfffffffc(%ebp),%edxmov$0x0,%eaxmov%eax,0xfffffff4(%ebp)mov%edx,%eaxmov%eax,0xfffffff8(%ebp)可以看到,由于input、output、temp都是程序局部整型数变量,于是它们实际上是存放在堆栈中的,也就是内存中的某个部分。其中output和temp是输出变量,而且“=m”表明它们应该在内存中,input是输入变量,“r”表明它应存放在寄存器中,于是首先把1存入input变量,然后将变量的值复制给了edx寄存器,在这里我们可以看到内嵌汇编中使用了破环描述符“eax”,这是告诉编译器在程序中eax寄存器已被使用,这样编译器为了避免冲突会将输入变量存放在除eax以外别的寄存器中,如像我们最后看到的edx寄存器。邻岗料缔醛粉泄梳果味荐枪浸秋匙言丛昼铅郴本跪心至橱镑懊裂柄荷咏脾第二部分ATT汇编语言第二部分ATT汇编语言

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 资格认证/考试 > 自考

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号