GCC嵌入汇编代码讲解Word格式.docx

上传人:b****1 文档编号:1004937 上传时间:2023-04-30 格式:DOCX 页数:23 大小:32.46KB
下载 相关 举报
GCC嵌入汇编代码讲解Word格式.docx_第1页
第1页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第2页
第2页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第3页
第3页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第4页
第4页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第5页
第5页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第6页
第6页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第7页
第7页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第8页
第8页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第9页
第9页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第10页
第10页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第11页
第11页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第12页
第12页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第13页
第13页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第14页
第14页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第15页
第15页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第16页
第16页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第17页
第17页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第18页
第18页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第19页
第19页 / 共23页
GCC嵌入汇编代码讲解Word格式.docx_第20页
第20页 / 共23页
亲,该文档总共23页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

GCC嵌入汇编代码讲解Word格式.docx

《GCC嵌入汇编代码讲解Word格式.docx》由会员分享,可在线阅读,更多相关《GCC嵌入汇编代码讲解Word格式.docx(23页珍藏版)》请在冰点文库上搜索。

GCC嵌入汇编代码讲解Word格式.docx

of 

ecx 

to 

eax 

*/ 

2.__asm__("

movb 

%bh 

(%eax)"

/*moves 

byte 

from 

bh 

memory 

pointed 

by 

YoumighthavenoticedthathereI’veused 

asm 

and 

__asm__.Botharevalid.Wecanuse__asm__ 

ifthekeywordasm 

conflictswithsomethinginourprogram.Ifwehavemorethanoneinstructions,wewriteoneperlineindoublequotes,andalsosuffixa’\n’and’\t’totheinstruction.Thisisbecausegccsendseachinstructionasastringtoas(GAS)andbyusingthenewline/tabwesendcorrectlyformattedlinestotheassembler.

可能注意到了这里使用了asm和__asm__.都是有效的.如果关键字asm在程序中有冲突,则可以使用__asm__.如果我们需要使用一条以上的汇编指令,我们应该每条占用一行,用双引号括起,并加上'

\n'

和'

\t'

后缀.这是因为gcc把用字符串的格式把汇编指令传给as(GAS),然后利用换行符,把它们转换成正确的汇编格式.

1.__asm__ 

("

%eax, 

%ebx\n\t"

2. 

"

$56, 

%esi\n\t"

3. 

%ecx, 

$label(%edx,%ebx,$4)\n\t"

4. 

%ah, 

(%ebx)"

Ifinourcodewetouch(ie,changethecontents)someregistersandreturnfromasmwithoutfixingthosechanges,somethingbadisgoingtohappen.ThisisbecauseGCChavenoideaaboutthechangesintheregistercontentsandthisleadsustotrouble,especiallywhencompilermakessomeoptimizations.ItwillsupposethatsomeregistercontainsthevalueofsomevariablethatwemighthavechangedwithoutinformingGCC,anditcontinueslikenothinghappened.Whatwecandoiseitherusethoseinstructionshavingnosideeffectsorfixthingswhenwequitorwaitforsomethingtocrash.Thisiswherewewantsomeextendedfunctionality.Extendedasmprovidesuswiththatfunctionality.

如果我们的代码里使用了寄存器,并且在返回的时候没有还原它,这将有坏的情况发生.因为GCC并不知道寄存器的值改变了,特别是编译器对代码进行优化的时候.编译器会认为,那些存放变量的寄存器,我们并没有改变它,然后继续自己的优化.为了避免这种情况,要么,我们不改变寄存器的值,要么,汇编函数返回之前,还原寄存器使用前的值,或者等着代码崩溃(waitforsomethingtocrash).正是由于存在这样的问题,我们需要使用"

ExtendedAsm"

.它将提供给我们扩展功能,解决上边的问题.

5. 

ExtendedAsm.

Inbasicinlineassembly,wehadonlyinstructions.Inextendedassembly,wecanalsospecifytheoperands.Itallowsustospecifytheinputregisters,outputregistersandalistofclobberedregisters.Itisnotmandatorytospecifytheregisterstouse,wecanleavethatheadachetoGCCandthatprobablyfitintoGCC’soptimizationschemebetter.Anywaythebasicformatis:

在基本嵌入汇编格式中,我们只使用了指令.在扩展汇编中,我们还可以指定更多操作.它允许我们指定输入寄存器,输出寄存器和变化表(clobberlist). 

我们并不一定要指定使用哪些寄存器.我们可以把这件事情交给GCC去做. 

扩展汇编的格式如下:

1.asm 

( 

assembler 

template 

:

output 

operands 

optional 

input 

list 

clobbered 

registers 

5. 

Theassemblertemplateconsistsofassemblyinstructions.Eachoperandisdescribedbyanoperand-constraintstringfollowedbytheCexpressioninparentheses.Acolonseparatestheassemblertemplatefromthefirstoutputoperandandanotherseparatesthelastoutputoperandfromthefirstinput,ifany.Commasseparatetheoperandswithineachgroup.Thetotalnumberofoperandsislimitedtotenortothemaximumnumberofoperandsinanyinstructionpatterninthemachinedescription,whicheverisgreater.

这个模板由若干条汇编指令组成,每个操作数(括号里C语言的变量)都有一个限制符(“”中的内容)加以描述.冒号用来分割输入的操作和输出的操作.如果每组内有多个操作数,用逗号分割它们. 

操作数最多为10个,或者依照具体机器而异.

Iftherearenooutputoperandsbutthereareinputoperands,youmustplacetwoconsecutivecolonssurroundingtheplacewheretheoutputoperandswouldgo.

如果没有输出操作,但是又有输入,你必须使用连续两个冒号,两个连续冒号中无内容,表示没有输出结果的数据操作.

Example:

cld\n\t"

rep\n\t"

stosl"

no 

c"

(count), 

a"

(fill_value), 

D"

(dest) 

6. 

%ecx"

 

%edi"

7. 

Now,whatdoesthiscodedo?

Theaboveinlinefillsthe 

fill_value 

count 

timestothelocationpointedtobytheregisteredi.Italsosaystogccthat,thecontentsofregisterseax 

andedi 

arenolongervalid.Letusseeonemoreexampletomakethingsmoreclearer.

上面这段代码做了什么?

这段内嵌汇编把fill_value,count装入寄存器,同时告知GCC,clobberlist目录中的寄存器eax,edi,已经改变. 

我们来看下一个例子:

1.int 

a=10, 

b;

2.asm 

%1, 

%%eax;

%%eax, 

%0;

=r"

(b) 

r"

(a) 

register 

Herewhatwedidiswemadethevalueof’b’equaltothatof’a’usingassemblyinstructions.Somepointsofinterestare:

代码目的是让'

b'

的值与'

a'

的值相等. 

∙"

b"

istheoutputoperand,referredtoby%0and"

istheinputoperand,referredtoby%1.

isaconstraintontheoperands.We’llseeconstraintsindetaillater.Forthetimebeing,"

saystoGCCtouseanyregisterforstoringtheoperands.outputoperandconstraintshouldhaveaconstraintmodifier"

="

.Andthismodifiersaysthatitistheoutputoperandandiswrite-only.

∙Therearetwo%’sprefixedtotheregistername.ThishelpsGCCtodistinguishbetweentheoperandsandregisters.operandshaveasingle%asprefix.

∙Theclobberedregister%eaxafterthethirdcolontellsGCCthatthevalueof%eaxistobemodifiedinside"

asm"

soGCCwon’tusethisregistertostoreanyothervalue.

∙'

是要输出的数据,%0也指它。

'

是输入的数据,%1也指它。

r'

是对操作数的约束。

呆会在详细了解。

暂时这样理解,‘r’告诉GCC选择一个可用的寄存器来保存这个操作数。

输出操作数,应该使用‘=’,表示这个数据只写。

∙双%%前缀,指明这是一个寄存器名。

单%指明操作数。

这帮组GCC辨别操作数和寄存器。

∙第三个冒号后边,这个变化表(clobberlist)里的寄存器%eax,告诉gcc声明的寄存器值已经改变,这样,GCC不会在其他地方使用这个寄存器了。

Whentheexecutionof"

iscomplete,"

willreflecttheupdatedvalue,asitisspecifiedasanoutputoperand.Inotherwords,thechangemadeto"

inside"

issupposedtobereflectedoutsidethe"

.

当这段汇编代码执行完毕,'

变量将会存储这个结果,,正如例子里声明这个变量为输出。

换句话说,'

用来反映汇编程序里值的变化。

Nowwemaylookeachfieldindetail.

现在,深入的理解每一块,看看细节。

5.1AssemblerTemplate.

TheassemblertemplatecontainsthesetofassemblyinstructionsthatgetsinsertedinsidetheCprogram.Theformatislike:

eithereachinstructionshouldbeenclosedwithindoublequotes,ortheentiregroupofinstructionsshouldbewithindoublequotes.Eachinstructionshouldalsoendwithadelimiter.Thevaliddelimitersarenewline(\n)andsemicolon(;

).’\n’maybefollowedbyatab(\t).Weknowthereasonofnewline/tab,right?

.OperandscorrespondingtotheCexpressionsarerepresentedby%0,%1...etc.

这个汇编模板包含一套完整的汇编指令,帮助在c语言内嵌入汇编语言。

具体格式如下:

每条指令应该加上双括号,或者给整套汇编指令加上双括号(如,最后一个例子)。

每条指令结尾都应加上结束符,合法的结束符有(\n)和(;

),或许还应该在\n后边加上一个\t,我们应该了解原因吧?

括号里的若干操作数,依次对应%0,%1。

等。

5.2Operands.

Cexpressionsserveasoperandsfortheassemblyinstructionsinside"

.Eachoperandiswrittenasfirstanoperandconstraintindoublequotes.Foroutputoperands,there’llbeaconstraintmodifieralsowithinthequotesandthenfollowstheCexpressionwhichstandsfortheoperand.ie,

constraint"

(Cexpression)isthegeneralform.Foroutputoperandsanadditionalmodifierwillbethere.Constraintsareprimarilyusedtodecidetheaddressingmodesforoperands.Theyarealsousedinspecifyingtheregisterstobeused.

内嵌的汇编指令需要C变量为其提供一个操作数,这个操作数应加上括号。

以输出操作为例,首先会有一个限制符,然后跟上C变量,运算结果将存入这个变量。

双引号内的“限制符”是一个规定的格式。

在输出操作中,这个限制符会额外多一个符号(=)。

限制符主要用来决定操作数的寻址方式。

同时还可指定使用某一个寄存器。

Ifweusemorethanoneoperand,theyareseparatedbycomma.

Intheassemblertemplate,eachoperandisreferencedbynumbers.Numberingisdoneasfollows.Ifthereareatotalofnoperands(bothinputandoutputinclusive),thenthefirstoutputoperandisnumbered0,continuinginincreasingorder,andthelastinputoperandisnumberedn-1.Themaximumnumberofoperandsisaswesawintheprevioussection.

Outputoperandexpressionsmustbelvalues.Theinputoperandsarenotrestrictedlikethis.Theymaybeexpressions.Theextendedasmfeatureismostoftenusedformachineinstructionsthecompileritselfdoesnotknowasexisting;

-).Iftheoutputexpressioncannotbedirectlyaddressed(forexample,itisabit-field),ourconstraintmustallowaregister.Inthatcase,GCCwillusetheregisterastheoutputoftheasm,andthenstorethatregistercontentsintotheoutput.

Asstatedabove,ordinaryoutputoperandsmustbewrite-only;

GCCwillassumethatthevaluesintheseoperandsbeforetheinstructionaredeadandneednotbegenerated.Extendedasmalsosupportsinput-outputorread-writeoperands.

如果我们不止一个操作(有输入,有输出),就必须使用冒号将他们分开。

在标准汇编模板中,每个操作数会有一个Number与之对应。

如果我们一共使用了n个操作数,那么输出操作里的第一个操作数就排0号,之后递增,所以最后一个输出操作的操作数编号为n-1。

操作数的最多个数,前边已经提到过了。

(一般最多10个或者某些机器指令支持更多)

输出操作的表达式必须是数值,输入操作没有这个限制,他可能是表达式。

扩展汇编常常用于实现机器平台自身特殊的指令,编译器可能并不能识别他们:

-)。

如果输出表达式不能直接被寻址(比如,他是一个位字段),我们就应该使用“限制符”指定一个寄存器。

这样,GCC会使用此寄存器存储输出结果,然后再将寄存器的值存入输出操作数。

Sonowweconcentrateonsomeexamples.Wewanttomultiplyanumberby5.Forthatweusetheinstructionlea.

我们现在分析几个例子。

我们想给一个数乘以5。

因此,我们使用lea指令:

(汇编语句leal(r1,r2,4),r3语句表示r1+r2*4→r3。

这个例子可以非常快地将x乘5。

leal 

(%1,%1,4), 

%0"

(five_times_x) 

(x) 

Hereourinputisin’x’.Wedidn’tspecifytheregistertobeused.GCCwillchoosesomeregisterforinput,oneforoutputanddoeswhatwedesired.Ifwewanttheinputandoutputtoresideinthesameregister,wecaninstructGCCtodoso.Hereweusethosetypesofread-writeoperands.Byspecifyingproperconstraints,herewedoit.

这里,输入一个变量x,我们并没指定特定的寄存器来存储它,GCC会选择一个(“r”表示gcc选择)。

如我们所要求的,gcc会自动选择两个寄存器,一个给input,一个给output。

如果我们想给input和output指定同一个寄存器,我们可以要求GCC这样做(通过更改“限制符”内容)。

(%0,%0,4), 

0"

Nowtheinputandoutputoperandsareinthesameregister.Butwedon’tknowwhichregister.Nowifwewanttospecifythatalso,thereisaway.

上例,我们就让input和output使用同一个寄存器,但是不知道具体哪一个。

(如果输入操作的限制符为0或为空,则说明使用与相应输出一样的

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 临时分类 > 批量上传

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2