Обща форма
В програмата тялото на функцията се изпълнява чрез извикване на функцията и процесът е подобен на този при извиквания на подпрограма на други езици.
В езика общата форма на функцията се нарича:
Име на функция (действителен списък с параметри)
Whencallingafunctionwithoutparameters,thereisnoactualparameterlist..Theparametersintheactualparametertablecanbeconstants,variables,orotherstructureddataandexpressions.Separateeachactualparameterwithacomma.
Потребителско пространство (потребителски режим) и пространство на ядрото (режим на ядро)
Пространството на процесите на операционната система може да бъде разделено на потребителско пространство и пространство на ядрото, което изисква различни разрешения за изпълнение. Извикването на функцията изпълнява потребителско пространство.
Включително съдържание
Функционален израз
Функциите се появяват като изрази като изрази на един елемент и върнатите стойности на функциите участват в изчисляването на изразите. Този метод изисква функцията да има върната стойност. Например: z=max(x,y) е израз за присвояване, който присвоява върната променлива на zmax.
Израз на функция
Общата форма на извикване на функция плюс точка и запетая представлява израз на функция. Например: printf("%d",a);scanf("%d",&b);всички функции за извикване във формата на изрази на функция.
FunctionArguments
Thefunctionappearsastheactualparameterofanotherfunctioncall.Inthiscase,thereturnvalueofthefunctionistransmittedasanactualparameter,sothefunctionmusthaveareturnvalue.Forexample:printf("%d",max(x,y));Thatis,thereturnvalueofthemaxcallisusedastheactualparameteroftheprintffunction.Anotherissuethatshouldbepaidattentiontoinfunctioncallsistheorderofevaluation.Theso-calledevaluationorderreferstowhetherthequantitiesintheactualparametertableareusedfromlefttorightorfromrighttoleft.Inthisregard,theregulationsofeachsystemarenotnecessarilythesame.Ithasbeenmentionedintheintroductionoftheprintffunction,andIwillemphasizeitagainfromtheperspectiveoffunctioncalls.
[Пример]
главен()
{inti=8;printf("%d\n%d\n%d\n%d\n",++i,--i,i++,i--);}
Ако се оценява отдясно наляво. Резултатът от изпълнението трябва да бъде:
8
7
7
8
Например, в израза printf++i,--i,i++,i--оценка от ляво надясно, трябва да има резултат:
9
8
8
9
Itshouldbenotedthatwhetheritisevaluatedfromlefttorightorfromrighttoleft,theoutputorderisthesame,thatis,theoutputorderisalwaysTheorderoftheactualparametersisthesameasintheactualparameterlist.SinceTurboCiscurrentlyevaluatedfromrighttoleft,theresultis8,7,7,8.Ifyoustilldon’tunderstandtheabovequestions,youwillunderstandafteratryonthecomputer.
Declarationandfunctionprototypeofthecalledfunction
Beforecallingafunctioninthemaincallingfunction,thecalledfunctionshouldbeexplained(declared),whichisthesameasbeforeusingvariables.Thevariabledescriptionisthesame.Thepurposeofexplainingthecalledfunctioninthecallingfunctionistomakethecompilersystemknowthetypeofthereturnvalueofthecalledfunction,sothatthereturnvaluecanbeprocessedaccordinglyinthecallingfunctionaccordingtothistype.
Общата форма:
Определянето на типа се нарича име на функция (тип параметър, тип параметър...);
Или:
Определянето на типа се нарича име на функция (тип, тип...);
Thetypeandnameoftheformalparameteraregivenintheparentheses,oronlythetypeoftheformalparameterisgiven.Thisfacilitateserrordetectionbythecompilersystemtopreventpossibleerrors.
Например, описанието на максималната функция в основната функция е:
intmax(inta,intb);
Написано:
intmax(int,int);
TheClanguagealsostipulatesthatthefunctiondescriptionofthecalledfunctioninthecallingfunctioncanbeomittedinthefollowingsituations.
1)Ifthereturnvalueofthecalledfunctionisanintegerorcharactertype,youcancallthecalledfunctiondirectlywithoutexplainingit.Atthistime,thesystemwillautomaticallytreatthereturnvalueofthecalledfunctionasaninteger.ThisisthecasewhenthefunctionsisnotdescribedinthemainfunctionofExample8.2anditiscalleddirectly.
2)Whenthefunctiondefinitionofthecalledfunctionappearsbeforethecallingfunction,thecallingfunctioncanalsobecalleddirectlywithoutfurtherexplainingthecalledfunction.Forexample,inExample8.1,thedefinitionofthefunctionmaxisplacedbeforethemainfunction,sothefunctiondescriptionofthemaxfunctioncanbeomittedinthemainfunctionintmax(inta,intb).
3)Ifthetypeofeachfunctionisspecifiedoutsidethefunctionbeforethedefinitionofallthefunctions,theninthesubsequentcallingfunctions,thecalledfunctioncannolongerbedescribed.Forexample:
charstr(inta);
floatf(floatb);
главен()
{……}
charstr(inta)
{……)
floatf(floatb)
{……}
Thefirstandsecondlineshavepre-explainedthestrfunctionandtheffunction.Therefore,thestrandffunctionscanbecalleddirectlyinthefollowingfunctionswithoutfurtherexplanation.
4)Thecallofthelibraryfunctiondoesnotneedtobeexplained,buttheheaderfileofthefunctionmustbeincludedinthefrontofthesourcefilewiththeincludecommand.
Nestedcall
NestedfunctiondefinitionsarenotallowedinClanguage.Therefore,thefunctionsareparallel,andthereisnoproblemoftheupperlevelfunctionandthenextlevelfunction.ButtheClanguageallowsacalltoanotherfunctiontoappearinthedefinitionofafunction.Inthisway,nestedcallsoffunctionsappear.Thatis,otherfunctionsarecalledinthecalledfunction.Thisissimilartothenestingofsubroutinesinotherlanguages.Therelationshipcanberepresentedasshowninthefigure.
Thefigureshowsatwo-levelnestingsituation.Theexecutionprocessis:whenthestatementthatcallsfunctionainthemainfunctionisexecuted,functionaisswitchedto,whenfunctionbiscalledinfunctiona,functionbisswitchedtoexecution,andfunctionbisexecutedtoreturntothebreakpointoffunctionatocontinueExecute,theexecutionoftheafunctioniscompleteandreturntothebreakpointofthemainfunctiontocontinueexecution.
[Пример]Изчислява=2∧2!+3∧2!
Thisquestioncanwritetwofunctions,oneisthefunctionf1usedtocalculatethesquarevalue,andtheotherisThefunctionf2usedtocalculatethefactorialvalue.Themainfunctionfirstadjustsf1tocalculatethesquarevalue,andthentakesthesquarevalueinf1astheactualparameter,callsf2tocalculatethefactorialvalue,andthenreturnstof1,thenreturnstothemainfunction,andcalculatesthecumulativesumintheloopprogram.
longf1(intp)
{intk;
longr;
longf2(int);
k=p*p;
r=f2(k);
връщане;}
longf2(intq)
p>{longc=1;
inti;
за(i=1;i<=q;i++)
c=c*i;
връщане;}
главен()
{inti;
longs=0;
p>за(i=2;i<=3;i++)
s=s+f1(i);
printf("\ns=%ld\n",s);}
Intheprogram,thefunctionsf1andf2arebothlongintegers,whicharedefinedbeforethemainfunction,sothereisnoneedtoexplainf1andf2inthemainfunction.Inthemainprogram,theexecutionloopprogramsequentiallycallsthevalueofiastheactualparametertocallthefunctionf1toobtainthevalueofi2.Inf1,acalltofunctionf2occursagain.Atthistime,thevalueofi2isusedasanactualparametertoadjustf2,andthecalculationofi2!iscompletedinf2.Afterf2isexecuted,theCvalue(iei2!)isreturnedtof1,andthenf1returnstothemainfunctiontoachieveaccumulation.Sofar,therequirementoftheproblemisrealizedbythenestedcallofthefunction.Becausethevalueisverylarge,thetypesoffunctionsandsomevariablesaredeclaredaslongintegers,otherwiseitwillcausecalculationerrors.
Действително изпълнение
Pointerregister
EBP
EBPistheso-calledframepointer,pointingtothecurrentactivityAbovetherecord(thebottomofthepreviousactivityrecord)
ESP
ESPistheso-calledstackpointer,whichpointstothebottomofthecurrentactivityrecord(bottomAnactivityrecordtobeinsertedatthetop)
Thevalueofthesetwopointersspecifiesthepositionofthecurrentactivityrecord
Предаване на параметри
Натискане на параметрите на функцията Stack:moveax,dwordptr[n];(nisaпараметъраргумент)
бутаща ос
Операция
Извикването на функцията ще изпълни следните операции:
⒈Избутайте указателя на рамката в стека:pushebp
⒉направете точката на рамката равна на указателя на стека:movebp,esp
⒊makethestackpointerdecrement,Thememoryaddressobtainedbysubtractionshouldbeableto(enough)beusedtostorethelocalstateofthecalledfunction:subesp,0CCh
Забележка: 0CC е 0xCC, което варира в зависимост от конкретната функция.
Passinsavestate
pushebx;savethevalueofebxregister
pushesi;запазете стойността на fesiregister
pushedi;Запазете стойността на ediregister
Зареден
leaedi,[ebp-0CCh];0c еразмерът на текущия активен запис.
EDI е индексният регистър на местоназначението.
Restoretheincomingsavestate
00411417popedi
00411418попеси
popebx
stackMovethepointeruptorestorespace
addesp,0CCh
Function returnstoreleasespace
Когато функцията се върне, компилаторът и хардуерът ще изпълнят следните операции:
⒈Направете точката на стека равна на указателя на рамката:movesp,ebp
⒉Извадете стария указател на рамка от стека:popebp
⒊Връщане: ret
Пример1
;voidfunction(intn);{pushebp
movebp, особено
subesp,0CCh
pushebx
пушеси
бутане
leaedi,[ebp-0CCh]
movecx,33ч
moveax,0CCCCCCCCh
repstosdwordptres:[edi]
;chara=1;
movbyteptr[a],1
;ако(n==0)връщане;
cmpdwordptr[n],0
jnefunction+2Ah(4113CAh)
jmpfunction+77h(411417h)
;printf("%d\t(0x%08x)\n",n,&n);
movesi, особено
leaeax,[n]
бутаща ос
movecx,dwordptr[n]
pushecx
pushoffsetstring"%d\t(0x%08x)\n"(415750h)
callwordptr[__imp__printf(4182B8h)]
addesp,0Ch
cmpesi, особено
обадете се на @ILT+305(__RTC_CheckEsp)(411136h)
;функция(n-1);
moveax,dwordptr[n]
подос,1
бутаща ос
функция за извикване (411041h)
addesp,4
;printf("----%d\t(0x%08x)\n",n,&n);
movesi, особено
leaeax,[n]
бутаща ос
movecx,dwordptr[n]
pushecx
pushoffsetstring"----%d\t(0x%08x)\n"(41573Ch)
callwordptr[__imp__printf(4182B8h)]
addesp,0Ch
cmpesi, особено
обадете се на @ILT+305(__RTC_CheckEsp)(411136h);}
попеди
попеси
popebx
addesp,0CCh
cmpebp, особено
обадете се на @ILT+305(__RTC_CheckEsp)(411136h)
movesp,ebp
popebp
остан
Пример2
117:bR=t1(p);
Кодът на сглобяването е следният:
00401FB8movecx,dwordptr[ebp-8];поставете параметъра в регистъра ecx
00401FBBpushecx;параметърът в стека
00401FBCcall@ILT+10(t1)(0040100f);Functioncall,адресът на следващия ред00401FC1е избутан в стека
00401FC1addesp,4;Функцията връща, указателят на стека е увеличен с 4 и е възстановен до стойността на 00401FB8
00401FC4movdwordptr[ebp-10h],eax;Вземете върнатата от функцията стойност на езика от високо ниво от meax и поставете в променливатаbR
Функцията1 е следната:
125:BOOLt1(void*p)
126:{
00402030pushebp;ebpintothestack
00402031movebp,esp;ebppointstothetopofthestackonthtime
00402033subesp,44h;espнамалява с една стойностиосвобождаваобласт за съхранение
p>00402036pushebx;Поставетестойноститена трите регистърав стека,за да можете да го използвате въвфункцията
00402037pushesi;
00402038pushedi;
00402039leaedi,[ebp-44h];
0040203Cmovecx,11h;
00402041moveax,0CCCCCCCCh;
00402046repstosdwordptr[edi];
127:int*q=(int*)p;;
00402048moveax,dwordptr[ebp+8];ebp+8pointstofunctioninputНай-ниския бит адреснапараметъра;
;ако се bp+4, сочи към най-ниския бит от адреса за връщане на функцията00401FC1, стойността е C1
0040204Bmovdwordptr[ebp-4],eax;
128:връщане0;
0040204Exoreax,eax;Върнатата стойност е поставена в регистъраeax
129:}
00402050popedi;Три регистъра излизат от стека
00402051попеси;
00402052popebx;
00402053movesp,ebp;esprestore
00402055popebp;ebppизскача от стека и стойността му е възстановена
00402056ret;Връщане към адреса на кода, съхранен в горната част на стека в този момент: 00401FC1
;soifyouareunluckyIfthereturnaddressismodified,theprogramwillbeunexpected
Горният код за сглобяване е компилиран от VC++6.0.
ThesituationofthestackaftertheEBPisputintothestack:
Нисък и висок
↓↓
Стек с адреси на паметта
┆┆
0012F600├───────┤←edi=0012F600
││
0012F604├─┄┄┄┄─┤
││
││
┆44hspace┆
┆┆
││
││
0012F640├─┄┄┄┄─┤
││
0012F644├───────┤←Ebpis е назначен да сочи към това устройство, в този моментebp=0012F644
│ACF61200│ebpis, присвоен на стойността преди
0012F648├─────────┤
│C11F4000│Обратен адрес
0012F64C├─────────┤←ebp+8
│A0F61200│Стойността на функционалния параметърp;
0012F650├──────────┤
││
├────────┤
┆┆
Note:Thememorystoragespacestackisarrangedfromhightolow,andtheaddressmarkedontheleftisthelowestaddressofthestorageunitatthebottomright.Forexample,0012F644pointstotheACbyteof0012F6AC,andACisatthetopofthestack.Thecontentinthememoryinthefigureiswrittenfromlowtohigh,"ACF61200"=0x0012F6AC
Обяснение
(1)Acprogramiscomposedofoneormoreprogrammodules,Eachprogrammoduleasasourceprogramfile.Forlargerprograms,yougenerallydon'twanttoputallthecontentinonefile,butputtheminseveralsourcefiles,andacprogramiscomposedofseveralsourceprogramfiles.Thismakesiteasytowriteandcompileseparately,andimprovedebuggingefficiency.Asourceprogramfilecanbesharedbymultiplecprograms.
(2)Asourceprogramfileiscomposedofoneormorefunctionsandotherrelatedcontent(suchasinstructions,datadeclarationsanddefinitions,etc.).Asourceprogramfileisacompilationunit,andthesubprogramiscompiledintheunitofthesourceprogramfile,notintheunitofthefunction.
(3)Theexecutionofthecprogramstartsfromthemainfunction.Ifyoucallotherfunctionsinthemainfunction,theprocessreturnstothemainfunctionafterthecall,andthewholeprogramendsinthemainfunction.
(4)Allfunctionsareparallel,thatis,whendefiningfunctions,theyareperformedseparatelyandareindependentofeachother.Afunctionisnotsubordinatetoanotherfunction,thatis,functionscannotbenesteddefinitions.Functionscancalleachother,butcannotcallthemainfunction.Themainfunctioniscalledbytheoperatingsystem.
(5) От гледна точка на потребителя има два вида функции
a:libraryfunctions,whichareprovidedbythesystem,andusersdonotneedtodefinethembythemselves,butcanusethemdirectly.Itshouldbenotedthatthenumberandfunctionsoflibraryfunctionsprovidedbydifferentclanguagecompilationsystemswillbesomewhatdifferent,ofcourse,manybasicfunctionsarecommon.
b: Дефинирана от потребителя функция. Това е функция, която отговаря на специфичните нужди на потребителите.
(6) От формата на функциите функциите са разделени на две категории.
a: Функция без параметри. Функциите без параметри не могат да връщат обратно или да не връщат функционални стойности, но обикновено има повече функционални стойности, които не връщат обратно.
b:Functionwithparameters.Whencallingafunction,thecallingfunctionpassesdatatothecalledfunctionthroughparameterswhencallingthecalledfunction.Undernormalcircumstances,afunctionvaluewillbeobtainedwhenthecallingfunctionisexecuted,whichcanbeusedbythecallingfunction.