Sie sind auf Seite 1von 211

Chapter2:ComputerArchitecture

Beforelearninghowtoprogram,youneedtofirstunderstandhowa
computerinterpretsprograms.Youdon'tneedadegreeinelectrical
engineering,butyouneedtounderstandsomebasics.
Moderncomputerarchitectureisbasedoffofanarchitecturecalled
theVonNeumannarchitecture,namedafteritscreator.TheVon
Neumannarchitecturedividesthecomputerupintotwomainparts
theCPU(forCentralProcessingUnit)andthememory.This
architectureisusedinallmoderncomputers,includingpersonal
computers,supercomputers,mainframes,andevencellphones.

StructureofComputerMemory
Tounderstandhowthecomputerviewsmemory,imagineyourlocalpost
office.TheyusuallyhavearoomfilledwithPOBoxes.Theseboxes
aresimilartocomputermemoryinthateacharenumberedsequencesof
fixedsizestoragelocations.Forexample,ifyouhave256megabytes
ofcomputermemory,thatmeansthatyourcomputercontainsroughly
256millionfixedsizestoragelocations.Or,touseouranalogy,256
millionPOBoxes.Eachlocationhasanumber,andeachlocationhas
thesame,fixedlengthsize.ThedifferencebetweenaPOBoxand
computermemoryisthatyoucanstorealldifferentkindsofthings
inaPOBox,butyoucanonlystoreasinglenumberinacomputer
memorystoragelocation.

MemorylocationsarelikePOBoxes
Youmaywonderwhyacomputerisorganizedthisway.Itisbecauseit
issimpletoimplement.Ifthecomputerwerecomposedofalotof

differentlysizedlocations,orifyoucouldstoredifferentkindsof
datainthem,itwouldbedifficultandexpensivetoimplement.
Thecomputer'smemoryisusedforanumberofdifferentthings.All
oftheresultsofanycalculationsarestoredinmemory.Infact,
everythingthatis"stored"isstoredinmemory.Thinkofyour
computerathome,andimaginewhatallisstoredinyourcomputer's
memory.
Thelocationofyourcursoronthescreen
Thesizeofeachwindowonthescreen
Theshapeofeachletterofeachfontbeingused
Thelayoutofallofthecontrolsoneachwindow
Thegraphicsforallofthetoolbaricons
Thetextforeacherrormessageanddialogbox
Thelistgoesonandon...
Inadditiontoallofthis,theVonNeumannarchitecturespecifies
thatnotonlycomputerdatashouldliveinmemory,buttheprograms
thatcontrolthecomputer'soperationshouldlivethere,too.In
fact,inacomputer,thereisnodifferencebetweenaprogramanda
program'sdataexcepthowitisusedbythecomputer.Theyareboth
storedandaccessedthesameway.

TheCPU
Sohowdoesthecomputerfunction?Obviously,simplystoringdata
doesn'tdomuchhelpyouneedtobeabletoaccess,manipulate,and
moveit.That'swheretheCPUcomesin.
TheCPUreadsininstructionsfrommemoryoneatatimeandexecutes
them.Thisisknownasthe
fetchexecutecycle.
TheCPUcontainsthe
followingelementstoaccomplishthis:
ProgramCounter
InstructionDecoder
Databus
Generalpurposeregisters
Arithmeticandlogicunit
The
programcounter
isusedtotellthecomputerwheretofetchthe
nextinstructionfrom.Wementionedearlierthatthereisno
differencebetweenthewaydataandprogramsarestored,theyare
justinterpreteddifferentlybytheCPU.Theprogramcounterholds
thememoryaddressofthenextinstructiontobeexecuted.TheCPU
beginsbylookingattheprogramcounter,andfetchingwhatever
numberisstoredinmemoryatthelocationspecified.Itisthen

passedontothe
instructiondecoder
whichfiguresoutwhatthe
instructionmeans.Thisincludeswhatprocessneedstotakeplace
(addition,subtraction,multiplication,datamovement,etc.)andwhat
memorylocationsaregoingtobeinvolvedinthisprocess.Computer
instructionsusuallyconsistofboththeactualinstructionandthe
listofmemorylocationsthatareusedtocarryitout.
Nowthecomputerusesthe
databus
tofetchthememorylocationsto
beusedinthecalculation.Thedatabusistheconnectionbetween
theCPUandmemory.Itistheactualwirethatconnectsthem.Ifyou
lookatthemotherboardofthecomputer,thewiresthatgooutfrom
thememoryareyourdatabus.
Inadditiontothememoryontheoutsideoftheprocessor,the
processoritselfhassomespecial,highspeedmemorylocationscalled
registers.Therearetwokindsofregisters
generalregisters
and
specialpurposeregisters.
Generalpurposeregistersarewherethe
mainactionhappens.Addition,subtraction,multiplication,
comparisions,andotheroperationsgenerallyusegeneralpurpose
registersforprocessing.However,computershaveveryfew
generalpurposeregisters.Mostinformationisstoredinmainmemory,
broughtintotheregistersforprocessing,andthenputbackinto
memorywhentheprocessingiscompleted.
specialpurposeregisters
areregisterswhichhaveveryspecificpurposes.Wewilldiscuss
theseaswecometothem.
NowthattheCPUhasretrievedallofthedataitneeds,itpasseson
thedataandthedecodedinstructiontothe
arithmeticandlogicunit
forfurtherprocessing.Heretheinstructionisactuallyexecuted.
Aftertheresultsofthecomputationhavebeencalculated,the
resultsarethenplacedonthedatabusandsenttotheappropriate
locationinmemoryorinaregister,asspecifiedbytheinstruction.
Thisisaverysimplifiedexplanation.Processorshaveadvancedquite
abitinrecentyears,andarenowmuchmorecomplex.Althoughthe
basicoperationisstillthesame,itiscomplicatedbytheuseof
cachehierarchies,superscalarprocessors,pipelining,branch
prediction,outoforderexecution,microcodetranslation,
coprocessors,andotheroptimizations.Don'tworryifyoudon'tknow
whatthosewordsmean,youcanjustusethemasInternetsearchterms
ifyouwanttolearnmoreabouttheCPU.

SomeTerms
Computermemoryisanumberedsequenceoffixedsizestorage
locations.Thenumberattachedtoeachstoragelocationiscalledits

address.
Thesizeofasinglestoragelocationiscalleda
byte.
On
x86processors,abyteisanumberbetween0and255.
Youmaybewonderinghowcomputerscandisplayandusetext,
graphics,andevenlargenumberswhenalltheycandoisstore
numbersbetween0and255.Firstofall,specializedhardwarelike
graphicscardshavespecialinterpretationsofeachnumber.When
displayingtothescreen,thecomputerusesASCIIcodetablesto
translatethenumbersyouaresendingitintoletterstodisplayon
thescreen,witheachnumbertranslatingtoexactlyoneletteror
1]
numeral.[

Forexample,thecapitalletterAisrepresentedbythe
number65.Thenumeral1isrepresentedbythenumber49.So,to
printout"HELLO",youwouldactuallygivethecomputerthesequence
ofnumbers72,69,76,76,79.Toprintoutthenumber100,youwould
givethecomputerthesequenceofnumbers49,48,48.AlistofASCII
charactersandtheirnumericcodesisfoundinAppendixD.
InadditiontousingnumberstorepresentASCIIcharacters,youas
theprogrammergettomakethenumbersmeananythingyouwantthem
to,aswell.Forexample,ifIamrunningastore,Iwouldusea
numbertorepresenteachitemIwasselling.Eachnumberwouldbe
linkedtoaseriesofothernumberswhichwouldbetheASCIIcodes
forwhatIwantedtodisplaywhentheitemswerescannedin.Iwould
havemorenumbersfortheprice,howmanyIhaveininventory,andso
on.
Sowhataboutifweneednumberslargerthan255?Wecansimplyusea
combinationofbytestorepresentlargernumbers.Twobytescanbe
usedtorepresentanynumberbetween0and65535.Fourbytescanbe
usedtorepresentanynumberbetween0and4294967295.Now,itis
quitedifficulttowriteprogramstostickbytestogethertoincrease
thesizeofyournumbers,andrequiresabitofmath.Luckily,the
computerwilldoitforusfornumbersupto4byteslong.Infact,
fourbytenumbersarewhatwewillworkwithbydefault.
Wementionedearlierthatinadditiontotheregularmemorythatthe
computerhas,italsohasspecialpurposestoragelocationscalled
registers.
Registersarewhatthecomputerusesforcomputation.
Thinkofaregisterasaplaceonyourdeskitholdsthingsyouare
currentlyworkingon.Youmayhavelotsofinformationtuckedawayin
foldersanddrawers,butthestuffyouareworkingonrightnowison
thedesk.Registerskeepthecontentsofnumbersthatyouare
currentlymanipulating.
Onthecomputersweareusing,registersareeachfourbyteslong.
Thesizeofatypicalregisteriscalledacomputer's
word
size.x86
processorshavefourbytewords.Thismeansthatitismostnatural

2]
onthesecomputerstodocomputationsfourbytesatatime.[

This
givesusroughly4billionvalues.
Addressesarealsofourbytes(1word)long,andthereforealsofit
intoaregister.x86processorscanaccessupto4294967296bytesif
enoughmemoryisinstalled.Noticethatthismeansthatwecanstore
addressesthesamewaywestoreanyothernumber.Infact,the
computercan'ttellthedifferencebetweenavaluethatisan
address,avaluethatisanumber,avaluethatisanASCIIcode,or
avaluethatyouhavedecidedtouseforanotherpurpose.Anumber
becomesanASCIIcodewhenyouattempttodisplayit.Anumber
becomesanaddresswhenyoutrytolookupthebyteitpointsto.
Takeamomenttothinkaboutthis,becauseitiscrucialto
understandinghowcomputerprogramswork.
Addresseswhicharestoredinmemoryarealsocalled
pointers,
becauseinsteadofhavingaregularvalueinthem,theypointyouto
adifferentlocationinmemory.
Aswe'vementioned,computerinstructionsarealsostoredinmemory.
Infact,theyarestoredexactlythesamewaythatotherdatais
stored.Theonlywaythecomputerknowsthatamemorylocationisan
instructionisthataspecialpurposeregistercalledtheinstruction
pointerpointstothematonepointoranother.Iftheinstruction
pointerpointstoamemoryword,itisloadedasaninstruction.
Otherthanthat,thecomputerhasnowayofknowingthedifference
3]
betweenprogramsandothertypesofdata.[

[1]
WiththeadventofinternationalcharactersetsandUnicode,this
isnotentirelytrueanymore.However,forthepurposesofkeeping
thissimpleforbeginners,wewillusetheassumptionthatonenumber
translatesdirectlytoonecharacter.Formoreinformation,see
AppendixD.
[2]
Previousincarnationsofx86processorsonlyhadtwobytewords.
Therefore,mostotherliteraturedealingwithx86processorsrefers
totwobyteentitiesaswordsforhistoricalreasons,andtherefore
refertofourbyteentitiesasdoublewords.Weareusingtheterm
word
tomeanthenormalregistersizeofacomputer,whichinthis
caseisfourbytes.MoreinformationisavailableinAppendixB,
[3]
Notethatherewearetalkingaboutgeneralcomputertheory.Some
processorsandoperatingsystemsactuallymarktheregionsofmemory
thatcanbeexecutedwithaspecialmarkerthatindicatesthis.

Interpreting

Memory
Computersareveryexact.Becausetheyareexact,programmershaveto
beequallyexact.Acomputerhasnoideawhatyourprogramis
supposedtodo.Therefore,itwillonlydoexactlywhatyoutellit
todo.Ifyouaccidentallyprintoutaregularnumberinsteadofthe
ASCIIcodesthatmakeupthenumber'sdigits,thecomputerwilllet
youandyouwillwindupwithjibberishonyourscreen(itwilltry
tolookupwhatyournumberrepresentsinASCIIandprintthat).If
youtellthecomputertostartexecutinginstructionsatalocation
containingdatainsteadofprograminstructions,whoknowshowthe
computerwillinterpretthatbutitwillcertainlytry.The
computerwillexecuteyourinstructionsintheexactorderyou
specify,evenifitdoesn'tmakesense.
Thepointis,thecomputerwilldoexactlywhatyoutellit,no
matterhowlittlesenseitmakes.Therefore,asaprogrammer,you
needtoknowexactlyhowyouhaveyourdataarrangedinmemory.
Remember,computerscanonlystorenumbers,soletters,pictures,
music,webpages,documents,andanythingelsearejustlong
sequencesofnumbersinthecomputer,whichparticularprogramsknow
howtointerpret.
Forexample,saythatyouwantedtostorecustomerinformationin
memory.Onewaytodosowouldbetosetamaximumsizeforthe
customer'snameandaddresssay50ASCIIcharactersforeach,which
wouldbe50bytesforeach.Then,afterthat,haveanumberforthe
customer'sageandtheircustomerid.Inthiscase,youwouldhavea
blockofmemorythatwouldlooklikethis:
StartofRecord:
Customer'sname(50bytes)startofrecord
Customer'saddress(50bytes)startofrecord+50bytes
Customer'sage(1word=4bytes)startofrecord+100bytes
Customer'sidnumber(1word=4bytes)startofrecord+104
by

Thisway,giventheaddressofacustomerrecord,youknowwherethe
restofthedatalies.However,itdoeslimitthecustomer'snameand
addresstoonly50ASCIIcharacterseach.

Whatifwedidn'twanttospecifyalimit?Anotherwaytodothis
wouldbetohaveinourrecordpointerstothisinformation.For
example,insteadofthecustomer'sname,wewouldhaveapointerto
theirname.Inthiscase,thememorywouldlooklikethis:
StartofRecord:
Customer'snamepointer(1word)startofrecord
Customer'saddresspointer(1word)startofrecord+4
Customer'sage(1word)startofrecord+8
Customer'sidnumber(1word)startofrecord+12

Theactualnameandaddresswouldbestoredelsewhereinmemory.This
way,itiseasytotellwhereeachpartofthedataisfromthestart
oftherecord,withoutexplicitlylimittingthesizeofthenameand
address.Ifthelengthofthefieldswithinourrecordscouldchange,
wewouldhavenoideawherethenextfieldstarted.Becauserecords
wouldbedifferentsizes,itwouldalsobehardtofindwherethe
nextrecordbegan.Therefore,almostallrecordsareoffixed
lengths.Variablelengthdataisusuallystoredseparatelyfromthe
restoftherecord.

DataAccessingMethods
Processorshaveanumberofdifferentwaysofaccessingdata,known
asaddressingmodes.Thesimplestmodeis
immediatemode,
inwhich
thedatatoaccessisembeddedintheinstructionitself.For
example,ifwewanttoinitializearegisterto0,insteadofgiving
thecomputeranaddresstoreadthe0from,wewouldspecify
immediatemode,andgiveitthenumber0.
Inthe
registeraddressingmode,
theinstructioncontainsaregister
toaccess,ratherthanamemorylocation.Therestofthemodeswill
dealwithaddresses.
Inthe
directaddressingmode,
theinstructioncontainsthememory
addresstoaccess.Forexample,Icouldsay,pleaseloadthis
registerwiththedataataddress2002.Thecomputerwouldgo
directlytobytenumber2002andcopythecontentsintoourregister.
Inthe
indexedaddressingmode,
theinstructioncontainsamemory
addresstoaccess,andalsospecifiesan
indexregister
tooffset
thataddress.Forexample,wecouldspecifyaddress2002andanindex
register.Iftheindexregistercontainsthenumber4,theactual
addressthedataisloadedfromwouldbe2006.Thisway,ifyouhave
asetofnumbersstartingatlocation2002,youcancyclebetween
eachofthemusinganindexregister.Onx86processors,youcanalso

specifya
multiplier
fortheindex.Thisallowsyoutoaccessmemory
abyteatatimeorawordatatime(4bytes).Ifyouareaccessing
anentireword,yourindexwillneedtobemultipliedby4togetthe
exactlocationofthefourthelementfromyouraddress.Forexample,
ifyouwantedtoaccessthefourthbytefromlocation2002,youwould
loadyourindexregisterwith3(remember,westartcountingat0)
andsetthemultiplierto1sinceyouaregoingabyteatatime.
Thiswouldgetyoulocation2005.However,ifyouwantedtoaccess
thefourthwordfromlocation2002,youwouldloadyourindex
registerwith3andsetthemultiplierto4.Thiswouldloadfrom
location2014thefourthword.Takethetimetocalculatethese
yourselftomakesureyouunderstandhowitworks.
Inthe
indirectaddressingmode,
theinstructioncontainsaregister
thatcontainsapointertowherethedatashouldbeaccessed.For
example,ifweusedindirectaddressingmodeandspecifiedthe%eax
register,andthe%eaxregistercontainedthevalue4,whatevervalue
wasatmemorylocation4wouldbeused.Indirectaddressing,we
wouldjustloadthevalue4,butinindirectaddressing,weuse4as
theaddresstousetofindthedatawewant.
Finally,thereisthe
basepointeraddressingmode.
Thisissimilar
toindirectaddressing,butyoualsoincludeanumbercalledthe
offset
toaddtotheregister'svaluebeforeusingitforlookup.We
willusethismodequiteabitinthisbook.
IntheSectioncalled
InterpretingMemory
wediscussedhavinga
structureinmemoryholdingcustomerinformation.Let'ssaywewanted
toaccessthecustomer'sage,whichwastheeighthbyteofthedata,
andwehadtheaddressofthestartofthestructureinaregister.
Wecouldusebasepointeraddressingandspecifytheregisterasthe
basepointer,and8asouroffset.Thisisalotlikeindexed
addressing,withthedifferencethattheoffsetisconstantandthe
pointerisheldinaregister,andinindexedaddressingtheoffset
isinaregisterandthepointerisconstant.
Thereareotherformsofaddressing,butthesearethemostimportant
ones.

Review

KnowtheConcepts
Describethefetchexecutecycle.

Whatisaregister?Howwouldcomputationbemoredifficultwithout
registers?
Howdoyourepresentnumberslargerthan255?
Howbigaretheregistersonthemachineswewillbeusing?
Howdoesacomputerknowhowtointerpretagivenbyteorsetof
bytesofmemory?
Whataretheaddressingmodesandwhataretheyusedfor?
Whatdoestheinstructionpointerdo?
UsetheConcepts
Whatdatawouldyouuseinanemployeerecord?Howwouldyoulayit
outinmemory?
IfIhadthepointertothebeginningoftheemployeerecordabove,
andwantedtoaccessaparticularpieceofdatainsideofit,what
addressingmodewouldIuse?
Inbasepointeraddressingmode,ifyouhavearegisterholdingthe
value3122,andanoffsetof20,whataddresswouldyoubetryingto
access?
Inindexedaddressingmode,ifthebaseaddressis6512,theindex
registerhasa5,andthemultiplieris4,whataddresswouldyoube
tryingtoaccess?
Inindexedaddressingmode,ifthebaseaddressis123472,theindex
registerhasa0,andthemultiplieris4,whataddresswouldyoube
tryingtoaccess?
Inindexedaddressingmode,ifthebaseaddressis9123478,theindex
registerhasa20,andthemultiplieris1,whataddresswouldyoube
tryingtoaccess?
GoingFurther
Whataretheminimumnumberofaddressingmodesneededfor
computation?
Whyincludeaddressingmodesthataren'tstrictlyneeded?
Researchandthendescribehowpipelining(oroneoftheother
complicatingfactors)affectsthefetchexecutecycle.
Researchandthendescribethetradeoffsbetweenfixedlength
instructionsandvariablelengthinstructions.

Chapter3:YourFirstPrograms

Inthischapteryouwilllearntheprocessforwritingandbuilding
Linuxassemblylanguageprograms.Inaddition,youwilllearnthe
structureofassemblylanguageprograms,andafewassemblylanguage
commands.Asyougothroughthischapter,youmaywanttoreferalso
toAppendixBandAppendixF.
Theseprogramsmayoverwhelmyouatfirst.However,gothroughthem
withdiligence,readthemandtheirexplanationsasmanytimesas
necessary,andyouwillhaveasolidfoundationofknowledgetobuild
on.Pleasetinkeraroundwiththeprogramsasmuchasyoucan.Even
ifyourtinkeringdoesnotwork,everyfailurewillhelpyoulearn.

EnteringintheProgram
Okay,thisfirstprogramissimple.Infact,it'snotgoingtodo
anythingbutexit!It'sshort,butitshowssomebasicsabout
assemblylanguageandLinuxprogramming.Youneedtoenterthe
programinaneditorexactlyaswritten,withthefilenameexit.s.
Theprogramfollows.Don'tworryaboutnotunderstandingit.This
sectiononlydealswithtypingitinandrunningit.IntheSection
called
OutlineofanAssemblyLanguageProgram
wewilldescribehowit
works.
#PURPOSE:Simpleprogramthatexitsandreturnsa
#statuscodebacktotheLinuxkernel
#

#INPUT:none
#

#OUTPUT:returnsastatuscode.Thiscanbeviewed
#bytyping
#
#echo$?
#
#afterrunningtheprogram
#

#VARIABLES:
#%eaxholdsthesystemcallnumber
#%ebxholdsthereturnstatus
#
.section.data

.section.text
.globl_start

_start:
movl$1,%eax#thisisthelinuxkernelcommand
#number(systemcall)forexiting
#aprogram

movl$0,%ebx#thisisthestatusnumberwewill
#returntotheoperatingsystem.
#Changethisaroundanditwill
#returndifferentthingsto
#echo$?

int$0x80#thiswakesupthekerneltorun
#theexitcommand

Whatyouhavetypediniscalledthe
sourcecode.
Sourcecodeisthe
humanreadableformofaprogram.Inordertotransformitintoa
programthatacomputercanrun,weneedto
assemble
and
link
it.
Thefirststepisto
assemble
it.Assemblingistheprocessthat
transformswhatyoutypedintoinstructionsforthemachine.The
machineitselfonlyreadssetsofnumbers,buthumanspreferwords.
An
assemblylanguage
isamorehumanreadableformofthe
instructionsacomputerunderstands.Assemblingtransformsthe
humanreadablefileintoamachinereadableone.Toassemblythe
programtypeinthecommand
asexit.soexit.o

asisthecommandwhichrunstheassembler,exit.sisthesource
file,andoexit.otellstheassembletoputitsoutputinthefile
exit.o.exit.oisan
objectfile.
Anobjectfileiscodethatisin
themachine'slanguage,buthasnotbeencompletelyputtogether.In
mostlargeprograms,youwillhaveseveralsourcefiles,andyouwill
converteachoneintoanobjectfile.The
linker
istheprogramthat
isresponsibleforputtingtheobjectfilestogetherandadding
informationtoitsothatthekernelknowshowtoloadandrunit.In
ourcase,weonlyhaveoneobjectfile,sothelinkerisonlyadding
theinformationtoenableittorun.To
link
thefile,enterthe
command
ldexit.ooexit

ldisthecommandtorunthelinker,exit.oistheobjectfilewe
wanttolink,andoexitinstructsthelinkertooutputthenew
1]
programintoafilecalledexit.[

Ifanyofthesecommandsreported
errors,youhaveeithermistypedyourprogramorthecommand.After

correctingtheprogram,youhavetorerunallthecommands.
Youmust
alwaysreassembleandrelinkprogramsafteryoumodifythesource
fileforthechangestooccurintheprogram.
Youcanrunexitby
typinginthecommand
./exit

The./isusedtotellthecomputerthattheprogramisn'tinoneof
thenormalprogramdirectories,butisthecurrentdirectory
2]
instead[

.You'llnoticewhenyoutypethiscommand,theonlything
thathappensisthatyou'llgotothenextline.
That'sbecausethisprogramdoesnothingbutexit.However,
immediatelyafteryouruntheprogram,ifyoutypein
echo$?

Itwillsay0.Whatishappeningisthateveryprogramwhenitexits
givesLinuxan
exitstatuscode,
whichtellsitifeverythingwent
allright.Ifeverythingwasokay,itreturns0.UNIXprogramsreturn
numbersotherthanzerotoindicatefailureorothererrors,
warnings,orstatuses.Theprogrammerdetermineswhateachnumber
means.Youcanviewthiscodebytypinginecho$?.Inthefollowing
sectionwewilllookatwhateachpartofthecodedoes.
[1]
If you are new to Linux and UNIX, you may not be aware that files don't have to have
extensions. In fact, while Windows uses the .exe extension to signify an executable
program, UNIX executables usually have no extension.
[2]
..referstothecurrentdirectoryinLinuxandUNIXsystems.

OutlineofanAssemblyLanguageProgram
Takealookattheprogramwejustentered.Atthebeginningthere
arelotsoflinesthatbeginwithhashes(#).Theseare
comments.
Commentsarenottranslatedbytheassembler.Theyareusedonlyfor
theprogrammertotalktoanyonewholooksatthecodeinthefuture.
Mostprogramsyouwritewillbemodifiedbyothers.Getintothe
habitofwritingcommentsinyourcodethatwillhelpthemunderstand
bothwhytheprogramexistsandhowitworks.Alwaysincludethe
followinginyourcomments:
Thepurposeofthecode
Anoverviewoftheprocessinginvolved
3]
Anythingstrangeyourprogramdoesandwhyitdoesit[

Afterthecomments,thenextlinesays
.section.data

Anythingstartingwithaperiodisn'tdirectlytranslatedintoa
machineinstruction.Instead,it'saninstructiontotheassembler
itself.Thesearecalled
assemblerdirectives
or
pseudooperations
becausetheyarehandledbytheassemblerandarenotactuallyrunby
thecomputer.The.sectioncommandbreaksyourprogramupinto
sections.Thiscommandstartsthedatasection,whereyoulistany
memorystorageyouwillneedfordata.Ourprogramdoesn'tuseany,
sowedon'tneedthesection.It'sjusthereforcompleteness.Almost
everyprogramyouwriteinthefuturewillhavedata.
Rightafterthisyouhave
.section.text

whichstartsthetextsection.Thetextsectionofaprogramiswhere
theprograminstructionslive.
Thenextinstructionis
.globl_start

Thisinstructstheassemblerthat_startisimportanttoremember.
_startisa
symbol,
whichmeansthatitisgoingtobereplacedby
somethingelseeitherduringassemblyorlinking.Symbolsare
generallyusedtomarklocationsofprogramsordata,soyoucan
refertothembynameinsteadofbytheirlocationnumber.Imagineif
youhadtorefertoeverymemorylocationbyitsaddress.Firstof
all,itwouldbeveryconfusingbecauseyouwouldhavetomemorizeor
lookupthenumericmemoryaddressofeverypieceofcodeordata.In
addition,everytimeyouhadtoinsertapieceofdataorcodeyou
wouldhavetochangealltheaddressesinyourprogram!Symbolsare
usedsothattheassemblerandlinkercantakecareofkeepingtrack
ofaddresses,andyoucanconcentrateonwritingyourprogram.
.globlmeansthattheassemblershouldn'tdiscardthissymbolafter
assembly,becausethelinkerwillneedit._startisaspecialsymbol
thatalwaysneedstobemarkedwith.globlbecauseitmarksthe
locationofthestartoftheprogram.
Withoutmarkingthislocationin
thisway,whenthecomputerloadsyourprogramitwon'tknowwhereto
beginrunningyourprogram.
Thenextline
_start:

defines
thevalueofthe_startlabel.A
label
isasymbolfollowed
byacolon.Labelsdefineasymbol'svalue.Whentheassembleris
assemblingtheprogram,ithastoassigneachdatavalueand
instructionanaddress.Labelstelltheassemblertomakethe
symbol'svaluebewhereverthenextinstructionordataelementwill

be.Thisway,iftheactualphysicallocationofthedataor
instructionchanges,youdon'thavetorewriteanyreferencestoit
thesymbolautomaticallygetsthenewvalue.
Nowwegetintoactualcomputerinstructions.Thefirstsuch
instructionisthis:
movl$l,%eax

Whentheprogramruns,thisinstructiontransfersthenumber1into
the%eaxregister.Inassemblylanguage,manyinstructionshave
operands.
movlhastwooperandsthe
source
andthe
destination.
In
thiscase,thesourceistheliteralnumber1,andthedestinationis
the%eaxregister.Operandscanbenumbers,memorylocation
references,orregisters.Differentinstructionsallowdifferent
typesofoperands.SeeAppendixBformoreinformationonwhich
instructionstakewhichkindsofoperands.
Onmostinstructionswhichhavetwooperands,thefirstoneisthe
sourceoperandandthesecondoneisthedestination.Notethatin
thesecases,thesourceoperandisnotmodifiedatall.Other
instructionsofthistypeare,forexample,addl,subl,andimull.
Theseadd/subtract/multiplythesourceoperandfrom/to/bythe
destinationoperandandandsavetheresultinthedestination
operand.Otherinstructionsmayhaveanoperandhardcodedin.idivl,
forexample,requiresthatthedividendbein%eax,and%edxbezero,
andthequotientisthentransferredto%eaxandtheremainderto
%edx.However,thedivisorcanbeanyregisterormemorylocation.
4]
Onx86processors,thereareseveralgeneralpurposeregisters[

(all
ofwhichcanbeusedwithmovl):
%eax
%ebx
%ecx
%edx
%edi
%esi
Inadditiontothesegeneralpurposeregisters,therearealso
severalspecialpurposeregisters,including:
%ebp
%esp
%eip
%eflags
5]
We'lldiscusstheselater,justbeawarethattheyexist.[

Someof
theseregisters,like%eipand%eflagscanonlybeaccessedthrough
specialinstructions.Theotherscanbeaccessedusingthesame
instructionsasgeneralpurposeregisters,buttheyhavespecial

meanings,specialuses,oraresimplyfasterwhenusedinaspecific
way.
So,themovlinstructionmovesthenumber1into%eax.The
dollarsigninfrontoftheoneindicatesthatwewanttouse
immediatemodeaddressing(referbacktotheSectioncalled
Data
AccessingMethods
inChapter2).Withoutthedollarsignitwoulddo
directaddressing,loadingwhatevernumberisataddress1.Wewant
theactualnumber1loadedin,sowehavetouseimmediatemode.
Thereasonwearemovingthenumber1into%eaxisbecauseweare
preparingtocalltheLinuxKernel.Thenumber1isthenumberofthe
exit
systemcall.
Wewilldiscusssystemcallsinmoredepthsoon,
butbasicallytheyarerequestsfortheoperatingsystem'shelp.
Normalprogramscan'tdoeverything.Manyoperationssuchascalling
otherprograms,dealingwithfiles,andexitinghavetobehandledby
theoperatingsystemthroughsystemcalls.Whenyoumakeasystem
call,whichwewilldoshortly,thesystemcallnumberhastobe
loadedinto%eax(foracompletelistingofsystemcallsandtheir
numbers,seeAppendixC).Dependingonthesystemcall,other
registersmayhavetohavevaluesinthemaswell.Notethatsystem
callsisnottheonlyuseoreventhemainuseofregisters.Itis
justtheonewearedealingwithinthisfirstprogram.Later
programswilluseregistersforregularcomputation.
Theoperatingsystem,however,usuallyneedsmoreinformationthan
justwhichcalltomake.Forexample,whendealingwithfiles,the
operatingsystemneedstoknowwhichfileyouaredealingwith,what
datayouwanttowrite,andotherdetails.Theextradetails,called
parameters
arestoredinotherregisters.Inthecaseoftheexit
systemcall,theoperatingsystemrequiresastatuscodebeloadedin
%ebx.Thisvalueisthenreturnedtothesystem.Thisisthevalue
youretrievedwhenyoutypedecho$?.So,weload%ebxwith0by
typingthefollowing:
movl$0,%ebx

Now,loadingregisterswiththesenumbersdoesn'tdoanythingitself.
Registersareusedforallsortsofthingsbesidessystemcalls.They
arewhereallprogramlogicsuchasaddition,subtraction,and
comparisonstakeplace.Linuxsimplyrequiresthatcertainregisters
beloadedwithcertainparametervaluesbeforemakingasystemcall.
%eaxisalwaysrequiredtobeloadedwiththesystemcallnumber.For
theotherregisters,however,eachsystemcallhasdifferent
requirements.Intheexitsystemcall,%ebxisrequiredtobeloaded
withtheexitstatus.Wewilldiscussdifferentsystemcallsasthey

areneeded.Foralistofcommonsystemcallsandwhatisrequiredto
beineachregister,seeAppendixC
Thenextinstructionisthe"magic"one.Itlookslikethis:
int$0x80

Theintstandsfor
interrupt.
The0x80istheinterruptnumberto
[6]
use. An
interrupt
interruptsthenormalprogramflow,andtransfers
controlfromourprogramtoLinuxsothatitwilldoasystem
7]
8]
call.[

.YoucanthinkofitaslikesignalingBatman(orLarryBoy[

,
ifyouprefer).Youneedsomethingdone,yousendthesignal,and
thenhecomestotherescue.Youdon'tcarehowhedoeshiswork
it'smoreorlessmagicandwhenhe'sdoneyou'rebackincontrol.
Inthiscase,allwe'redoingisaskingLinuxtoterminatethe
program,inwhichcasewewon'tbebackincontrol.Ifwedidn't
signaltheinterrupt,thennosystemcallwouldhavebeenperformed.
QuickSystemCallReview:
TorecapOperatingSystemfeaturesare
accessedthroughsystemcalls.Theseareinvokedbysettingupthe
registersinaspecialwayandissuingtheinstructionint$0x80.
Linuxknowswhichsystemcallwewanttoaccessbywhatwestoredin
the%eaxregister.Eachsystemcallhasotherrequirementsastowhat
needstobestoredintheotherregisters.Systemcallnumber1is
theexitsystemcall,whichrequiresthestatuscodetobeplacedin
%ebx.
Nowthatyou'veassembled,linked,run,andexaminedtheprogram,you
shouldmakesomebasicedits.Dothingslikechangethenumberthat
isloadedinto%ebx,andwatchitcomeoutattheendwithecho$?.
Don'tforgettoassembleandlinkitagainbeforerunningit.Add
somecomments.Don'tworry,theworsethingthatwouldhappenisthat
theprogramwon'tassembleorlink,orwillfreezeyourscreen.
That'sjustpartoflearning!
[3]
You'llfindthatmanyprogramsendupdoingthingsstrangeways.
Usuallythereisareasonforthat,but,unfortunately,programmers
neverdocumentsuchthingsintheircomments.So,futureprogrammers
eitherhavetolearnthereasonthehardwaybymodifyingthecode
andwatchingitbreak,orjustleavingitalonewhetheritisstill
neededornot.Youshould
always
documentanystrangebehavioryour
programperforms.Unfortunately,figuringoutwhatisstrangeand
whatisstraightforwardcomesmostlywithexperience.
[4]
Notethatonx86processors,eventhegeneralpurposeregisters
havesomespecialpurposes,orusedtobeforeitwent32bit.
However,thesearegeneralpurposeregistersformostinstructions.
Eachofthemhasatleastoneinstructionwhereitisusedina

specialway.However,formostofthem,thoseinstructionsaren't
coveredinthisbook.
[5]
Youmaybewondering,
whydoalloftheseregistersbeginwiththe
lettere?
Thereasonisthatearlygenerationsofx86processorswere
16bitsratherthan32bits.Therefore,theregisterswereonlyhalf
thelengththeyarenow.Inlatergenerationsofx86processors,the
sizeoftheregistersdoubled.Theykepttheoldnamestoreferto
thefirsthalfoftheregister,andaddedanetorefertothe
extendedversionsoftheregister.Usuallyyouwillonlyusethe
extendedversions.Newermodelsalsooffera64bitmode,which
doublesthesizeoftheseregistersyetagainandusesanrprefixto
indicatethelargerregisters(i.e.%raxisthe64bitversionof
%eax).However,theseprocessorsarenotwidelyused,andarenot
coveredinthisbook.
[6]
Youmaybewonderingwhyit's0x80insteadofjust80.Thereason
isthatthenumberiswritteninhexadecimal.Inhexadecimal,a
singledigitcanhold16valuesinsteadofthenormal10.Thisis
donebyutilizingthelettersathroughfinadditiontotheregular
digits.arepresents10,brepresents11,andsoon.0x10represents
thenumber16,andsoon.Thiswillbediscussedmoreindepthlater,
butjustbeawarethatnumbersstartingwith0xareinhexadecimal.
TackingonanHattheendisalsosometimesusedinstead,butwe
won'tdothatinthisbook.Formoreinformationaboutthis,see
Chapter10
[7]
Actually,theinterrupttransferscontroltowhoeversetupan
interrupthandler
fortheinterruptnumber.InthecaseofLinux,all
ofthemaresettobehandledbytheLinuxkernel.
[8]
Ifyoudon'twatchVeggieTales,youshould.StartwithDaveand
theGiantPickle.

PlanningtheProgram
Inournextprogramwewilltrytofindthemaximumofalistof
numbers.Computersareverydetailoriented,soinordertowritethe
programwewillhavetohaveplannedoutanumberofdetails.These
detailsinclude:
Wherewilltheoriginallistofnumbersbestored?
Whatprocedurewillweneedtofollowtofindthemaximum
number?
Howmuchstoragedoweneedtocarryoutthatprocedure?
Willallofthestoragefitintoregisters,ordoweneedto
usesomememoryaswell?

Youmightnotthinkthatsomethingassimpleasfindingthemaximum
numberfromalistwouldtakemuchplanning.Youcanusuallytell
peopletofindthemaximumnumber,andtheycandosowithlittle
trouble.However,ourmindsareusedtoputtingtogethercomplex
tasksautomatically.Computersneedtobeinstructedthroughthe
process.Inaddition,wecanusuallyholdanynumberofthingsinour
mindwithoutmuchtrouble.Weusuallydon'tevenrealizewearedoing
it.Forexample,ifyouscanalistofnumbersforthemaximum,you
willprobablykeepinmindboththehighestnumberyou'veseenso
far,andwhereyouareinthelist.Whileyourminddoesthis
automatically,withcomputersyouhavetoexplicitlysetupstorage
forholdingthecurrentpositiononthelistandthecurrentmaximum
number.Youalsohaveotherproblemssuchashowtoknowwhento
stop.Whenreadingapieceofpaper,youcanstopwhenyourunoutof
numbers.However,thecomputeronlycontainsnumbers,soithasno
ideawhenithasreachedthelastof
your
numbers.
Incomputers,youhavetoplaneverystepoftheway.So,let'sdoa
littleplanning.Firstofall,justforreference,let'snamethe
addresswherethelistofnumbersstartsasdata_items.Let'ssay
thatthelastnumberinthelistwillbeazero,soweknowwhereto
stop.Wealsoneedavaluetoholdthecurrentpositioninthelist,
avaluetoholdthecurrentlistelementbeingexamined,andthe
currenthighestvalueonthelist.Let'sassigneachofthesea
register:
%ediwillholdthecurrentpositioninthelist.
%ebxwillholdthecurrenthighestvalueinthelist.
%eaxwillholdthecurrentelementbeingexamined.
Whenwebegintheprogramandlookatthefirstiteminthelist,
sincewehaven'tseenanyotheritems,thatitemwillautomatically
bethecurrentlargestelementinthelist.Also,wewillsetthe
currentpositioninthelisttobezerothefirstelement.From
then,wewillfollowthefollowingsteps:
1.Checkthecurrentlistelement(%eax)toseeifit'szero(the
terminatingelement).
2.Ifitiszero,exit.
3.Increasethecurrentposition(%edi).
4.Loadthenextvalueinthelistintothecurrentvalueregister
(%eax).Whataddressingmodemightweusehere?Why?
5.Comparethecurrentvalue(%eax)withthecurrenthighestvalue
(%ebx).
6.Ifthecurrentvalueisgreaterthanthecurrenthighestvalue,
replacethecurrenthighestvaluewiththecurrentvalue.
7.Repeat.

Thatistheprocedure.ManytimesinthatprocedureImadeuseofthe
word"if".Theseplacesarewheredecisionsaretobemade.Yousee,
thecomputerdoesn'tfollowtheexactsamesequenceofinstructions
everytime.Dependingonwhich"if"sarecorrect,thecomputermay
followadifferentsetofinstructions.Thesecondtimethrough,it
mightnothavethehighestvalue.Inthatcase,itwillskipstep6,
butcomebacktostep7.Ineverycaseexceptthelastone,itwill
skipstep2.Inmorecomplicatedprograms,theskippingaround
increasesdramatically.
These"if"sareaclassofinstructionscalled
flowcontrol
instructions,becausetheytellthecomputerwhichstepstofollow
andwhichpathstotake.Inthepreviousprogram,wedidnothaveany
flowcontrolinstructions,astherewasonlyonepossiblepathto
takeexit.Thisprogramismuchmoredynamicinthatitisdirected
bydata.Dependingonwhatdataitreceives,itwillfollowdifferent
instructionpaths.
Inthisprogram,thiswillbeaccomplishedbytwodifferent
instructions,theconditionaljumpandtheunconditionaljump.The
conditionaljumpchangespathsbasedontheresultsofaprevious
comparisonorcalculation.Theunconditionaljumpjustgoesdirectly
toadifferentpathnomatterwhat.Theunconditionaljumpmayseem
useless,butitisverynecessarysincealloftheinstructionswill
belaidoutonaline.Ifapathneedstoconvergebacktothemain
path,itwillhavetodothisbyanunconditionaljump.Wewillsee
moreofbothofthesejumpsinthenextsection.
Anotheruseofflowcontrolisinimplementingloops.Aloopisa
pieceofprogramcodethatismeanttoberepeated.Inourexample,
thefirstpartoftheprogram(settingthecurrentpositionto0and
loadingthecurrenthighestvaluewiththecurrentvalue)wasonly
doneonce,soitwasn'taloop.However,thenextpartisrepeated
overandoveragainforeverynumberinthelist.Itisonlyleft
whenwehavecometothelastelement,indicatedbyazero.Thisis
calleda
loop
becauseitoccursoverandoveragain.Itis
implementedbydoingunconditionaljumpstothebeginningoftheloop
attheendoftheloop,whichcausesittostartover.However,you
havetoalwaysremembertohaveaconditionaljumptoexittheloop
somewhere,ortheloopwillcontinueforever!Thisconditionis
calledan
infiniteloop.
Ifweaccidentallyleftoutstep1,2,or3,
theloop(andourprogram)wouldneverend.
Inthenextsection,wewillimplementthisprogramthatwehave
planned.Programplanningsoundscomplicatedanditis,tosome
degree.Whenyoufirststartprogramming,it'softenhardtoconvert
ournormalthoughtprocessintoaprocedurethatthecomputercan

understand.Weoftenforgetthenumberof"temporarystorage
locations"thatourmindsareusingtoprocessproblems.Asyouread
andwriteprograms,however,thiswilleventuallybecomeverynatural
toyou.Justhavepatience.

FindingaMaximum

Value
Enterthefollowingprogramasmaximum.s:
#PURPOSE:Thisprogramfindsthemaximumnumberofa
#setofdataitems.
#
#VARIABLES:Theregistershavethefollowinguses:
#
#%ediHoldstheindexofthedataitembeingexamined
#%ebxLargestdataitemfound
#%eaxCurrentdataitem
#
#Thefollowingmemorylocationsareused:
#
#data_itemscontainstheitemdata.A0isused
#toterminatethedata
#

.section.data

data_items:#Thesearethedataitems
.long3,67,34,222,45,75,54,34,44,33,22,11,66,0

.section.text

.globl_start
_start:
movl$0,%edi#move0intotheindexregister
movldata_items(,%edi,4),%eax#loadthefirstbyteofdata
movl%eax,%ebx#sincethisisthefirstitem,%eaxis
#thebiggest


start_loop:#startloop
cmpl$0,%eax#checktoseeifwe'vehittheend
jeloop_exit
incl%edi#loadnextvalue
movldata_items(,%edi,4),%eax
cmpl%ebx,%eax#comparevalues
jlestart_loop#jumptoloopbeginningifthenew
#oneisn'tbigger
movl%eax,%ebx#movethevalueasthelargest
jmpstart_loop#jumptoloopbeginning

loop_exit:
#%ebxisthestatuscodefortheexitsystemcall
#anditalreadyhasthemaximumnumber
movl$1,%eax#1istheexit()syscall
int$0x80

Now,assembleandlinkitwiththesecommands:
asmaximum.somaximum.o
ldmaximum.oomaximum

Nowrunit,andcheckitsstatus.
./maximum
echo$?

You'llnoticeitreturnsthevalue222.Let'stakealookatthe
programandwhatitdoes.Ifyoulookinthecomments,you'llsee
thattheprogramfindsthemaximumofasetofnumbers(aren't
commentswonderful!).Youmayalsonoticethatinthisprogramwe
actuallyhavesomethinginthedatasection.Theselinesarethedata
section:
data_items:#Thesearethedataitems
.long3,67,34,222,45,75,54,34,44,33,22,11,66,0

Letslookatthis.data_itemsisalabelthatreferstothelocation
thatfollowsit.Then,thereisadirectivethatstartswith.long.
Thatcausestheassemblertoreservememoryforthelistofnumbers
thatfollowit.data_itemsreferstothelocationofthefirstone.
Becausedata_itemsisalabel,anytimeinourprogramwhereweneed
torefertothisaddresswecanusethedata_itemssymbol,andthe
assemblerwillsubstituteitwiththeaddresswherethenumbersstart
duringassembly.Forexample,theinstructionmovldata_items,%eax

wouldmovethevalue3into%eax.Thereareseveraldifferenttypes
ofmemorylocationsotherthan.longthatcanbereserved.Themain
onesareasfollows:
.byte
Bytestakeuponestoragelocationforeachnumber.Theyarelimited
tonumbersbetween0and255.
.int
Ints(whichdifferfromtheintinstruction)takeuptwostorage
locationsforeachnumber.Thesearelimittedtonumbersbetween0
9]
and65535.[

.long
Longstakeupfourstoragelocations.Thisisthesameamountof
spacetheregistersuse,whichiswhytheyareusedinthisprogram.
Theycanholdnumbersbetween0and4294967295.
.ascii
The.asciidirectiveistoenterincharactersintomemory.
Characterseachtakeuponestoragelocation(theyareconvertedinto
bytesinternally).So,ifyougavethedirective.ascii"Hello
there\0",theassemblerwouldreserve12storagelocations(bytes).
ThefirstbytecontainsthenumericcodeforH,thesecondbyte
containsthenumericcodefore,andsoforth.Thelastcharacteris
representedby\0,anditistheterminatingcharacter(itwillnever
display,itjusttellsotherpartsoftheprogramthatthat'stheend
ofthecharacters).Lettersandnumbersthatstartwithabackslash
representcharactersthatarenottypeableonthekeyboardoreasily
viewableonthescreen.Forexample,\nreferstothe"newline"
characterwhichcausesthecomputertostartoutputonthenextline
and\treferstothe"tab"character.Allofthelettersinan.ascii
directiveshouldbeinquotes.
Inourexample,theassemblerreserves14.longs,onerightafter
another.Sinceeachlongtakesup4bytes,thatmeansthatthewhole
listtakesup56bytes.Thesearethenumberswewillbesearching
throughtofindthemaximum.data_itemsisusedbytheassemblerto
refertotheaddressofthefirstofthesevalues.
Takenotethatthelastdataiteminthelistisazero.Idecidedto
useazerototellmyprogramthatithashittheendofthelist.I
couldhavedonethisotherways.Icouldhavehadthesizeofthe
listhardcodedintotheprogram.Also,Icouldhaveputthelength
ofthelistasthefirstitem,orinaseparatelocation.Ialso
couldhavemadeasymbolwhichmarkedthelastlocationofthelist
items.NomatterhowIdoit,Imusthavesomemethodofdetermining
theendofthelist.Thecomputerknowsnothingitcanonlydowhat
itistold.It'snotgoingtostopprocessingunlessIgiveitsome

sortofsignal.Otherwiseitwouldcontinueprocessingpasttheend
ofthelistintothedatathatfollowsit,andeventolocations
wherewehaven'tputanydata.
Noticethatwedon'thavea.globldeclarationfordata_items.This
isbecauseweonlyrefertotheselocationswithintheprogram.No
otherfileorprogramneedstoknowwheretheyarelocated.Thisis
incontrasttothe_startsymbol,whichLinuxneedstoknowwhereit
issothatitknowswheretobegintheprogram'sexecution.It'snot
anerrortowrite.globldata_items,it'sjustnotnecessary.Anyway,
playaroundwiththislineandaddyourownnumbers.Eventhoughthey
are.long,theprogramwillproducestrangeresultsifanynumberis
greaterthan255,becausethat'sthelargestallowedexitstatus.
Alsonoticethatifyoumovethe0toearlierinthelist,therest
getignored.
Rememberthatanytimeyouchangethesourcefile,you
havetoreassembleandrelinkyourprogram.Dothisnowandseethe
results.
Allright,we'veplayedwiththedataalittlebit.Nowlet'slookat
thecode.Inthecommentsyouwillnoticethatwe'vemarkedsome
variables
thatweplantouse.Avariableisadedicatedstorage
locationusedforaspecificpurpose,usuallygivenadistinctname
bytheprogrammer.Wetalkedabouttheseintheprevioussection,but
didn'tgivethemaname.Inthisprogram,wehaveseveralvariables:
avariableforthecurrentmaximumnumberfound
avariableforwhichnumberofthelistwearecurrentlyexamining,
calledtheindex
avariableholdingthecurrentnumberbeingexamined
Inthiscase,wehavefewenoughvariablesthatwecanholdthemall
inregisters.Inlargerprograms,youhavetoputtheminmemory,and
thenmovethemtoregisterswhenyouarereadytousethem.Wewill
discusshowtodothatlater.Whenpeoplestartoutprogramming,they
usuallyunderestimatethenumberofvariablestheywillneed.People
arenotusedtohavingtothinkthrougheverydetailofaprocess,
andthereforeleaveoutneededvariablesintheirfirstprogramming
attempts.
Inthisprogram,weareusing%ebxasthelocationofthelargest
itemwe'vefound.%ediisusedasthe
index
tothecurrentdataitem
we'relookingat.Now,let'stalkaboutwhatanindexis.Whenwe
readtheinformationfromdata_items,wewillstartwiththefirst
one(dataitemnumber0),thengotothesecondone(dataitemnumber
1),thenthethird(dataitemnumber2),andsoon.Thedataitem
numberisthe
index
ofdata_items.You'llnoticethatthefirst
instructionwegivetothecomputeris:

movl$0,%edi

Sinceweareusing%ediasourindex,andwewanttostartlookingat
thefirstitem,weload%ediwith0.Now,thenextinstructionis
tricky,butcrucialtowhatwe'redoing.Itsays:
movldata_items(,%edi,4),%eax

Nowtounderstandthisline,youneedtokeepseveralthingsinmind:
data_itemsisthelocationnumberofthestartofournumberlist.
Eachnumberisstoredacross4storagelocations(becausewedeclared
itusing.long)
%ediisholding0atthispoint
So,basicallywhatthislinedoesissay,"startatthebeginningof
data_items,andtakethefirstitemnumber(because%ediis0),and
rememberthateachnumbertakesupfourstoragelocations."Thenit
storesthatnumberin%eax.Thisishowyouwriteindexedaddressing
modeinstructionsinassemblylanguage.Theinstructioninageneral
formisthis:
movlBEGINNINGADDRESS(,%INDEXREGISTER,WORDSIZE)

Inourcasedata_itemswasourbeginningaddress,%ediwasourindex
register,and4wasourwordsize.Thistopicisdiscussedfurtherin
theSectioncalled
AddressingModes.
Ifyoulookatthenumbersindata_items,youwillseethatthe
number3isnowin%eax.If%ediwassetto1,thenumber67wouldbe
in%eax,andifitwassetto2,thenumber34wouldbein%eax,and
soforth.Verystrangethingswouldhappenifweusedanumberother
10]
than4asthesizeofourstoragelocations.[

Thewayyouwrite
thisisveryawkward,butifyouknowwhateachpiecedoes,it'snot
toodifficult.Formoreinformationaboutthis,seetheSection
called
AddressingModes
Let'slookatthenextline:
movl%eax,%ebx

Wehavethefirstitemtolookatstoredin%eax.Sinceitisthe
firstitem,weknowit'sthebiggestonewe'velookedat.Westoreit
in%ebx,sincethat'swherewearekeepingthelargestnumberfound.
Also,eventhoughmovlstandsfor
move,
itactuallycopiesthevalue,
11]
so%eaxand%ebxbothcontainthestartingvalue.[

Nowwemoveintoa
loop.
Aloopisasegmentofyourprogramthat
mightrunmorethanonce.Wehavemarkedthestartinglocationofthe
loopinthesymbolstart_loop.Thereasonwearedoingaloopis

becausewedon'tknowhowmanydataitemswehavetoprocess,butthe
procedurewillbethesamenomatterhowmanythereare.Wedon't
wanttohavetorewriteourprogramforeverylistlengthpossible.
Infact,wedon'tevenwanttohavetowriteoutcodefora
comparisonforeverylistitem.Therefore,wehaveasinglesection
ofcode(aloop)thatweexecuteoverandoveragainforevery
elementindata_items.
Intheprevioussection,weoutlinedwhatthisloopneededtodo.
Let'sreview:
Checktoseeifthecurrentvaluebeinglookedatiszero.Ifso,
thatmeansweareattheendofourdataandshouldexittheloop.
Wehavetoloadthenextvalueofourlist.
Wehavetoseeifthenextvalueisbiggerthanourcurrentbiggest
value.
Ifitis,wehavetocopyittothelocationweareholdingthe
largestvaluein.
Nowweneedtogobacktothebeginningoftheloop.
Okay,sonowletsgotothecode.Wehavethebeginningoftheloop
markedwithstart_loop.Thatissoweknowwheretogobacktoatthe
endofourloop.Thenwehavetheseinstructions:
cmpl$0,%eax
jeloop_exit

Thecmplinstructioncomparesthetwovalues.Here,wearecomparing
thenumber0tothenumberstoredin%eaxThiscompareinstruction
alsoaffectsaregisternotmentionedhere,the%eflagsregister.
Thisisalsoknownasthestatusregister,andhasmanyuseswhichwe
willdiscusslater.Justbeawarethattheresultofthecomparison
isstoredinthestatusregister.Thenextlineisaflowcontrol
instructionwhichsaysto
jump
totheloop_exitlocationifthe
valuesthatwerejustcomparedareequal(that'swhattheeofje
means).Itusesthestatusregistertoholdthevalueofthelast
comparison.Weusedje,buttherearemanyjumpstatementsthatyou
canuse:
je
Jumpifthevalueswereequal
jg
12]
Jumpifthesecondvaluewasgreaterthanthefirstvalue[

jge
Jumpifthesecondvaluewasgreaterthanorequaltothefirstvalue
jl
Jumpifthesecondvaluewaslessthanthefirstvalue

jle
Jumpifthesecondvaluewaslessthanorequaltothefirstvalue
jmp
Jumpnomatterwhat.Thisdoesnotneedtobepreceededbya
comparison.
ThecompletelistisdocumentedinAppendixB.Inthiscase,weare
jumpingif%eaxholdsthevalueofzero.Ifso,wearedoneandwego
13]
toloop_exit.[

Ifthelastloadedelementwasnotzero,wegoontothenext
instructions:
incl%edi
movldata_items(,%edi,4),%eax

Ifyourememberfromourpreviousdiscussion,%edicontainstheindex
toourlistofvaluesindata_items.inclincrementsthevalueof%edi
byone.Thenthemovlisjustliketheonewedidbeforehand.
However,sincewealreadyincremented%edi,%eaxisgettingthenext
valuefromthelist.Now%eaxhasthenextvaluetobetested.So,
let'stestit!
cmpl%ebx,%eax
jlestart_loop

Herewecompareourcurrentvalue,storedin%eaxtoourbiggest
valuesofar,storedin%ebx.Ifthecurrentvalueislessorequal
toourbiggestvaluesofar,wedon'tcareaboutit,sowejustjump
backtothebeginningoftheloop.Otherwise,weneedtorecordthat
valueasthelargestone:
movl%eax,%ebx
jmpstart_loop

whichmovesthecurrentvalueinto%ebx,whichweareusingtostore
thecurrentlargestvalue,andstartstheloopoveragain.
Okay,sotheloopexecutesuntilitreachesa0,whenitjumpsto
loop_exit.ThispartoftheprogramcallstheLinuxkerneltoexit.
Ifyourememberfromthelastprogram,whenyoucalltheoperating
system(rememberit'slikesignalingBatman),youstorethesystem
callnumberin%eax(1fortheexitcall),andstoretheothervalues
intheotherregisters.Theexitcallrequiresthatweputourexit
statusin%ebxWealreadyhavetheexitstatustheresinceweare
using%ebxasourlargestnumber,soallwehavetodoisload%eax
withthenumberoneandcallthekerneltoexit.Likethis:

movl$1,%eax
int$0x80

Okay,thatwasalotofworkandexplanation,especiallyforsucha
smallprogram.Buthey,you'relearningalot!Now,readthroughthe
wholeprogramagain,payingspecialattentiontothecomments.Make
surethatyouunderstandwhatisgoingonateachline.Ifyoudon't
understandaline,gobackthroughthissectionandfigureoutwhat
thelinemeans.
Youmightalsograbapieceofpaper,andgothroughtheprogram
stepbystep,recordingeverychangetoeveryregister,soyoucan
seemoreclearlywhatisgoingon.
[9]
Notethatnonumbersinassemblylanguage(oranyothercomputer
languageI'veseen)havecommasembeddedinthem.So,alwayswrite
numberslike65535,andneverlike65,535.
[10]
Theinstructiondoesn'treallyuse4forthesizeofthestorage
locations,althoughlookingatitthatwayworksforourpurposes
now.It'sactuallywhat'scalleda
multiplier.
basically,thewayit
worksisthatyoustartatthelocationspecifiedbydata_items,then
youadd%edi*4storagelocations,andretrievethenumberthere.
Usually,youusethesizeofthenumbersasyourmultiplier,butin
somecircumstancesyou'llwanttodootherthings.
[11]
Also,the1inmovlstandsfor
movelong
sincewearemovinga
valuethattakesupfourstoragelocations.
[12]
noticethatthecomparisonistoseeifthe
second
valueisgreater
thanthefirst.Iwouldhavethoughtittheotherwayaround.You
willfindalotofthingslikethiswhenlearningprogramming.It
occursbecausedifferentthingsmakesensetodifferentpeople.
Anyway,you'lljusthavetomemorizesuchthingsandgoon.
[13]
Thenamesofthesesymbolscanbeanythingyouwantthemtobe,as
longastheyonlycontainlettersandtheunderscorecharacter(_).
Theonlyonethatisforcedis_start,andpossiblyothersthatyou
declarewith.globl.However,ifitisasymbolyoudefineandonly
youuse,feelfreetocallitanythingyouwantthatisadequately
descriptive(rememberthatotherswillhavetomodifyyourcode
later,andwillhavetofigureoutwhatyoursymbolsmean).

AddressingModes
IntheSectioncalled
DataAccessingMethods
inChapter2welearned
thedifferenttypesofaddressingmodesavailableforuseinassembly
language.Thissectionwilldealwithhowthoseaddressingmodesare
representedinassemblylanguageinstructions.
Thegeneralformofmemoryaddressreferencesisthis:
ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)

Allofthefieldsareoptional.Tocalculatetheaddress,simply
performthefollowingcalculation:
FINALADDRESS=ADDRESS_OR_OFFSET+%BASE_OR_OFFSET+MULTIPLIER*
%INI

ADDRESS_OR_OFFSETandMULTIPLIERmustbothbeconstants,whilethe
othertwomustberegisters.Ifanyofthepiecesisleftout,itis
justsubstitutedwithzerointheequation.
AlloftheaddressingmodesmentionedintheSectioncalled
Data
AccessingMethods
inChapter2exceptimmediatemodecanbe
representedinthisfashion.
directaddressingmode
ThisisdonebyonlyusingtheADDRESS_OR_OFFSETportion.Example:
movlADDRESS,%eax

Thisloads%eaxwiththevalueatmemoryaddressADDRESS.
indexedaddressingmode
ThisisdonebyusingtheADDRESS_OR_OFFSETandthe%INDEXportion.
Youcanuseanygeneralpurposeregisterastheindexregister.You
canalsohaveaconstantmultiplierof1,2,or4fortheindex
register,tomakeiteasiertoindexbybytes,doublebytes,and
words.Forexample,let'ssaythatwehadastringofbytesas
string_startandwantedtoaccessthethirdone(anindexof2since
westartcountingtheindexatzero),and%ecxheldthevalue2.If
youwantedtoloaditinto%eaxyoucoulddothefollowing:
movlstring_start(,%ecx,1),%eax

Thisstartsatstring_start,andadds1*%ecxtothataddress,and
loadsthevalueinto%eax.

indirectaddressingmode
Indirectaddressingmodeloadsavaluefromtheaddressindicatedby
aregister.Forexample,if%eaxheldanaddress,wecouldmovethe
valueatthataddressto%ebxbydoingthefollowing:
movl(%eax),%ebx

basepointeraddressingmode
Basepointeraddressingissimilartoindirectaddressing,except
thatitaddsaconstantvaluetotheaddressintheregister.For
example,ifyouhavearecordwheretheagevalueis4bytesintothe
record,andyouhavetheaddressoftherecordin%eax,youcan
retrievetheageinto%ebxbyissuingthefollowinginstruction:
movl4(%eax),%ebx

immediatemode
Immediatemodeisverysimple.Itdoesnotfollowthegeneralformwe
havebeenusing.Immediatemodeisusedtoloaddirectvaluesinto
registersormemorylocations.Forexample,ifyouwantedtoloadthe
number12into%eax,youwouldsimplydothefollowing:
movl$12,%eax

Noticethattoindicateimmediatemode,weusedadollarsignin
frontofthenumber.Ifwedidnot,itwouldbedirectaddressing
mode,inwhichcasethevaluelocatedatmemorylocation12wouldbe
loadedinto%eaxratherthanthenumber12itself.
registeraddressingmode
Registermodesimplymovesdatainoroutofaregister.Inallof
ourexamples,registeraddressingmodewasusedfortheother
operand.
Theseaddressingmodesareveryimportant,aseverymemoryaccess
willuseoneofthese.Everymodeexceptimmediatemodecanbeused
aseitherthesourceordestinationoperand.Immediatemodecanonly
beasourceoperand.
Inadditiontothesemodes,therearealsodifferentinstructionsfor
differentsizesofvaluestomove.Forexample,wehavebeenusing
movltomovedataawordatatime.inmanycases,youwillonlywant
tomovedataabyteatatime.Thisisaccomplishedbythe
instructionmovb.However,sincetheregisterswehavediscussedare
wordsizedandnotbytesized,youcannotusethefullregister.
Instead,youhavetouseaportionoftheregister.
Takeforinstance%eax.Ifyouonlywantedtoworkwithtwobytesat
atime,youcouldjustuse%ax.%axistheleastsignificanthalf
(i.e.thelastpartofthenumber)ofthe%eaxregister,andis

usefulwhendealingwithtwobytequantities.%axisfurtherdivided
upinto%aland%ah.%alistheleastsignificantbyteof%ax,and
14]
%ahisthemostsignificantbyte.[

Loadingavalueinto%eaxwill
wipeoutwhateverwasin%aland%ah(andalso%ax,since%axismade
upofthem).Similarly,loadingavalueintoeither%alor%ahwill
corruptanyvaluethatwasformerlyin%eax.Basically,it'swiseto
onlyusearegisterforeitherabyteoraword,butneverbothat
thesametime.

Layoutofthe%eaxregister
Foramorecomprehensivelistofinstructions,seeAppendixB.
[14]
Whenwetalkaboutthemostorleast
significant
byte,itmaybea
littleconfusing.Let'stakethenumber5432.Inthatnumber,54is
themostsignificanthalfofthatnumberand32istheleast
significanthalf.Youcan'tquitedivideitlikethatforregisters,
sincetheyoperateonbase2ratherthanbase10numbers,butthat's
thebasicidea.Formoreinformationonthistopic,seeChapter10.

Review
KnowtheConcepts
Whatdoesitmeanifalineintheprogramstartswiththe'#'
character?
Whatisthedifferencebetweenanassemblylanguagefileandan
objectcodefile?
Whatdoesthelinkerdo?
Howdoyouchecktheresultstatuscodeofthelastprogramyouran?
Whatisthedifferencebetweenmovl$1,%eaxandmovl1,%eax?
Whichregisterholdsthesystemcallnumber?

Whatareindexesusedfor?
Whydoindexesusuallystartat0?
IfIissuedthecommandmovldata_items(,%edi,4),%eaxand
data_itemswasaddress3634and%ediheldthevalue13,whataddress
wouldyoubeusingtomoveinto%eax?
Listthegeneralpurposeregisters.
Whatisthedifferencebetweenmovlandmovb?
Whatisflowcontrol?
Whatdoesaconditionaljumpdo?
Whatthingsdoyouhavetoplanforwhenwritingaprogram?
Gothrougheveryinstructionandlistwhataddressingmodeisbeing
usedforeachoperand.
UsetheConcepts
Modifythefirstprogramtoreturnthevalue3.
Modifythemaximumprogramtofindtheminimuminstead.
Modifythemaximumprogramtousethenumber255toendthelist
ratherthanthenumber0
Modifythemaximumprogramtouseanendingaddressratherthanthe
number0toknowwhentostop.
Modifythemaximumprogramtousealengthcountratherthanthe
number0toknowwhentostop.
Whatwouldtheinstructionmovl_start,%eaxdo?Bespecific,based
onyourknowledgeofbothaddressingmodesandthemeaningof_start.
Howwouldthisdifferfromtheinstructionmovl$_start,%eax?
GoingFurther
Modifythefirstprogramtoleaveofftheintinstructionline.
Assemble,link,andexecutethenewprogram.Whaterrormessagedo
youget.Whydoyouthinkthismightbe?
Sofar,wehavediscussedthreeapproachestofindingtheendofthe
listusingaspecialnumber,usingtheendingaddress,andusing
thelengthcount.Whichapproachdoyouthinkisbest?Why?Which
approachwouldyouuseifyouknewthatthelistwassorted?Why?

Chapter4:AllAboutFunctions
DealingwithComplexity
InChapter3,theprogramswewroteonlyconsistedofonesectionof
code.However,ifwewroterealprogramslikethat,itwouldbe
impossibletomaintainthem.Itwouldbereallydifficulttoget
multiplepeopleworkingontheproject,asanychangeinonepart

mightadverselyaffectanotherpartthatanotherdeveloperisworking
on.
Toassistprogrammersinworkingtogetheringroups,itisnecessary
tobreakprogramsapartintoseparatepieces,whichcommunicatewith
eachotherthroughwelldefinedinterfaces.Thisway,eachpiececan
bedevelopedandtestedindependentlyoftheothers,makingiteasier
formultipleprogrammerstoworkontheproject.
Programmersuse
functions
tobreaktheirprogramsintopieceswhich
canbeindependentlydevelopedandtested.Functionsareunitsof
codethatdoadefinedpieceofworkonspecifiedtypesofdata.For
example,inawordprocessorprogram,Imayhaveafunctioncalled
handle_typed_characterwhichisactivatedwheneverausertypesina
key.Thedatathefunctionuseswouldprobablybethekeypressitself
andthedocumenttheusercurrentlyhasopen.Thefunctionwouldthen
modifythedocumentaccordingtothekeypressitwastoldabout.
Thedataitemsafunctionisgiventoprocessarecalledits
parameters
.Inthewordprocessingexample,thekeywhichwaspressed
andthedocumentwouldbeconsideredparameterstothe
handle_typed_charactersfunction.Theparameterlistandthe
processingexpectationsofafunction(whatitisexpectedtodowith
theparameters)arecalledthefunction'sinterface.Muchcaregoes
intodesigningfunctioninterfaces,becauseiftheyarecalledfrom
manyplaceswithinaproject,itisdifficulttochangethemif
necessary.
Atypicalprogramiscomposedofhundredsorthousandsoffunctions,
eachwithasmall,welldefinedtasktoperform.However,ultimately
therearethingsthatyoucannotwritefunctionsforwhichmustbe
providedbythesystem.Thosearecalled
primitivefunctions
(orjust
primitives
)theyarethebasicswhicheverythingelseisbuiltoff
of.Forexample,imagineaprogramthatdrawsagraphicaluser
interface.Therehastobeafunctiontocreatethemenus.That
functionprobablycallsotherfunctionstowritetext,towrite
icons,topaintthebackground,calculatewherethemousepointeris,
etc.However,ultimately,theywillreachasetofprimitives
providedbytheoperatingsystemtodobasiclineorpointdrawing.
Programmingcaneitherbeviewedasbreakingalargeprogramdown
intosmallerpiecesuntilyougettotheprimitivefunctions,or
incrementallybuildingfunctionsontopofprimitivesuntilyouget
thelargepictureinfocus.Inassemblylanguage,theprimitivesare
usuallythesamethingasthesystemcalls,eventhoughsystemcalls
aren'ttruefunctionsaswewilltalkaboutinthischapter.

HowFunctionsWork

Functionsarecomposedofseveraldifferentpieces:
functionname
Afunction'snameisasymbolthatrepresentstheaddresswherethe
function'scodestarts.Inassemblylanguage,thesymbolisdefined
bytypingthefunction'snameasalabelbeforethefunction'scode.
Thisisjustlikelabelsyouhaveusedforjumping.
functionparameters
Afunction'sparametersarethedataitemsthatareexplicitlygiven
tothefunctionforprocessing.Forexample,inmathematics,thereis
asinefunction.Ifyouweretoaskacomputertofindthesineof2,
sinewouldbethefunction'sname,and2wouldbetheparameter.Some
1]
functionshavemanyparameters,othershavenone.[

localvariables
Localvariablesaredatastoragethatafunctionuseswhile
processingthatisthrownawaywhenitreturns.It'skindoflikea
scratchpadofpaper.Functionsgetanewpieceofpapereverytime
theyareactivated,andtheyhavetothrowitawaywhentheyare
finishedprocessing.Localvariablesofafunctionarenotaccessible
toanyotherfunctionwithinaprogram.
staticvariables
Staticvariablesaredatastoragethatafunctionuseswhile
processingthatisnotthrownawayafterwards,butisreusedfor
everytimethefunction'scodeisactivated.Thisdataisnot
accessibletoanyotherpartoftheprogram.Staticvariablesare
generallynotusedunlessabsolutelynecessary,astheycancause
problemslateron.
globalvariables
Globalvariablesaredatastoragethatafunctionusesforprocessing
whicharemanagedoutsidethefunction.Forexample,asimpletext
editormayputtheentirecontentsofthefileitisworkingonina
globalvariablesoitdoesn'thavetobepassedtoeveryfunction
2]
thatoperatesonit.[

Configurationvaluesarealsooftenstoredin
globalvariables.
returnaddress
Thereturnaddressisan"invisible"parameterinthatitisn't
directlyusedduringthefunction.Thereturnaddressisaparameter
whichtellsthefunctionwheretoresumeexecutingafterthefunction
iscompleted.Thisisneededbecausefunctionscanbecalledtodo
processingfrommanydifferentpartsofyourprogram,andthe
functionneedstobeabletogetbacktowhereveritwascalledfrom.
Inmostprogramminglanguages,thisparameterispassedautomatically
whenthefunctioniscalled.Inassemblylanguage,thecall
instructionhandlespassingthereturnaddressforyou,andret

handlesusingthataddresstoreturnbacktowhereyoucalledthe
functionfrom.
returnvalue
Thereturnvalueisthemainmethodoftransferringdatabacktothe
mainprogram.Mostprogramminglanguagesonlyallowasinglereturn
valueforafunction.
Thesepiecesarepresentinmostprogramminglanguages.Howyou
specifyeachpieceisdifferentineachone,however.
Thewaythatthevariablesarestoredandtheparametersandreturn
valuesaretransferredbythecomputervariesfromlanguageto
languageaswell.Thisvarianceisknownasalanguage's
calling
convention,
becauseitdescribeshowfunctionsexpecttogetand
3]
receivedatawhentheyarecalled.[

Assemblylanguagecanuseanycallingconventionitwantsto.Youcan
evenmakeoneupyourself.However,ifyouwanttointeroperatewith
functionswritteninotherlanguages,youhavetoobeytheircalling
conventions.WewillusethecallingconventionoftheCprogramming
languageforourexamplesbecauseitisthemostwidelyused,and
becauseitisthestandardforLinuxplatforms.
[1]
Functionparameterscanalsobeusedtoholdpointerstodatathat
thefunctionwantstosendbacktotheprogram.
[2]
Thisisgenerallyconsideredbadpractice.Imagineifaprogramis
writtenthisway,andinthenextversiontheydecidedtoallowa
singleinstanceoftheprogrameditmultiplefiles.Eachfunction
wouldthenhavetobemodifiedsothatthefilethatwasbeing
manipulatedwouldbepassedasaparameter.Ifyouhadsimplypassed
itasaparametertobeginwith,mostofyourfunctionscouldhave
survivedyourupgradeunchanged.
[3]
A
convention
isawayofdoingthingsthatisstandardized,butnot
forciblyso.Forexample,itisaconventionforpeopletoshake
handswhentheymeet.IfIrefusetoshakehandswithyou,youmay
thinkIdon'tlikeyou.Followingconventionsisimportantbecauseit
makesiteasierforotherstounderstandwhatyouaredoing,and
makesiteasierforprogramswrittenbymultipleindependentauthors
toworktogether.

AssemblyLanguageFunctionsusingtheC
CallingConvention
Youcannotwriteassemblylanguagefunctionswithoutunderstanding
howthecomputer's
stack
works.Eachcomputerprogramthatrunsuses
aregionofmemorycalledthestacktoenablefunctionstowork
properly.Thinkofastackasapileofpapersonyourdeskwhichcan

beaddedtoindefinitely.Yougenerallykeepthethingsthatyouare
workingontowardthetop,andyoutakethingsoffasyouare
finishedworkingwiththem.
Yourcomputerhasastack,too.Thecomputer'sstacklivesatthe
verytopaddressesofmemory.Youcanpushvaluesontothetopofthe
stackthroughaninstructioncalledpushl,whichpusheseithera
registerormemoryvalueontothetopofthestack.Well,wesayit's
thetop,butthe"top"ofthestackisactuallythebottomofthe
stack'smemory.Althoughthisisconfusing,thereasonforitisthat
whenwethinkofastackofanythingdishes,papers,etc.we
thinkofaddingandremovingtothetopofit.However,inmemorythe
stackstartsatthetopofmemoryandgrowsdownwarddueto
architecturalconsiderations.Therefore,whenwerefertothe"topof
thestack"rememberit'satthebottomofthestack'smemory.Youcan
alsopopvaluesoffthetopusinganinstructioncalledpopl.This
removesthetopvaluefromthestackandplacesitintoaregisteror
memorylocationofyourchoosing..
Whenwepushavalueontothestack,thetopofthestackmovesto
accomodatetheadditionalvalue.Wecanactuallycontinuallypush
valuesontothestackanditwillkeepgrowingfurtherandfurther
downinmemoryuntilwehitourcodeordata.Sohowdoweknowwhere
thecurrent"top"ofthestackis?Thestackregister,%esp,always
containsapointertothecurrenttopofthestack,whereveritis.
Everytimewepushsomethingontothestackwithpushl,%espgets
subtractedby4sothatitpointstothenewtopofthestack
(remember,eachwordisfourbyteslong,andthestackgrows
downward).Ifwewanttoremovesomethingfromthestack,wesimply
usethepoplinstruction,whichadds4to%espandputstheprevious
topvalueinwhateverregisteryouspecified.pushlandpopleach
takeoneoperandtheregistertopushontothestackforpushl,or
receivethedatathatispoppedoffthestackforpopl.
Ifwesimplywanttoaccessthevalueonthetopofthestackwithout
removingit,wecansimplyusethe%espregisterinindirect
addressingmode.Forexample,thefollowingcodemoveswhateverisat
thetopofthestackinto%eax:
movl(%esp),%eax

Ifweweretojustdothis:
movl%esp,%eax

then%eaxwouldjustholdthepointertothetopofthestackrather
thanthevalueatthetop.Putting%espinparenthesiscausesthe
computertogotoindirectaddressingmode,andthereforewegetthe

valuepointedtoby%esp.Ifwewanttoaccessthevaluerightbelow
thetopofthestack,wecansimplyissuethisinstruction:
movl4(%esp),%eax

Thisinstructionusesthebasepointeraddressingmode(seethe
Sectioncalled
DataAccessingMethods
inChapter2)whichsimplyadds
4to%espbeforelookingupthevaluebeingpointedto.
IntheClanguagecallingconvention,thestackisthekeyelement
forimplementingafunction'slocalvariables,parameters,andreturn
address.
Beforeexecutingafunction,aprogrampushesalloftheparameters
forthefunctionontothestackinthereverseorderthattheyare
documented.Thentheprogramissuesacallinstructionindicating
whichfunctionitwishestostart.Thecallinstructiondoestwo
things.Firstitpushestheaddressofthenextinstruction,whichis
thereturnaddress,ontothestack.Thenitmodifiestheinstruction
pointer(%eip)topointtothestartofthefunction.So,atthetime
thefunctionstarts,thestacklookslikethis(the"top"ofthe
stackisatthebottomonthisexample):
Parameter#N
...
Parameter2
Parameter1
ReturnAddress<(%esp)

Eachoftheparametersofthefunctionhavebeenpushedontothe
stack,andfinallythereturnaddressisthere.Nowthefunction
itselfhassomeworktodo.
Thefirstthingitdoesissavethecurrentbasepointerregister,
%ebp,bydoingpushl%ebp.Thebasepointerisaspecialregister
usedforaccessingfunctionparametersandlocalvariables.Next,it
copiesthestackpointerto%ebpbydoingmovl%esp,%ebp.This
allowsyoutobeabletoaccessthefunctionparametersasfixed
indexesfromthebasepointer.Youmaythinkthatyoucanusethe
stackpointerforthis.However,duringyourprogramyoumaydoother
thingswiththestacksuchaspushingargumentstootherfunctions.
Copyingthestackpointerintothebasepointeratthebeginningofa
functionallowsyoutoalwaysknowwhereyourparametersare(andas
wewillsee,localvariablestoo),evenwhileyoumaybepushing
thingsonandoffthestack.%ebpwillalwaysbewherethestack
pointerwasatthebeginningofthefunction,soitismoreorlessa
constantreferencetothe
stackframe
(thestackframeconsistsof

allofthestackvariablesusedwithinafunction,including
parameters,localvariables,andthereturnaddress).
Atthispoint,thestacklookslikethis:
Parameter#N<N*4+4(%ebp)
...
Parameter2<12(%ebp)
Parameter1<8(%ebp)
ReturnAddress<4(%ebp)
Old%ebp<(%esp)and(%ebp)

Asyoucansee,eachparametercanbeaccessedusingbasepointer
addressingmodeusingthe%ebpregister.
Next,thefunctionreservesspaceonthestackforanylocal
variablesitneeds.Thisisdonebysimplymovingthestackpointer
outoftheway.Let'ssaythatwearegoingtoneedtwowordsof
memorytorunafunction.Wecansimplymovethestackpointerdown
twowordstoreservethespace.Thisisdonelikethis:
subl$8,%esp

4]
Thissubtracts8from%esp(remember,awordisfourbyteslong).[

Thisway,wecanusethestackforvariablestoragewithoutworring
aboutclobberingthemwithpushesthatwemaymakeforfunction
calls.Also,sinceitisallocatedonthestackframeforthis
functioncall,thevariablewillonlybealiveduringthisfunction.
Whenwereturn,thestackframewillgoaway,andsowillthese
variables.That'swhytheyarecalledlocaltheyonlyexistwhile
thisfunctionisbeingcalled.
Nowwehavetwowordsforlocalstorage.Ourstacknowlookslike
this:
Parameter#N<N*4+4(%ebp)
...
Parameter2<12(%ebp)
Parameter1<8(%ebp)
ReturnAddress<4(%ebp)
Old%ebp<(%ebp)
LocalVariable1<4(%ebp)
LocalVariable2<8(%ebp)and(%esp)

Sowecannowaccessallofthedataweneedforthisfunctionby
usingbasepointeraddressingusingdifferentoffsetsfrom%ebp.%ebp
wasmadespecificallyforthispurpose,whichiswhyitiscalledthe
basepointer.Youcanuseotherregistersinbasepointeraddressing

mode,butthex86architecturemakesusingthe%ebpregisteralot
faster.
Globalvariablesandstaticvariablesareaccessedjustlikethe
memorywehavebeenaccessingmemoryinpreviouschapters.Theonly
differencebetweentheglobalandstaticvariablesisthatstatic
variablesareonlyusedbyonefunction,whileglobalvariablesare
usedbymanyfunctions.Assemblylanguagetreatsthemexactlythe
same,althoughmostotherlanguagesdistinguishthem.
Whenafunctionisdoneexecuting,itdoesthreethings:
Itstoresitsreturnvaluein%eax.
Itresetsthestacktowhatitwaswhenitwascalled(itgetsridof
thecurrentstackframeandputsthestackframeofthecallingcode
backintoeffect).
Itreturnscontrolbacktowhereveritwascalledfrom.Thisisdone
usingtheretinstruction,whichpopswhatevervalueisatthetopof
thestack,andsetstheinstructionpointer,%eip,tothatvalue.
So,beforeafunctionreturnscontroltothecodethatcalledit,it
mustrestorethepreviousstackframe.Notealsothatwithoutdoing
this,retwouldn'twork,becauseinourcurrentstackframe,the
returnaddressisnotatthetopofthestack.Therefore,beforewe
return,wehavetoresetthestackpointer%espandbasepointer%ebp
towhattheywerewhenthefunctionbegan.
Thereforetoreturnfromthefunctionyouhavetodothefollowing:
movl%ebp,%esp
popl%ebp
ret

Atthispoint,youshouldconsideralllocalvariablestobedisposed
of.
Thereasonisthatafteryoumovethestackpointerback,future
stackpusheswilllikelyoverwriteeverythingyouputthere.
Therefore,youshouldneversavetheaddressofalocalvariablepast
thelifeofthefunctionitwascreatedin,orelseitwillbe
overwrittenafterthelifeofitsstackframeends.
Controlhasnowbeenhandedbacktothecallingcode,whichcannow
examine%eaxforthereturnvalue.Thecallingcodealsoneedstopop
offalloftheparametersitpushedontothestackinordertoget
thestackpointerbackwhereitwas(youcanalsosimplyadd4*
numberofparametersto%espusingtheaddlinstruction,ifyoudon't
5]
needthevaluesoftheparametersanymore).[

DestructionofRegisters

Whenyoucallafunction,youshouldassumethateverythingcurrently
inyourregisterswillbewipedout.Theonlyregisterthatis
guaranteedtobeleftwiththevalueitstartedwithare%ebpanda
fewothers(theLinuxCcallingconventionrequiresfunctionsto
preservethevaluesof%ebx,%edi,and%esiiftheyarealtered
thisisnotstrictlyheldduringthisbookbecausetheseprogramsare
selfcontainedandnotcalledbyoutsidefunctions).%ebxalsohas
someotherusesinpositionindependentcode,whichisnotcoveredin
thisbook.%eaxisguaranteedtobeoverwrittenwiththereturn
value,andtheotherslikelyare.Ifthereareregistersyouwantto
savebeforecallingafunction,youneedtosavethembypushingthem
onthestackbeforepushingthefunction'sparameters.Youcanthen
popthembackoffinreverseorderafterpoppingofftheparameters.
Evenifyouknowafunctiondoesnotoverwritearegisteryoushould
saveit,becausefutureversionsofthatfunctionmay.
NotethatinLinuxassemblylanguage,functionsare
Otherlanguages'callingconventionsmaybedifferent.Forexample,
othercallingconventionsmayplacetheburdenonthefunctionto
saveanyregistersituses.Besuretochecktomakesurethecalling
conventionsofyourlanguagesarecompatiblebeforetryingtomix
languages.Orinthecaseofassemblylanguage,besureyouknowhow
tocalltheotherlanguage'sfunctions.

ExtendedSpecification:
DetailsoftheClanguagecallingconvention
(alsoknownastheABI,orApplicationBinaryInterface)isavailable
online.Wehaveoversimplifiedandleftoutseveralimportantpieces
tomakethissimplerfornewprogrammers.Forfulldetails,you
shouldcheckoutthedocumentsavailableat
http://www.linuxbase.org/spec/refspecs/Specifically,youshouldlook
forthe
SystemVApplicationBinaryInterfaceIntel386Architecture
ProcessorSupplement.
[4]
Justareminderthedollarsigninfrontoftheeightindicates
immediatemodeaddressing,meaningthatwesubtractthenumber8
itselffrom%espratherthanthevalueataddress8.
[5]
Thisisnotalwaysstrictlyneededunlessyouaresavingregisters
onthestackbeforeafunctioncall.Thebasepointerkeepsthestack
frameinareasonablyconsistentstate.However,itisstillagood
idea,andisabsolutelynecessaryifyouaretemporarilysaving
registersonthestack..

AFunctionExample
Let'stakealookathowafunctioncallworksinarealprogram.The
functionwearegoingtowriteisthepowerfunction.Wewillgive
thepowerfunctiontwoparametersthenumberandthepowerwewant
toraiseitto.Forexample,ifwegaveittheparameters2and3,it
wouldraise2tothepowerof3,or2*2*2,giving8.Inordertomake
thisprogramsimple,wewillonlyallownumbers1andgreater.
Thefollowingisthecodeforthecompleteprogram.Asusual,an
explanationfollows.Namethefilepower.s.
#PURPOSE:Programtoillustratehowfunctionswork
#Thisprogramwillcomputethevalueof
#2^3+5^2
#

#Everythinginthemainprogramisstoredinregisters,
#sothedatasectiondoesn'thaveanything.
.section.data

.section.text

.globl_start
_start:
pushl$3#pushsecondargument
pushl$2#pushfirstargument
callpower#callthefunction
addl$8,%esp#movethestackpointerback

pushl%eax#savethefirstanswerbefore
#callingthenextfunction
pushl$2#pushsecondargument
pushl$5#pushfirstargument
callpower#callthefunction
addl$8,%esp#movethestackpointerback

popl%ebx#Thesecondanswerisalready
#in%eax.Wesavedthe
#firstanswerontothestack,
#sonowwecanjustpopit
#outinto%ebx

addl%eax,%ebx#addthemtogether

#theresultisin%ebx

movl$1,%eax#exit(%ebxisreturned)
int$0x80

#PURPOSE:Thisfunctionisusedtocompute
#thevalueofanumberraisedto
#apower.
#
#INPUT:Firstargumentthebasenumber
#Secondargumentthepowerto
#raiseitto
#
#OUTPUT:Willgivetheresultasareturnvalue
#
#NOTES:Thepowermustbe1orgreater
#
#VARIABLES:
#%ebxholdsthebasenumber
#%ecxholdsthepower
#
#4(%ebp)holdsthecurrentresult
#
#%eaxisusedfortemporarystorage
#
.typepower,@function
power:
pushl%ebp#saveoldbasepointer
movl%esp,%ebp#makestackpointerthebasepointer
subl$4,%esp#getroomforourlocalstorage

movl8(%ebp),%ebx#putfirstargumentin%ebx
movl12(%ebp),%ecx#putsecondargumentin%ecx

movl%ebx,4(%ebp)#storecurrentresult

power_loop_start:
cmpl$1,%ecx#ifthepoweris1,wearedone
jeend_power
movl4(%ebp),%eax#movethecurrentresultinto%eax
imull%ebx,%eax#multiplythecurrentresultby
#thebasenumber
movl%eax,4(%ebp)#storethecurrentresult


decl%ecx#decreasethepower
jmppower_loop_start#runforthenextpower

end_power:
movl4(%ebp),%eax#returnvaluegoesin%eax
movl%ebp,%esp#restorethestackpointer
popl%ebp#restorethebasepointer
ret

Typeintheprogram,assembleit,andrunit.Trycallingpowerfor
differentvalues,butrememberthattheresulthastobelessthan
256whenitispassedbacktotheoperatingsystem.Alsotry
subtractingtheresultsofthetwocomputations.Tryaddingathird
calltothepowerfunction,andadditsresultbackin.
Themainprogramcodeisprettysimple.Youpushtheargumentsonto
thestack,callthefunction,andthenmovethestackpointerback.
Theresultisstoredin%eax.Notethatbetweenthetwocallsto
power,wesavethefirstvalueontothestack.Thisisbecausethe
onlyregisterthatisguaranteedtobesavedis%ebp.Thereforewe
pushthevalueontothestack,andpopthevaluebackoffafterthe
secondfunctioncalliscomplete.
Let'slookathowthefunctionitselfiswritten.Noticethatbefore
thefunction,thereisdocumentationastowhatthefunctiondoes,
whatitsargumentsare,andwhatitgivesasareturnvalue.Thisis
usefulforprogrammerswhousethisfunction.Thisisthefunction's
interface.Thisletstheprogrammerknowwhatvaluesareneededon
thestack,andwhatwillbein%eaxattheend.
Wethenhavethefollowingline:
.typepower,@function

Thistellsthelinkerthatthesymbolpowershouldbetreatedasa
function.Sincethisprogramisonlyinonefile,itwouldworkjust
thesamewiththisleftout.However,itisgoodpractice.
Afterthat,wedefinethevalueofthepowerlabel:
power:

Asmentionedpreviously,thisdefinesthesymbolpowertobethe
addresswheretheinstructionsfollowingthelabelbegin.Thisishow
callpowerworks.Ittransferscontroltothisspotoftheprogram.
Thedifferencebetweencallandjmpisthatcallalsopushesthe
returnaddressontothestacksothatthefunctioncanreturn,while
thejmpdoesnot.

Next,wehaveourinstructionstosetupourfunction:
pushl%ebp
movl%esp,%ebp
subl$4,%esp

Atthispoint,ourstacklookslikethis:
BaseNumber<12(%ebp)
Power<8(%ebp)
ReturnAddress<4(%ebp)
Old%ebp<(%ebp)
Currentresult<4(%ebp)and(%esp)

Althoughwecouldusearegisterfortemporarystorage,thisprogram
usesalocalvariableinordertoshowhowtosetitup.Oftentimes
therejustaren'tenoughregisterstostoreeverything,soyouhave
tooffloadthemintolocalvariables.Othertimes,yourfunctionwill
needtocallanotherfunctionandsenditapointertosomeofyour
data.Youcan'thaveapointertoaregister,soyouhavetostoreit
inalocalvariableinordertosendapointertoit.
Basically,whattheprogramdoesisstartwiththebasenumber,and
storeitbothasthemultiplier(storedin%ebx)andthecurrent
value(storedin4(%ebp)).Italsohasthepowerstoredin%ecxIt
thencontinuallymultipliesthecurrentvaluebythemultiplier,
decreasesthepower,andleavestheloopifthepower(in%ecx)gets
downto1.
Bynow,youshouldbeabletogothroughtheprogramwithouthelp.
Theonlythingsyoushouldneedtoknowisthatimulldoesinteger
multiplicationandstorestheresultinthesecondoperand,anddecl
decreasesthegivenregisterby1.Formoreinformationontheseand
otherinstructions,seeAppendixB
Agoodprojecttotrynowistoextendtheprogramsoitwillreturn
thevalueofanumberifthepoweris0(hint,anythingraisedtothe
zeropoweris1).Keeptrying.Ifitdoesn'tworkatfirst,trygoing
throughyourprogrambyhandwithascrapofpaper,keepingtrackof
where%ebpand%esparepointing,whatisonthestack,andwhatthe
valuesareineachregister.

RecursiveFunctions
Thenextprogramwillstretchyourbrainsevenmore.Theprogramwill
computethe
factorial
ofanumber.Afactorialistheproductofa

numberandallthenumbersbetweenitandone.Forexample,the
factorialof7is7*6*5*4*3*2*1,andthefactorialof4is4*3*2*1.
Now,onethingyoumightnoticeisthatthefactorialofanumberis
thesameastheproductofanumberandthefactorialjustbelowit.
Forexample,thefactorialof4is4timesthefactorialof3.The
factorialof3is3timesthefactorialof2.2is2timesthe
factorialof1.Thefactorialof1is1.Thistypeofdefinitionis
calledarecursivedefinition.Thatmeans,thedefinitionofthe
factorialfunctionincludesthefactorialfunctionitself.However,
sinceallfunctionsneedtoend,arecursivedefinitionmustinclude
a
basecase.
Thebasecaseisthepointwhererecursionwillstop.
Withoutabasecase,thefunctionwouldgoonforevercallingitself
untiliteventuallyranoutofstackspace.Inthecaseofthe
factorial,thebasecaseisthenumber1.Whenwehitthenumber1,
wedon'trunthefactorialagain,wejustsaythatthefactorialof1
is1.So,let'srunthroughwhatwewantthecodetolooklikefor
ourfactorialfunction:
1.Examinethenumber
2.Isthenumber1?
3.Ifso,theanswerisone
4.Otherwise,theansweristhenumbertimesthefactorialofthe
numberminusone
Thiswouldbeproblematicifwedidn'thavelocalvariables.Inother
programs,storingvaluesinglobalvariablesworkedfine.However,
globalvariablesonlyprovideonecopyofeachvariable.Inthis
program,wewillhavemultiplecopiesofthefunctionrunningatthe
6]
sametime,allofthemneedingtheirowncopiesofthedata![

Since
localvariablesexistonthestackframe,andeachfunctioncallgets
itsownstackframe,weareokay.
Let'slookatthecodetoseehowthisworks:
#PURPOSEGivenanumber,thisprogramcomputesthe
#factorial.Forexample,thefactorialof
#3is3*2*1,or6.Thefactorialof
#4is4*3*2*1,or24,andsoon.
#

#Thisprogramshowshowtocallafunctionrecursively.

.section.data

#Thisprogramhasnoglobaldata

.section.text


.globl_start
.globlfactorial#thisisunneededunlesswewanttoshare
#thisfunctionamongotherprograms
_start:
pushl$4#Thefactorialtakesoneargumentthe
#numberwewantafactorialof.So,it
#getspushed
callfactorial#runthefactorialfunction
addl$4,%esp#Scrubstheparameterthatwaspushedon
#thestack
movl%eax,%ebx#factorialreturnstheanswerin%eax,but
#wewantitin%ebxtosenditasourexit
#status
movl$1,%eax#callthekernel'sexitfunction
int$0x80

#Thisistheactualfunctiondefinition
.typefactorial,@function
factorial:
pushl%ebp#standardfunctionstuffwehaveto
#restore%ebptoitspriorstatebefore
#returning,sowehavetopushit
movl%esp,%ebp#Thisisbecausewedon'twanttomodify
#thestackpointer,soweuse%ebp.

movl8(%ebp),%eax#Thismovesthefirstargumentto%eax
#4(%ebp)holdsthereturnaddress,and
#8(%ebp)holdsthefirstparameter
cmpl$1,%eax#Ifthenumberis1,thatisourbase
#case,andwesimplyreturn(1is
#alreadyin%eaxasthereturnvalue)
jeend_factorial
decl%eax#otherwise,decreasethevalue
pushl%eax#pushitforourcalltofactorial
callfactorial#callfactorial
movl8(%ebp),%ebx#%eaxhasthereturnvalue,sowe
#reloadourparameterinto%ebx
imull%ebx,%eax#multiplythatbytheresultofthe
#lastcalltofactorial(in%eax)
#theanswerisstoredin%eax,which
#isgoodsincethat'swherereturn

#valuesgo.
end_factorial:
movl%ebp,%esp#standardfunctionreturnstuffwe
popl%ebp#havetorestore%ebpand%esptowhere
#theywerebeforethefunctionstarted
ret#returnfromthefunction(thispopsthe
#returnvalue,too)

Assemble,link,andrunitwiththesecommands:
asfactorial.sofactorial.o
ldfactorial.oofactorial
./factorial
echo$?

Thisshouldgiveyouthevalue24.24isthefactorialof4,youcan
testitoutyourselfwithacalculator:4*3*2*1=24.
I'mguessingyoudidn'tunderstandthewholecodelisting.Let'sgo
throughitalineatatimetoseewhatishappening.
_start:
pushl$4
callfactorial

Okay,thisprogramisintendedtocomputethefactorialofthenumber
4.Whenprogrammingfunctions,youaresupposedtoputtheparameters
ofthefunctiononthetopofthestackrightbeforeyoucallit.
Remember,afunction's
parameters
arethedatathatyouwantthe
functiontoworkwith.Inthiscase,thefactorialfunctiontakes1
parameterthenumberyouwantthefactorialof.
Thepushlinstructionputsthegivenvalueatthetopofthestack.
Thecallinstructionthenmakesthefunctioncall.
Nextwehavetheselines:
addl$4,%esp
movl%eax,%ebx
movl$1,%eax
int$0x80

Thistakesplaceafterfactorialhasfinishedandcomputedthe
factorialof4forus.Nowwehavetocleanupthestack.Theaddl
instructionmovesthestackpointerbacktowhereitwasbeforewe
pushedthe$4ontothestack.Youshouldalwayscleanupyourstack
parametersafterafunctioncallreturns.

Thenextinstructionmoves%eaxto%ebx.What'sin%eax?Itis
factorial'sreturnvalue.Inourcase,itisthevalueofthe
factorialfunction.With4asourparameter,24shouldbeourreturn
value.Remember,returnvaluesarealwaysstoredin%eax.Wewantto
returnthisvalueasthestatuscodetotheoperatingsystem.
However,Linuxrequiresthattheprogram'sexitstatusbestoredin
%ebx,not%eax,sowehavetomoveit.Thenwedothestandardexit
systemcall.
Thenicethingaboutfunctioncallsisthat:
Otherprogrammersdon'thavetoknowanythingaboutthemexcept
itsargumentstousethem.
Theyprovidestandardizedbuildingblocksfromwhichyoucan
formaprogram.
Theycanbecalledmultipletimesandfrommultiplelocations
andtheyalwaysknowhowtogetbacktowheretheyweresince
callpushesthereturnaddressontothestack.
Thesearethemainadvantagesoffunctions.Largerprogramsalsouse
functionstobreakdowncomplexpiecesofcodeintosmaller,simpler
ones.Infact,almostallofprogrammingiswritingandcalling
functions.
Let'snowtakealookathowthefactorialfunctionitselfis
implemented.
Beforethefunctionstarts,wehavethisdirective:
.typefactorial,@function
factorial:

The.typedirectivetellsthelinkerthatfactorialisafunction.
Thisisn'treallyneededunlesswewereusingfactorialinother
programs.Wehaveincludeditforcompleteness.Thelinethatsays
factorial:givesthesymbolfactorialthestoragelocationofthe
nextinstruction.That'showcallknewwheretogowhenwesaidcall
factorial.
Thefirstrealinstructionsofthefunctionare:
pushl%ebp
movl%esp,%ebp

Asshowninthepreviousprogram,thiscreatesthestackframefor
thisfunction.Thesetwolineswillbethewayyoushouldstartevery
function.
Thenextinstructionisthis:
movl8(%ebp),%eax

Thisusesbasepointeraddressingtomovethefirstparameterofthe
functioninto%eax.Remember,(%ebp)hastheold%ebp,4(%ebp)has
thereturnaddress,and8(%ebp)isthelocationofthefirst
parametertothefunction.Ifyouthinkback,thiswillbethevalue
4onthefirstcall,sincethatwaswhatwepushedonthestack
beforecallingthefunctionthefirsttime(withpushl$4).Asthis
functioncallsitself,itwillhaveothervalues,too.
Next,wechecktoseeifwe'vehitourbasecase(aparameterof1).
Ifso,wejumptotheinstructionatthelabelend_factorial,where
itwillbereturned.It'salreadyin%eaxwhichwementionedearlier
iswhereyouputreturnvalues.Thatisaccomplishedbytheselines:
cmpl$1,%eax
jeend_factorial

Ifit'snotourbasecase,whatdidwesaywewoulddo?Wewouldcall
thefactorialfunctionagainwithourparameterminusone.So,first
wedecrease%eaxbyone:
decl%eax

declstandsfordecrement.Itsubtracts1fromthegivenregisteror
memorylocation(%eaxinourcase).inclistheinverseitadds1.
Afterdecrementing%eaxwepushitontothestacksinceit'sgoingto
betheparameterofthenextfunctioncall.Andthenwecall
factorialagain!
pushl%eax
callfactorial

Okay,nowwe'vecalledfactorial.Onethingtorememberisthatafter
afunctioncall,wecanneverknowwhattheregistersare(except
%espand%ebp).Soeventhoughwehadthevaluewewerecalledwith
in%eax,it'snotthereanymore.Therefore,weneedpullitoffthe
stackfromthesameplacewegotitthefirsttime(at8(%ebp)).So,
wedothis:
movl8(%ebp),%ebx

Now,wewanttomultiplythatnumberwiththeresultofthefactorial
function.Ifyourememberourpreviousdiscussion,theresultof
functionsareleftin%eax.So,weneedtomultiply%ebxwith%eax.
Thisisdonewiththisinstruction:
imull%ebx,%eax

Thisalsostorestheresultin%eax,whichisexactlywherewewant
thereturnvalueforthefunctiontobe!Sincethereturnvalueisin

placewejustneedtoleavethefunction.Ifyouremember,atthe
startofthefunctionwepushed%ebp,andmoved%espinto%ebpto
createthecurrentstackframe.Nowwereversetheoperationto
destroythecurrentstackframeandreactivatethelastone:
end_factorial:
movl%ebp,%esp
popl%ebp

Nowwe'realreadytoreturn,soweissuethefollowingcommand
ret

Thispopsthetopvalueoffofthestack,andthenjumpstoit.If
yourememberourdiscussionaboutcall,wesaidthatcallfirst
pushedtheaddressofthenextinstructionontothestackbeforeit
jumpedtothebeginningofthefunction.So,herewepopitbackoff
sowecanreturnthere.Thefunctionisdone,andwehaveouranswer!
Likeourpreviousprogram,youshouldlookovertheprogramagain,
andmakesureyouknowwhateverythingdoes.Lookbackthroughthis
sectionandtheprevioussectionsfortheexplanationofanythingyou
don'tunderstand.Then,takeapieceofpaper,andgothroughthe
programstepbystep,keepingtrackofwhatthevaluesofthe
registersareateachstep,andwhatvaluesareonthestack.Doing
thisshoulddeepenyourunderstandingofwhatisgoingon.
[6]
By"runningatthesametime"Iamtalkingaboutthefactthatone
willnothavefinishedbeforeanewoneisactivated.Iamnot
implyingthattheirinstructionsarerunningatthesametime.

Review
KnowtheConcepts

Whatareprimitives?
Whatarecallingconventions?
Whatisthestack?
Howdopushlandpoplaffectthestack?Whatspecialpurpose
registerdotheyaffect?
Whatarelocalvariablesandwhataretheyusedfor?
Whyarelocalvariablessonecessaryinrecursivefunctions?
Whatare%ebpand%espusedfor?
Whatisastackframe?

UsetheConcepts

Writeafunctioncalledsquarewhichreceivesoneargumentand
returnsthesquareofthatargument.
Writeaprogramtotestyoursquarefunction.
ConvertthemaximumprogramgivenintheSectioncalled
Finding
aMaximumValue
inChapter3sothatitisafunctionwhich
takesapointertoseveralvaluesandreturnstheirmaximum.
Writeaprogramthatcallsmaximumwith3differentlists,and
returnstheresultofthelastoneastheprogram'sexitstatus
code.
Explaintheproblemsthatwouldarisewithoutastandard
callingconvention.

GoingFurther

Doyouthinkit'sbetterforasystemtohavealargesetof
primitivesorasmallone,assumingthatthelargersetcanbe
writtenintermsofthesmallerone?
Thefactorialfunctioncanbewrittennonrecursively.Doso.
Findanapplicationonthecomputeryouuseregularly.Tryto
locateaspecificfeature,andpracticebreakingthatfeature
outintofunctions.Definethefunctioninterfacesbetweenthat
featureandtherestoftheprogram.
Comeupwithyourowncallingconvention.Rewritetheprograms
inthischapterusingit.Anexampleofadifferentcalling
conventionwouldbetopassparametersinregistersratherthan
thestack,topasstheminadifferentorder,toreturnvalues
inotherregistersormemorylocations.Whateveryoupick,be
consistentandapplyitthroughoutthewholeprogram.
Canyoubuildacallingconventionwithoutusingthestack?
Whatlimitationsmightithave?
Whattestcasesshouldweuseinourexampleprogramtocheck
toseeifitisworkingproperly?

Chapter5:DealingwithFiles
Alotofcomputerprogrammingdealswithfiles.Afterall,whenwe
rebootourcomputers,theonlythingthatremainsfromprevious
sessionsarethethingsthathavebeenputondisk.Datawhichis

storedinfilesiscalled
persistent
data,becauseitpersistsin
filesthatremainonthediskevenwhentheprogramisn'trunning..

TheUNIXFileConcept
Eachoperatingsystemhasitsownwayofdealingwithfiles.However,
theUNIXmethod,whichisusedonLinux,isthesimplestandmost
universal.UNIXfiles,nomatterwhatprogramcreatedthem,canall
beaccessedasasequentialstreamofbytes.Whenyouaccessafile,
youstartbyopeningitbyname.Theoperatingsystemthengivesyou
anumber,calleda
filedescriptor,
whichyouusetorefertothe
fileuntilyouarethroughwithit.Youcanthenreadandwriteto
thefileusingitsfiledescriptor.Whenyouaredonereadingand
writing,youthenclosethefile,whichthenmakesthefile
descriptoruseless.
Inourprogramswewilldealwithfilesinthefollowingways:
1.TellLinuxthenameofthefiletoopen,andinwhatmodeyou
wantitopened(read,write,bothreadandwrite,createitif
itdoesn'texist,etc.).Thisishandledwiththeopensystem
call,whichtakesafilename,anumberrepresentingthemode,
andapermissionsetasitsparameters.%eaxwillholdthe
systemcallnumber,whichis5.Theaddressofthefirst
characterofthefilenameshouldbestoredin%ebx.The
read/writeintentions,representedasanumber,shouldbe
storedin%ecx.Fornow,use0forfilesyouwanttoreadfrom,
and03101forfilesyouwanttowriteto(youmustincludethe
1]
leadingzero).[

Finally,thepermissionsetshouldbestored
asanumberin%edx.IfyouareunfamiliarwithUNIX
permissions,justuse0666forthepermissions(again,youmust
includetheleadingzero).
2.Linuxwillthenreturntoyouafiledescriptorin%eax.
Remember,thisisanumberthatyouusetorefertothisfile
throughoutyourprogram.
3.Nextyouwilloperateonthefiledoingreadsand/orwrites,
eachtimegivingLinuxthefiledescriptoryouwanttouse.
readissystemcall3,andtocallityouneedtohavethefile
descriptorin%ebx,theaddressofabufferforstoringthe
datathatisreadin%ecx,andthesizeofthebufferin%edx.
BufferswillbeexplainedintheSectioncalled
Buffersand
.bss.
readwillreturnwitheitherthenumberofcharactersread
fromthefile,oranerrorcode.Errorcodescanbe
distinguishedbecausetheyarealwaysnegativenumbers(more
informationonnegativenumberscanbefoundinChapter10).

writeissystemcall4,anditrequiresthesameparametersas
thereadsystemcall,exceptthatthebuffershouldalreadybe
filledwiththedatatowriteout.Thewritesystemcallwill
givebackthenumberofbyteswrittenin%eaxoranerrorcode.
4.Whenyouarethroughwithyourfiles,youcanthentellLinux
toclosethem.Afterwards,yourfiledescriptorisnolonger
valid.Thisisdoneusingclose,systemcall6.Theonly
parametertocloseisthefiledescriptor,whichisplacedin
%ebx
[1]
ThiswillbeexplainedinmoredetailintheSectioncalled
Truth,
Falsehood,andBinaryNumbers
inChapter10.

Buffersand.bss
Intheprevioussectionwementionedbufferswithoutexplainingwhat
theywere.Abufferisacontinuousblockofbytesusedforbulkdata
transfer.Whenyourequesttoreadafile,theoperatingsystemneeds
tohaveaplacetostorethedataitreads.Thatplaceiscalleda
buffer.Usuallybuffersareonlyusedtostoredatatemporarily,and
itisthenreadfromthebuffersandconvertedtoaformthatis
easierfortheprogramstohandle.Ourprogramswon'tbecomplicated
enoughtoneedthatdone.Foranexample,let'ssaythatyouwantto
readinasinglelineoftextfromafilebutyoudonotknowhow
longthatlineis.Youwouldthensimplyreadalargenumberof
bytes/charactersfromthefileintoabuffer,lookforthe
endoflinecharacter,andcopyallofthecharacterstothat
endoflinecharactertoanotherlocation.Ifyoudidn'tfindan
endoflinecharacter,youwouldallocateanotherbufferandcontinue
reading.Youwouldprobablywindupwithsomecharactersleftoverin
yourbufferinthiscase,whichyouwoulduseasthestartingpoint
2]
whenyounextneeddatafromthefile.[

Anotherthingtonoteisthatbuffersareafixedsize,setbythe
programmer.So,ifyouwanttoreadindata500bytesatatime,you
sendthereadsystemcalltheaddressofa500byteunusedlocation,
andsenditthenumber500soitknowshowbigitis.Youcanmakeit
smallerorbigger,dependingonyourapplication'sneeds.
Tocreateabuffer,youneedtoeitherreservestaticordynamic
storage.Staticstorageiswhatwehavetalkedaboutsofar,storage
locationsdeclaredusing.longor.bytedirectives.Dynamicstorage
willbediscussedintheSectioncalled
GettingMoreMemory
in
Chapter9.Thereareproblems,though,withdeclaringbuffersusing
.byte.First,itistedioustotype.Youwouldhavetotype500

numbersafterthe.bytedeclaration,andtheywouldn'tbeusedfor
anythingbuttotakeupspace.Second,itusesupspaceinthe
executable.Intheexampleswe'veusedsofar,itdoesn'tuseuptoo
much,butthatcanchangeinlargerprograms.Ifyouwant500bytes
youhavetotypein500numbersanditwastes500bytesinthe
executable.Thereisasolutiontobothofthese.Sofar,wehave
discussedtwoprogramsections,the.textandthe.datasections.
Thereisanothersectioncalledthe.bss.Thissectionislikethe
datasection,exceptthatitdoesn'ttakeupspaceintheexecutable.
Thissectioncanreservestorage,butitcan'tinitializeit.Inthe
.datasection,youcouldreservestorageandsetittoaninitial
value.Inthe.bsssection,youcan'tsetaninitialvalue.Thisis
usefulforbuffersbecausewedon'tneedtoinitializethemanyway,
wejustneedtoreservestorage.Inordertodothis,wedothe
followingcommands:
.section.bss
.lcommmy_buffer,500

Thisdirective,.lcomm,willcreateasymbol,my_buffer,thatrefers
toa500bytestoragelocationthatwecanuseasabuffer.Wecan
thendothefollowing,assumingwehaveopenedafileforreadingand
haveplacedthefiledescriptorin%ebx:
movl$my_buffer,%ecx
movl500,%edx
movl3,%eax
int$0x80

Thiswillreadupto500bytesintoourbuffer.Inthisexample,I
placedadollarsigninfrontofmy_buffer.Rememberthatthereason
forthisisthatwithoutthedollarsign,my_bufferistreatedasa
memorylocation,andisaccessedindirectaddressingmode.The
dollarsignswitchesittoimmediatemodeaddressing,whichactually
loadsthenumberrepresentedbymy_bufferitself(i.e.theaddress
ofthestartofourbuffer,whichistheaddressofmy_buffer)into
%ecx.
[2]
Whilethissoundscomplicated,mostofthetimeinprogrammingyou
willnotneedtodealdirectlywithbuffersandfiledescriptors.In
Chapter8youwilllearnhowtouseexistingcodepresentinLinuxto
handlemostofthecomplicationsoffileinput/outputforyou.

StandardandSpecialFiles

Youmightthinkthatprogramsstartwithoutanyfilesopenby
default.Thisisnottrue.Linuxprogramsusuallyhaveatleastthree
openfiledescriptorswhentheybegin.Theyare:
STDIN
Thisisthe
standardinput.
Itisareadonlyfile,andusually
[3]
representsyourkeyboard. Thisisalwaysfiledescriptor0.
STDOUT
Thisisthe
standardoutput.
Itisawriteonlyfile,andusually
representsyourscreendisplay.Thisisalwaysfiledescriptor1.
STDERR
Thisisyour
standarderror.
Itisawriteonlyfile,andusually
representsyourscreendisplay.Mostregularprocessingoutputgoes
toSTDOUT,butanyerrormessagesthatcomeupintheprocessgoto
STDERR.Thisway,ifyouwantto,youcansplitthemupintoseparate
places.Thisisalwaysfiledescriptor2.
Anyofthese"files"canberedirectedfromortoarealfile,rather
thanascreenorakeyboard.Thisisoutsidethescopeofthisbook,
butanygoodbookontheUNIXcommandlinewilldescribeitin
detail.Theprogramitselfdoesnotevenneedtobeawareofthis
indirectionitcanjustusethestandardfiledescriptorsasusual.
Noticethatmanyofthefilesyouwritetoaren'tfilesatall.
UNIXbasedoperatingsystemstreatallinput/outputsystemsasfiles.
Networkconnectionsaretreatedasfiles,yourserialportistreated
likeafile,evenyouraudiodevicesaretreatedasfiles.
Communicationbetweenprocessesisusuallydonethroughspecialfiles
calledpipes.Someofthesefileshavedifferentmethodsofopening
andcreatingthemthanregularfiles(i.e.theydon'tusetheopen
systemcall),buttheycanallbereadfromandwrittentousingthe
standardreadandwritesystemcalls.
[3]
Aswementionedearlier,inLinux,almosteverythingisa"file".
Yourkeyboardinputisconsideredafile,andsoisyourscreen
display.

UsingFilesinaProgram
Wearegoingtowriteasimpleprogramtoillustratetheseconcepts.
Theprogramwilltaketwofiles,andreadfromone,convertallof
itslowercaseletterstouppercase,andwritetotheotherfile.
Beforewedoso,let'sthinkaboutwhatweneedtodotogetthejob
done:

Haveafunctionthattakesablockofmemoryandconvertsitto
uppercase.Thisfunctionwouldneedanaddressofablockofmemory
anditssizeasparameters.
Haveasectionofcodethatrepeatedlyreadsintoabuffer,calls
ourconversionfunctiononthebuffer,andthenwritesthebuffer
backouttotheotherfile.
Begintheprogrambyopeningthenecessaryfiles.
NoticethatI'vespecifiedthingsinreverseorderthattheywillbe
done.That'sausefultrickinwritingcomplexprogramsfirst
decidethemeatofwhatisbeingdone.Inthiscase,it'sconverting
blocksofcharacterstouppercase.Then,youthinkaboutwhatall
needstobesetupandprocessedtogetthattohappen.Inthiscase,
youhavetoopenfiles,andcontinuallyreadandwriteblocksto
disk.Oneofthekeysofprogrammingiscontinuallybreakingdown
problemsintosmallerandsmallerchunksuntilit'ssmallenoughthat
youcaneasilysolvetheproblem.Thenyoucanbuildthesechunks
4]
backupuntilyouhaveaworkingprogram.[

Youmayhavebeenthinkingthatyouwillneverrememberallofthese
numbersbeingthrownatyouthesystemcallnumbers,theinterrupt
number,etc.Inthisprogramwewillalsointroduceanewdirective,
.equwhichshouldhelpout..equallowsyoutoassignnamesto
numbers.Forexample,ifyoudid.equLINUX_SYSCALL,0x80,anytime
afterthatyouwroteLINUX_SYSCALL,theassemblerwouldsubstitue
0x80forthat.Sonow,youcanwrite
int$LINUX_SYSCALL

whichismucheasiertoread,andmucheasiertoremember.Codingis
complex,buttherearealotofthingswecandolikethistomakeit
easier.
Hereistheprogram.Notethatwehavemorelabelsthanweactually
useforjumps,becausesomeofthemarejustthereforclarity.Try
totracethroughtheprogramandseewhathappensinvariouscases.
Anindepthexplanationoftheprogramwillfollow.
#PURPOSE:Thisprogramconvertsaninputfile
#toanoutputfilewithallletters
#convertedtouppercase.
#
#PROCESSING:1)Opentheinputfile
#2)Opentheoutputfile
#3)Whilewe'renotattheendoftheinputfile
#a)readpartoffileintoourmemorybuffer
#b)gothrougheachbyteofmemory
#ifthebyteisalowercaseletter,

#convertittouppercase
#c)writethememorybuffertooutputfile

.section.data

#######CONSTANTS########

#systemcallnumbers
.equSYS_OPEN,5
.equSYS_WRITE,4
.equSYS_READ,3
.equSYS_CLOSE,6
.equSYS_EXIT,1

#optionsforopen(lookat
#/usr/include/asm/fcntl.hfor
#variousvalues.Youcancombinethem
#byaddingthemorORingthem)
#Thisisdiscussedatgreaterlength
#in"CountingLikeaComputer"
.equO_RDONLY,0
.equO_CREAT_WRONLY_TRUNC,03101

#standardfiledescriptors
.equSTDIN,0
.equSTDOUT,1
.equSTDERR,2

#systemcallinterrupt
.equLINUX_SYSCALL,0x80

.equEND_OF_FILE,0#Thisisthereturnvalue
#ofreadwhichmeanswe've
#hittheendofthefile

.equNUMBER_ARGUMENTS,2

.section.bss
#Bufferthisiswherethedataisloadedinto
#fromthedatafileandwrittenfrom

#
intotheoutputfile.Thisshould
#neverexceed16,000forvarious
#reasons.

.equBUFFER_SIZE,500
.lcommBUFFER_DATA,BUFFER_SIZE

.section.text

#STACKPOSITIONS
.equST_SIZE_RESERVE,8
.equST_FD_IN,4
.equST_FD_OUT,8
.equST_ARGC,0#Numberofarguments
.equST_ARGV_0,4#Nameofprogram
.equST_ARGV_1,8#Inputfilename
.equST_ARGV_2,12#Outputfilename

.globl_start
_start:
###INITIALIZEPROGRAM###
#savethestackpointer
movl%esp,%ebp

#Allocatespaceforourfiledescriptors
#onthestack
subl$ST_SIZE_RESERVE,%esp

open_files:
open_fd_in:
###OPENINPUTFILE###
#opensyscall
movl$SYS_OPEN,%eax
#inputfilenameinto%ebx
movlST_ARGV_1(%ebp),%ebx
#readonlyflag
movl$O_RDONLY,%ecx
#thisdoesn'treallymatterforreading
movl$0666,%edx
#callLinux
int$LINUX_SYSCALL

store_fd_in:
#savethegivenfiledescriptor
movl%eax,ST_FD_IN(%ebp)

open_fd_out:

###OPENOUTPUTFILE###
#openthefile
movl$SYS_OPEN,%eax
#outputfilenameinto%ebx
movlST_ARGV_2(%ebp),%ebx
#flagsforwritingtothefile
movl$O_CREAT_WRONLY_TRUNC,%ecx
#permissionsetfornewfile(ifit'screated)
movl$0666,%edx
#callLinux
int$LINUX_SYSCALL

store_fd_out:
#storethefiledescriptorhere
movl%eax,ST_FD_OUT(%ebp)

###BEGINMAINLOOP###
read_loop_begin:

###READINABLOCKFROMTHEINPUTFILE###
movl$SYS_READ,%eax
#gettheinputfiledescriptor
movlST_FD_IN(%ebp),%ebx
#thelocationtoreadinto
movl$BUFFER_DATA,%ecx
#thesizeofthebuffer
movl$BUFFER_SIZE,%edx
#Sizeofbufferreadisreturnedin%eax
int$LINUX_SYSCALL

###EXITIFWE'VEREACHEDTHEEND###
#checkforendoffilemarker
cmpl$END_OF_FILE,%eax
#iffoundoronerror,gototheend
jleend_loop

continue_read_loop:
###CONVERTTHEBLOCKTOUPPERCASE###
pushl$BUFFER_DATA#locationofbuffer
pushl%eax#sizeofthebuffer
callconvert_to_upper
popl%eax#getthesizeback
addl$4,%esp#restore%esp


###WRITETHEBLOCKOUTTOTHEOUTPUTFILE###
#sizeofthebuffer
movl%eax,%edx
movl$SYS_WRITE,%eax
#filetouse
movlST_FD_OUT(%ebp),%ebx
#locationofthebuffer
movl$BUFFER_DATA,%ecx
int$LINUX_SYSCALL

###CONTINUETHELOOP###
jmpread_loop_begin

end_loop:
###CLOSETHEFILES###
#NOTEwedon'tneedtodoerrorchecking
#onthese,becauseerrorconditions
#don'tsignifyanythingspecialhere
movl$SYS_CLOSE,%eax
movlST_FD_OUT(%ebp),%ebx
int$LINUX_SYSCALL

movl$SYS_CLOSE,%eax
movlST_FD_IN(%ebp),%ebx
int$LINUX_SYSCALL

###EXIT###
movl$SYS_EXIT,%eax
movl$0,%ebx
int$LINUX_SYSCALL

#PURPOSE:Thisfunctionactuallydoesthe
#conversiontouppercaseforablock
#
#INPUT:Thefirstparameteristhelengthof
#theblockofmemorytoconvert
#
#Thesecondparameteristhestarting
#addressofthatblockofmemory
#
#OUTPUT:Thisfunctionoverwritesthecurrent

#bufferwiththeuppercasifiedversion.
#
#VARIABLES:
#%eaxbeginningofbuffer
#%ebxlengthofbuffer
#%edicurrentbufferoffset
#%clcurrentbytebeingexamined
#(firstpartof%ecx)
#

###CONSTANTS##
#Thelowerboundaryofoursearch
.equLOWERCASE_A,'a'
#Theupperboundaryofoursearch
.equLOWERCASE_Z,'z'
#Conversionbetweenupperandlowercase
.equUPPER_CONVERSION,'A''a'

###STACKSTUFF###
.equST_BUFFER_LEN,8#Lengthofbuffer
.equST_BUFFER,12#actualbuffer
convert_to_upper:
pushl%ebp
movl%esp,%ebp

###SETUPVARIABLES###
movlST_BUFFER(%ebp),%eax
movlST_BUFFER_LEN(%ebp),%ebx
movl$0,%edi
#ifabufferwithzerolengthwasgiven
#tous,justleave
cmpl$0,%ebx
jeend_convert_loop

convert_loop:
#getthecurrentbyte
movb(%eax,%edi,1),%cl

#gotothenextbyteunlessitisbetween
#'a'and'z'
cmpb$LOWERCASE_A,%cl
jlnext_byte
cmpb$LOWERCASE_Z,%cl

jgnext_byte

#otherwiseconvertthebytetouppercase
addb$UPPER_CONVERSION,%cl
#andstoreitback
movb%cl,(%eax,%edi,1)
next_byte:
incl%edi#nextbyte
cmpl%edi,%ebx#continueunless
#we'vereachedthe
#end
jneconvert_loop

end_convert_loop:
#noreturnvalue,justleave
movl%ebp,%esp
popl%ebp
ret

Typeinthisprogramastoupper.s,andthenenterinthefollowing
commands:
astoupper.sotoupper.o
ldtoupper.ootoupper

Thisbuildsaprogramcalledtoupper,whichconvertsallofthe
lowercasecharactersinafiletouppercase.Forexample,toconvert
thefiletoupper.stouppercase,typeinthefollowingcommand:
./touppertoupper.stoupper.uppercase

Youwillnowfindinthefiletoupper.uppercaseanuppercaseversion
ofyouroriginalfile.
Let'sexaminehowtheprogramworks.
ThefirstsectionoftheprogramismarkedCONSTANTS.Inprogramming,
aconstantisavaluethatisassignedwhenaprogramassemblesor
compiles,andisneverchanged.Imakeahabitofplacingallofmy
constantstogetheratthebeginningoftheprogram.It'sonly
necessarytodeclarethembeforeyouusethem,butputtingthemall
atthebeginningmakesthemeasytofind.Makingthemalluppercase
makesitobviousinyourprogramwhichvaluesareconstantsandwhere
5]
tofindthem.[

Inassemblylanguage,wedeclareconstantswiththe
.equdirectiveasmentionedbefore.Here,wesimplygivenamestoall

ofthestandardnumberswe'veusedsofar,likesystemcallnumbers,
thesyscallinterruptnumber,andfileopenoptions.
ThenextsectionismarkedBUFFERS.Weonlyuseonebufferinthis
program,whichwecallBUFFER_DATA.Wealsodefineaconstant,
BUFFER_SIZE,whichholdsthesizeofthebuffer.Ifwealwaysrefer
tothisconstantratherthantypingoutthenumber500wheneverwe
needtousethesizeofthebuffer,ifitlaterchanges,weonlyneed
tomodifythisvalue,ratherthanhavingtogothroughtheentire
programandchangingallofthevaluesindividually.
Insteadofgoingontothe_startsectionoftheprogram,gotothe
endwherewedefinetheconvert_to_upperfunction.Thisisthepart
thatactuallydoestheconversion.
ThissectionbeginswithalistofconstantsthatwewilluseThe
reasontheseareputhereratherthanatthetopisthattheyonly
dealwiththisonefunction.Wehavethesedefinitions:
.equLOWERCASE_A,'a'
.equLOWERCASE_Z,'z'
.equUPPER_CONVERSION,'A''a'

Thefirsttwosimplydefinethelettersthataretheboundariesof
whatwearesearchingfor.Rememberthatinthecomputer,lettersare
representedasnumbers.Therefore,wecanuseLOWERCASE_Ain
comparisons,additions,subtractions,oranythingelsewecanuse
numbersin.Also,noticewedefinetheconstantUPPER_CONVERSION.
Sincelettersarerepresentedasnumbers,wecansubtractthem.
Subtractinganuppercaseletterfromthesamelowercaseletter
givesushowmuchweneedtoaddtoalowercaselettertomakeit
uppercase.Ifthatdoesn'tmakesense,lookattheASCIIcodetables
themselves(seeAppendixD).You'llnoticethatthenumberforthe
characterAis65andthecharacterais97.Theconversionfactoris
then32.Foranylowercaseletterifyouadd32,youwillgetits
capitalequivalent.
Afterthis,wehavesomeconstantslabelledSTACKPOSITIONS.Remember
thatfunctionparametersarepushedontothestackbeforefunction
calls.Theseconstants(prefixedwithSTforclarity)definewherein
thestackweshouldexpecttofindeachpieceofdata.Thereturn
addressisatposition4+%esp,thelengthofthebufferisat
position8+%esp,andtheaddressofthebufferisatposition12+
%esp.Usingsymbolsforthesenumbersinsteadofthenumbers
themselvesmakesiteasiertoseewhatdataisbeingusedandmoved.
Nextcomesthelabelconvert_to_upper.Thisistheentrypointofthe
function.Thefirsttwolinesareourstandardfunctionlinestosave
thestackpointer.Thenexttwolines

movlST_BUFFER(%ebp),%eax
movlST_BUFFER_LEN(%ebp),%ebx

movethefunctionparametersintotheappropriateregistersforuse.
Then,weloadzerointo%edi.Whatwearegoingtodoisiterate
througheachbyteofthebufferbyloadingfromthelocation%eax+
%edi,incrementing%edi,andrepeatinguntil%ediisequaltothe
bufferlengthstoredin%ebx.Thelines
cmpl$0,%ebx
jeend_convert_loop

arejustasanitychecktomakesurethatnoonegaveusabufferof
zerosize.Iftheydid,wejustcleanupandleave.Guardingagainst
potentialuserandprogrammingerrorsisanimportanttaskofa
programmer.Youcanalwaysspecifythatyourfunctionshouldnottake
abufferofzerosize,butit'sevenbettertohavethefunction
checkandhaveareliableexitplanifithappens.
Nowwestartourloop.First,itmovesabyteinto%cl.Thecodefor
thisis
movb(%eax,%edi,1),%cl

Itisusinganindexedindirectaddressingmode.Itsaystostartat
%eaxandgo%edilocationsforward,witheachlocationbeing1byte
big.Ittakesthevaluefoundthere,andputitin%cl.Afterthisit
checkstoseeifthatvalueisintherangeoflowercase
a
to
lowercase
z.
Tochecktherange,itsimplycheckstoseeifthe
letterissmallerthana.Ifitis,itcan'tbealowercaseletter.
Likewise,ifitislargerthan
z,
itcan'tbealowercaseletter.
So,ineachofthesecases,itsimplymoveson.Ifitisinthe
properrange,itthenaddstheuppercaseconversion,andstoresit
backintothebuffer.
Eitherway,itthengoestothenextvaluebyincrementing%cl.Next
itcheckstoseeifweareattheendofthebuffer.Ifwearenotat
theend,wejumpbacktothebeginningoftheloop(theconvert_loop
label).Ifweareattheend,itsimplycontinuesontotheendof
thefunction.Becausewearemodifyingthebufferdirectly,wedon't
needtoreturnanythingtothecallingprogramthechangesare
alreadyinthebuffer.Thelabelend_convert_loopisnotneeded,but
it'stheresoit'seasytoseewherethepartsoftheprogramare.
Nowweknowhowtheconversionprocessworks.Nowweneedtofigure
outhowtogetthedatainandoutofthefiles.
Beforereadingandwritingthefileswemustopenthem.TheUNIXopen
systemcalliswhathandlesthis.Ittakesthefollowingparameters:

%eaxcontainsthesystemcallnumberasusual5inthiscase.
%ebxcontainsapointertoastringthatisthenameofthefileto
open.Thestringmustbeterminatedwiththenullcharacter.
%ecxcontainstheoptionsusedforopeningthefile.ThesetellLinux
howtoopenthefile.Theycanindicatethingssuchasopenfor
reading,openforwriting,openforreadingandwriting,createifit
doesn'texist,deletethefileifitalreadyexists,etc.Wewillnot
gointohowtocreatethenumbersfortheoptionsuntiltheSection
called
Truth,Falsehood,andBinaryNumbers
inChapter10.Fornow,
justtrustthenumberswecomeupwith.
%edxcontainsthepermissionsthatareusedtoopenthefile.Thisis
usedincasethefilehastobecreatedfirst,soLinuxknowswhat
permissionstocreatethefilewith.Theseareexpressedinoctal,
6]
justlikeregularUNIXpermissions.[

Aftermakingthesystemcall,thefiledescriptorofthenewlyopened
fileisstoredin%eax.
So,whatfilesareweopening?Inthisexample,wewillbeopening
thefilesspecifiedonthecommandline.Fortunately,commandline
parametersarealreadystoredbyLinuxinaneasytoaccesslocation,
andarealreadynullterminated.WhenaLinuxprogrambegins,all
pointerstocommandlineargumentsarestoredonthestack.The
numberofargumentsisstoredat(%esp),thenameoftheprogramis
storedat4(%esp),andtheargumentsarestoredfrom8(%esp)on.In
theCProgramminglanguage,thisisreferredtoastheargvarray,so
wewillrefertoitthatwayinourprogram.
Thefirstthingourprogramdoesissavethecurrentstackposition
in%ebpandthenreservesomespaceonthestacktostorethefile
descriptors.Afterthis,itstartsopeningfiles.
Thefirstfiletheprogramopensistheinputfile,whichisthe
firstcommandlineargument.Wedothisbysettingupthesystem
call.Weputthefilenameinto%ebx,thereadonlymodenumberinto
%ecx,thedefaultmodeof$0666into%edx,andthesystemcallnumber
into%eaxAfterthesystemcall,thefileisopenandthefile
7]
descriptorisstoredin%eax.[

Thefiledescriptoristhen
transferredtoitsappropriateplaceonthestack.
Thesameisthendonefortheoutputfile,exceptthatitiscreated
withawriteonly,createifdoesn'texist,truncateifdoesexist
mode.Itsfiledescriptorisstoredaswell.
Nowwegettothemainparttheread/writeloop.Basically,wewill
readfixedsizechunksofdatafromtheinputfile,callour
conversionfunctiononit,andwriteitbacktotheoutputfile.
Althoughwearereadingfixedsizechunks,thesizeofthechunks
don'tmatterforthisprogramwearejustoperatingonstraight

sequencesofcharacters.Wecouldreaditinwithaslittleoras
largeofchunksaswewant,anditstillwouldworkproperly.
Thefirstpartoftheloopistoreadthedata.Thisusestheread
systemcall.Thiscalljusttakesafiledescriptortoreadfrom,a
buffertowriteinto,andthesizeofthebuffer(i.e.themaximum
numberofbytesthatcouldbewritten).Thesystemcallreturnsthe
numberofbytesactuallyread,orendoffile(thenumber0).
Afterreadingablock,wecheck%eaxforanendoffilemarker.If
found,itexitstheloop.Otherwisewekeepongoing.
Afterthedataisread,theconvert_to_upperfunctioniscalledwith
thebufferwejustreadinandthenumberofcharactersreadinthe
previoussystemcall.Afterthisfunctionexecutes,thebuffershould
becapitalizedandreadytowriteout.Theregistersarethen
restoredwithwhattheyhadbefore.
Finally,weissueawritesystemcall,whichisexactlyliketheread
systemcall,exceptthatitmovesthedatafromthebufferouttothe
file.Nowwejustgobacktothebeginningoftheloop.
Aftertheloopexits(remember,itexitsif,afteraread,itdetects
theendofthefile),itsimplyclosesitsfiledescriptorsand
exits.Theclosesystemcalljusttakesthefiledescriptortoclose
in%ebx.
Theprogramisthenfinished!
[4]
MaureenSprankle's
ProblemSolvingandProgrammingConcepts
isan
excellentbookontheproblemsolvingprocessappliedtocomputer
programming.
[5]
Thisisfairlystandardpracticeamongprogrammersinall
languages.
[6]
Ifyouaren'tfamiliarwithUNIXpermissions,justput$0666here.
Don'tforgettheleadingzero,asitmeansthatthenumberisan
octalnumber.
[7]
Noticethatwedon'tdoanyerrorcheckingonthis.Thatisdone
justtokeeptheprogramsimple.Innormalprograms,everysystem
callshouldnormallybecheckedforsuccessorfailure.Infailure
cases,%eaxwillholdanerrorcodeinsteadofareturnvalue.Error
codesarenegative,sotheycanbedetectedbycomparing%eaxtozero
andjumpingifitislessthanzero.

Review
KnowtheConcepts
Describethelifecycleofafiledescriptor.
Whatarethestandardfiledescriptorsandwhataretheyusedfor?

Whatisabuffer?
Whatisthedifferencebetweenthe.datasectionandthe.bss
section?
Whatarethesystemcallsrelatedtoreadingandwritingfiles?
UsetheConcepts
ModifythetoupperprogramsothatitreadsfromSTDINandwritesto
STDOUTinsteadofusingthefilesonthecommandline.
Changethesizeofthebuffer.
Rewritetheprogramsothatitusesstorageinthe.bsssection
ratherthanthestacktostorethefiledescriptors.
Writeaprogramthatwillcreateafilecalledheynow.txtandwrite
thewords"Heydiddlediddle!"intoit.
GoingFurther
Whatdifferencedoesthesizeofthebuffermake?
Whaterrorresultscanbereturnedbyeachofthesesystemcalls?
Maketheprogramabletoeitheroperateoncommandlineargumentsor
useSTDINorSTDOUTbasedonthenumberofcommandlinearguments
specifiedbyARGC.
Modifytheprogramsothatitcheckstheresultsofeachsystemcall,
andprintsoutanerrormessagetoSTDOUTwhenitoccurs.

Chapter6:ReadingandWriting
SimpleRecords
Overview
AsmentionedinChapter5,manyapplicationsdealwithdatathatis
persistent
meaningthatthedataliveslongerthantheprogramby
beingstoredondiskinfiles.Youcanshutdowntheprogramandopen
itbackup,andyouarebackwhereyoustarted.Now,therearetwo
basickindsofpersistentdatastructuredandunstructured.
Unstructureddataislikewhatwedealtwithinthetoupperprogram.
Itjustdealtwithtextfilesthatwereenteredbyaperson.The
contentsofthefilesweren'tusablebyaprogrambecauseaprogram
can'tinterpretwhattheuseristryingtosayinrandomtext.
Structureddata,ontheotherhand,iswhatcomputersexcelat
handling.Structureddataisdatathatisdividedupintofieldsand
records.Forthemostpart,thefieldsandrecordsarefixedlength.
Becausethedataisdividedintofixedlengthrecordsand
fixedformatfields,thecomputercaninterpretthedata.Structured

datacancontainvariablelengthfields,butatthatpointyouare
1]
usuallybetteroffwithadatabase.[

Thischapterdealswithreadingandwritingsimplefixedlength
records.Let'ssaywewantedtostoresomebasicinformationabout
peopleweknow.Wecouldimaginethefollowingexamplefixedlength
recordaboutpeople:
Firstname40bytes
Lastname40bytes
Address240bytes
Age4bytes
Inthis,everythingischaracterdataexceptfortheage,whichis
simplyanumericfield,usingastandard4byteword(wecouldjust
useasinglebyteforthis,butkeepingitatawordmakesiteasier
toprocess).
Inprogramming,youoftenhavecertaindefinitionsthatyouwilluse
overandoveragainwithintheprogram,orperhapswithinseveral
programs.Itisgoodtoseparatetheseoutintofilesthataresimply
includedintotheassemblylanguagefilesasneeded.Forexample,in
ournextprogramswewillneedtoaccessthedifferentpartsofthe
recordabove.Thismeansweneedtoknowtheoffsetsofeachfield
fromthebeginningoftherecordinordertoaccessthemusingbase
pointeraddressing.Thefollowingconstantsdescribetheoffsetsto
theabovestructure.Puttheminafilenamedrecorddef.s:
.equRECORD_FIRSTNAME,0
.equRECORD_LASTNAME,40
.equRECORD_ADDRESS,80
.equRECORD_AGE,320

.equRECORD_SIZE,324

Inaddition,thereareseveralconstantsthatwehavebeendefining
overandoverinourprograms,anditisusefultoputthemina
file,sothatwedon'thavetokeepenteringthem.Putthefollowing
constantsinafilecalledlinux.s:
#CommonLinuxDefinitions

#SystemCallNumbers
.equSYS_EXIT,1
.equSYS_READ,3
.equSYS_WRITE,4
.equSYS_OPEN,5
.equSYS_CLOSE,6
.equSYS_BRK,45

#SystemCallInterruptNumber
.equLINUX_SYSCALL,0x80

#StandardFileDescriptors
.equSTDIN,0
.equSTDOUT,1
.equSTDERR,2

#CommonStatusCodes
.equEND_OF_FILE,0

Wewillwritethreeprogramsinthischapterusingthestructure
definedinrecorddef.s.Thefirstprogramwillbuildafile
containingseveralrecordsasdefinedabove.Thesecondprogramwill
displaytherecordsinthefile.Thethirdprogramwilladd1yearto
theageofeveryrecord.
Inadditiontothestandardconstantswewillbeusingthroughoutthe
programs,therearealsotwofunctionsthatwewillbeusingin
severaloftheprogramsonewhichreadsarecordandonewhich
writesarecord.
Whatparametersdothesefunctionsneedinordertooperate?We
basicallyneed:
Thelocationofabufferthatwecanreadarecordinto
Thefiledescriptorthatwewanttoreadfromorwriteto
Let'slookatourreadingfunctionfirst:
.include"recorddef.s"
.include"linux.s"

#PURPOSE:Thisfunctionreadsarecordfromthefile
#descriptor
#
#INPUT:Thefiledescriptorandabuffer
#
#OUTPUT:Thisfunctionwritesthedatatothebuffer
#andreturnsastatuscode.
#
#STACKLOCALVARIABLES
.equST_READ_BUFFER,8
.equST_FILEDES,12
.section.text
.globlread_record
.typeread_record,@function
read_record:

pushl%ebp
movl%esp,%ebp

pushl%ebx
movlST_FILEDES(%ebp),%ebx
movlST_READ_BUFFER(%ebp),%ecx
movl$RECORD_SIZE,%edx
movl$SYS_READ,%eax
int$LINUX_SYSCALL

#NOTE%eaxhasthereturnvalue,whichwewill
#givebacktoourcallingprogram
popl%ebx

movl%ebp,%esp
popl%ebp
ret

It'saprettysimplyfunction.Itjustreadsdatathesizeofour
structureintoanappropriatelysizedbufferfromthegivenfile
descriptor.Thewritingoneissimilar:
.include"linux.s"
.include"recorddef.s"
#PURPOSE:Thisfunctionwritesarecordto
#thegivenfiledescriptor
#
#INPUT:Thefiledescriptorandabuffer
#
#OUTPUT:Thisfunctionproducesastatuscode
#
#STACKLOCALVARIABLES
.equST_WRITE_BUFFER,8
.equST_FILEDES,12
.section.text
.globlwrite_record
.typewrite_record,@function
write_record:
pushl%ebp
movl%esp,%ebp

pushl%ebx
movl$SYS_WRITE,%eax
movlST_FILEDES(%ebp),%ebx

movlST_WRITE_BUFFER(%ebp),%ecx
movl$RECORD_SIZE,%edx
int$LINUX_SYSCALL

#NOTE%eaxhasthereturnvalue,whichwewill
#givebacktoourcallingprogram
popl%ebx

movl%ebp,%esp
popl%ebp
ret

Nowthatwehaveourbasicdefinitionsdown,wearereadytowrite
ourprograms.
[1]
Adatabaseisaprogramwhichhandlespersistentstructureddata
foryou.Youdon'thavetowritetheprogramstoreadandwritethe
datatodisk,todolookups,oreventodobasicprocessing.Itisa
veryhighlevelinterfacetostructureddatawhich,althoughitadds
someoverheadandadditionalcomplexity,isveryusefulforcomplex
dataprocessingtasks.Referencesforlearninghowdatabasesworkare
listedinChapter13.

WritingRecords
Thisprogramwillsimplywritesomehardcodedrecordstodisk.It
will:
Openthefile
Writethreerecords
Closethefile
Typethefollowingcodeintoafilecalledwriterecords.s:
.include"linux.s"
.include"recorddef.s"

.section.data

#Constantdataoftherecordswewanttowrite
#Eachtextdataitemispaddedtotheproper
#lengthwithnull(i.e.0)bytes.

#.reptisusedtopadeachitem..repttells
#theassemblertorepeatthesectionbetween
#.reptand.endrthenumberoftimesspecified.

#Thisisusedinthisprogramtoaddextranull
#charactersattheendofeachfieldtofill
#itup
record1:
.ascii"Fredrick\0"
.rept31#Paddingto40bytes
.byte0
.endr

.ascii"Bartlett\0"
.rept31#Paddingto40bytes
.byte0
.endr

.ascii"4242SPrairie\nTulsa,OK55555\0"
.rept209#Paddingto240bytes
.byte0
.endr

.long45

record2:
.ascii"Marilyn\0"
.rept32#Paddingto40bytes
.byte0
.endr

.ascii"Taylor\0"
.rept33#Paddingto40bytes
.byte0
.endr

.ascii"2224SJohannanSt\nChicago,IL12345\0"
.rept203#Paddingto240bytes
.byte0
.endr

.long29

record3:
.ascii"Derrick\0"
.rept32#Paddingto40bytes
.byte0

.endr
.ascii"McIntire\0"
.rept31#Paddingto40bytes
.byte0
.endr

.ascii"500WOakland\nSanDiego,CA54321\0"
.rept206#Paddingto240bytes
.byte0
.endr

.long36

#Thisisthenameofthefilewewillwriteto
file_name:
.ascii"test.dat\0"

.equST_FILE_DESCRIPTOR,4
.globl_start
_start:
#Copythestackpointerto%ebp
movl%esp,%ebp
#Allocatespacetoholdthefiledescriptor
subl$4,%esp

#Openthefile
movl$SYS_OPEN,%eax
movl$file_name,%ebx
movl$0101,%ecx#Thissaystocreateifit
#doesn'texist,andopenfor
#writing
movl$0666,%edx
int$LINUX_SYSCALL

#Storethefiledescriptoraway
movl%eax,ST_FILE_DESCRIPTOR(%ebp)
#Writethefirstrecord
pushlST_FILE_DESCRIPTOR(%ebp)
pushl$recordl
callwrite_record
addl$8,%esp

#Writethesecondrecord

pushlST_FILE_DESCRIPTOR(%ebp)
pushl$record2
callwrite_record
addl$8,%esp

#Writethethirdrecord
pushlST_FILE_DESCRIPTOR(%ebp)
pushl$record3
callwrite_record
addl$8,%esp

#Closethefiledescriptor
movl$SYS_CLOSE,%eax
movlST_FILE_DESCRIPTOR(%ebp),%ebx
int$LINUX_SYSCALL

#Exittheprogram
movl$SYS_EXIT,%eax
movl$0,%ebx
int$LINUX_SYSCALL

Thisisafairlysimpleprogram.Itmerelyconsistsofdefiningthe
datawewanttowriteinthe.datasection,andthencallingthe
rightsystemcallsandfunctioncallstoaccomplishit.Fora
refresherofallofthesystemcallsused,seeAppendixC.
Youmayhavenoticedthelines:
.include"linux.s"
.include"recorddef.s"

Thesestatementscausethegivenfilestobasicallybepastedright
thereinthecode.Youdon'tneedtodothiswithfunctions,because
thelinkercantakecareofcombiningfunctionsexportedwith.globl.
However,constantsdefinedinanotherfiledoneedtobeimportedin
thisway.
Also,youmayhavenoticedtheuseofanewassemblerdirective,
.rept.Thisdirectiverepeatsthecontentsofthefilebetweenthe
.reptandthe.endrdirectivesthenumberoftimesspecifiedafter
.rept.Thisisusuallyusedthewayweusedittopadvaluesinthe
.datasection.Inourcase,weareaddingnullcharacterstotheend
ofeachfielduntiltheyaretheirdefinedlengths.
Tobuildtheapplication,runthecommands:
aswriterecords.sowriterecord.o
aswriterecord.sowriterecord.o

ldwriterecord.owriterecords.oowriterecords

Hereweareassemblingtwofilesseparately,andthencombiningthem
togetherusingthelinker.Toruntheprogram,justtypethe
following:
./writerecords

Thiswillcauseafilecalledtest.dattobecreatedcontainingthe
records.However,sincetheycontainnonprintablecharacters(the
nullcharacter,specifically),theymaynotbeviewablebyatext
editor.Thereforeweneedthenextprogramtoreadthemforus.

ReadingRecords
Nowwewillconsidertheprocessofreadingrecords.Inthisprogram,
wewillreadeachrecordanddisplaythefirstnamelistedwitheach
record.
Sinceeachperson'snameisadifferentlength,wewillneeda
functiontocountthenumberofcharacterswewanttowrite.Sincewe
padeachfieldwithnullcharacters,wecansimplycountcharacters
2]
untilwereachanullcharacter.[

Notethatthismeansourrecords
mustcontainatleastonenullcharactereach.
Hereisthecode.Putitinafilecalledcountchars.s:
#PURPOSE:Countthecharactersuntilanullbyteisreached.
#
#INPUT:Theaddressofthecharacterstring
#
#OUTPUT:Returnsthecountin%eax
#
#PROCESS:
#Registersused:
#%ecxcharactercount
#%alcurrentcharacter
#%edxcurrentcharacteraddress

.typecount_chars,@function
.globlcount_chars

#Thisiswhereouroneparameterisonthestack
.equST_STRING_START_ADDRESS,8
count_chars:
pushl%ebp
movl%esp,%ebp


#Counterstartsatzero
movl$0,%ecx
#Startingaddressofdata
movlST_STRING_START_ADDRESS(%ebp),%edx

count_loop_begin:
#Grabthecurrentcharacter
movb(%edx),%al
#Isitnull?
cmpb$0,%al
#Ifyes,we'redone
jecount_loop_end
#Otherwise,incrementthecounterandthepointer
incl%ecx
incl%edx
#Gobacktothebeginningoftheloop
jmpcount_loop_begin

count_loop_end:
#We'redone.Movethecountinto%eax
#andreturn.
movl%ecx,%eax

popl%ebp
ret

Asyoucansee,it'safairlystraightforwardfunction.Itsimply
loopsthroughthebytes,countingasitgoes,untilithitsanull
character.Thenitreturnsthecount.
Ourrecordreadingprogramwillbefairlystraightforward,too.It
willdothefollowing:
Openthefile
Attempttoreadarecord
Ifweareattheendofthefile,exit
Otherwise,countthecharactersofthefirstname
WritethefirstnametoSTDOUT
WriteanewlinetoSTDOUT
Gobacktoreadanotherrecord
Towritethis,weneedonemoresimplefunctionafunctiontowrite
outanewlinetoSTDOUT.Putthefollowingcodeintowritenewline.s:
.include"linux.s"
.globlwrite_newline

.typewrite_newline,@function
.section.data
newline:
.ascii"\n"
.section.text
.equST_FILEDES,8
write_newline:
pushl%ebp
movl%esp,%ebp

movl$SYS_WRITE,%eax
movlST_FILEDES(%ebp),%ebx
movl$newline,%ecx
movl$1,%edx
int$LINUX_SYSCALL
movl%ebp,%esp
popl%ebp
ret

Nowwearereadytowritethemainprogram.Hereisthecodeto
readrecords.s:
.include"linux.s"
.include"recorddef.s"

.section.data
file_name:
.ascii"test.dat\0"

.section.bss
.lcommrecord_buffer,RECORD_SIZE

.section.text
#Mainprogram
.globl_start
_start:
#Thesearethelocationsonthestackwhere
#wewillstoretheinputandoutputdescriptors
#(FYIwecouldhaveusedmemoryaddressesin
#a.datasectioninstead)
.equST_INPUT_DESCRIPTOR,4
.equST_OUTPUT_DESCRIPTOR,8

#Copythestackpointerto%ebp
movl%esp,%ebp
#Allocatespacetoholdthefiledescriptors
subl$8,%esp

#Openthefile
movl$SYS_OPEN,%eax
movl$file_name,%ebx
movl$0,%ecx#Thissaystoopenreadonly
movl$0666,%edx
int$LINUX_SYSCALL

#Savefiledescriptor

movl%eax,ST_INPUT_DESCRIPTOR(%ebp)

#Eventhoughit'saconstant,weare
#savingtheoutputfiledescriptorin
#alocalvariablesothatifwelater
#decidethatitisn'talwaysgoingto
#beSTDOUT,wecanchangeiteasily.
movl$STDOUT,ST_OUTPUT_DESCRIPTOR(%ebp)

record_read_loop:
pushlST_INPUT_DESCRIPTOR(%ebp)
pushl$record_buffer
callread_record
addl$8,%esp

#Returnsthenumberofbytesread.
#Ifitisn'tthesamenumberwe
#requested,thenit'seitheran
#endoffile,oranerror,sowe're
#quitting
cmpl$RECORD_SIZE,%eax
jnefinished_reading

#Otherwise,printoutthefirstname
#butfirst,wemustknowit'ssize
pushl$RECORD_FIRSTNAME+record_buffer
callcount_chars
addl$4,%esp
movl%eax,%edx

movlST_OUTPUT_DESCRIPTOR(%ebp),%ebx
movl$SYS_WRITE,%eax
movl$RECORD_FIRSTNAME+record_buffer,%ecx
int$LINUX_SYSCALL

pushlST_OUTPUT_DESCRIPTOR(%ebp)
callwrite_newline
addl$4,%esp

jmprecord_read_loop

finished_reading:
movl$SYS_EXIT,%eax
movl$0,%ebx
int$LINUX_SYSCALL

Tobuildthisprogram,weneedtoassembleallofthepartsandlink
themtogether:
asreadrecord.soreadrecord.o
ascountchars.socountchars.o
aswritenewline.sowritenewline.o
asreadrecords.soreadrecords.o
ldreadrecord.ocountchars.owritenewline.o\
readrecords.ooreadrecords

Thebackslashinthefirstlinesimplymeansthatthecommand
continuesonthenextline.Youcanrunyourprogrambydoing
./readrecords.
Asyoucansee,thisprogramopensthefileandthenrunsaloopof
reading,checkingfortheendoffile,andwritingthefirstname.The
oneconstructthatmightbenewisthelinethatsays:
pushl$RECORD_FIRSTNAME+record_buffer

Itlookslikewearecombiningandaddinstructionwithapush
instruction,butwearenot.Yousee,bothRECORD_FIRSTNAMEand
record_bufferareconstants.Thefirstisadirectconstant,created
throughtheuseofa.equdirective,whilethelatterisdefined
automaticallybytheassemblerthroughitsuseasalabel(it'svalue
beingtheaddressthatthedatathatfollowsitwillstartat).Since
theyarebothconstantsthattheassemblerknows,itisabletoadd
themtogetherwhileitisassemblingyourprogram,sothewhole
instructionisasingleimmediatemodepushofasingleconstant.

TheRECORD_FIRSTNAMEconstantisthenumberofbytesafterthe
beginningofarecordbeforewehitthefirstname.record_bufferis
thenameofourbufferforholdingrecords.Addingthemtogethergets
ustheaddressofthefirstnamememberoftherecordstoredin
record_buffer.
[2]
IfyouhaveusedC,thisiswhatthestrlenfunctiondoes.

ModifyingtheRecords
Inthissection,wewillwriteaprogramthat:
Opensaninputandoutputfile
Readsrecordsfromtheinput
Incrementstheage
Writesthenewrecordtotheoutputfile
Likemostprogramswe'veencounteredrecently,thisprogramispretty
3]
straightforward.[

.include"linux.s"
.include"recorddef.s"
.section.data
input_file_name:
.ascii"test.dat\0"

output_file_name:
.ascii"testout.dat\0"

.section.bss
.lcommrecord_buffer,RECORD_SIZE

#Stackoffsetsoflocalvariables
.equST_INPUT_DESCRIPTOR,4
.equST_OUTPUT_DESCRIPTOR,8

.section.text
.globl_start
_start:
#Copystackpointerandmakeroomforlocalvariables
movl%esp,%ebp
subl$8,%esp

#Openfileforreading
movl$SYS_OPEN,%eax
movl$input_file_name,%ebx
movl$0,%ecx
movl$0666,%edx

int$LINUX_SYSCALL

movl%eax,ST_INPUT_DESCRIPTOR(%ebp)

#Openfileforwriting
movl$SYS_OPEN,%eax
movl$output_file_name,%ebx
movl$0101,%ecx
movl$0666,%edx
int$LINUX_SYSCALL

movl%eax,ST_OUTPUT_DESCRIPTOR(%ebp)

loop_begin:
pushlST_INPUT_DESCRIPTOR(%ebp)
pushl$record_buffer
callread_record
addl$8,%esp

#Returnsthenumberofbytesread.
#Ifitisn'tthesamenumberwe
#requested,thenit'seitheran
#endoffile,oranerror,sowe're
#quitting
cmpl$RECORD_SIZE,%eax
jneloop_end

#Incrementtheage
inclrecord_buffer+RECORD_AGE

#Writetherecordout
pushlST_OUTPUT_DESCRIPTOR(%ebp)
pushl$record_buffer
callwrite_record
addl$8,%esp

jmploop_begin

loop_end:
movl$SYS_EXIT,%eax
movl$0,%ebx
int$LINUX_SYSCALL

4]
Youcantypeitinasaddyear.s.Tobuildit,typethefollowing[

:
asaddyear.soaddyear.o
ldaddyear.oreadrecord.owriterecord.ooaddyear

5]
Toruntheprogram,justtypeinthefollowing[

:
./addyear

Thiswilladdayeartoeveryrecordlistedintest.datandwritethe
newrecordstothefiletestout.dat.
Asyoucansee,writingfixedlengthrecordsisprettysimple.You
onlyhavetoreadinblocksofdatatoabuffer,processthem,and
writethembackout.Unfortunately,thisprogramdoesn'twritethe
newagesouttothescreensoyoucanverifyyourprogram's
effectiveness.Thisisbecausewewon'tgettodisplayingnumbers
untilChapter8andChapter10.Afterreadingthoseyoumaywantto
comebackandrewritethisprogramtodisplaythenumericdatathat
wearemodifying.
[3]
Youwillfindthatafterlearningthemechanicsofprogramming,
mostprogramsareprettystraightforwardonceyouknowexactlywhat
itisyouwanttodo.Mostoftheminitializedata,dosome
processinginaloop,andthencleaneverythingup.
[4]
Thisassumesthatyouhavealreadybuilttheobjectfiles
readrecord.oandwriterecord.ointhepreviousexamples.Ifnot,
youwillhavetodoso.
[5]
Thisisassumingyoucreatedthefileinapreviousrunof
writerecords.Ifnot,youneedtorunwriterecordsfirstbefore
runningthisprogram.

Review
KnowtheConcepts
Whatisarecord?
Whatistheadvantageoffixedlengthrecordsovervariablelength
records?
Howdoyouincludeconstantsinmultipleassemblysourcefiles?
Whymightyouwanttosplitupaprojectintomultiplesourcefiles?
Whatdoestheinstructioninclrecord_buffer+RECORD_AGEdo?What
addressingmodeisitusing?Howmanyoperandsdoestheincl
instructionshaveinthiscase?Whichpartsarebeinghandledbythe
assemblerandwhichpartsarebeinghandledwhentheprogramisrun?

UsetheConcepts
Addanotherdatamembertothepersonstructuredefinedinthis
chapter,andrewritethereadingandwritingfunctionsandprograms
totakethemintoaccount.Remembertoreassembleandrelinkyour
filesbeforerunningyourprograms.
Createaprogramthatusesalooptowrite30identicalrecordstoa
file.
Createaprogramtofindthelargestageinthefileandreturnthat
ageasthestatuscodeoftheprogram.
Createaprogramtofindthesmallestageinthefileandreturnthat
ageasthestatuscodeoftheprogram.
GoingFurther
Rewritetheprogramsinthischaptertousecommandlineargumentsto
specifythefilesnames.
Researchthelseeksystemcall.Rewritetheaddyearprogramtoopen
thesourcefileforbothreadingandwriting(use$2forthe
read/writemode),andwritethemodifiedrecordsbacktothesame
filetheywerereadfrom.
Researchthevariouserrorcodesthatcanbereturnedbythesystem
callsmadeintheseprograms.Pickonetorewrite,andaddcodethat
checks%eaxforerrorconditions,and,ifoneisfound,writesa
messageaboutittoSTDERRandexit.
Writeaprogramthatwilladdasinglerecordtothefilebyreading
thedatafromthekeyboard.Remember,youwillhavetomakesurethat
thedatahasatleastonenullcharacterattheend,andyouneedto
haveawayfortheusertoindicatetheyaredonetyping.Becausewe
havenotgottenintocharacterstonumbersconversion,youwillnot
beabletoreadtheageinfromthekeyboard,soyou'llhavetohave
adefaultage.
Writeafunctioncalledcomparestringsthatwillcomparetwostrings
upto5characters.Thenwriteaprogramthatallowstheuserto
enter5characters,andhavetheprogramreturnallrecordswhose
firstnamestartswiththose5characters.

Chapter7:DevelopingRobust
Programs
Thischapterdealswithdevelopingprogramsthatare
robust.
Robust
programsareabletohandleerrorconditionsgracefully.Theyare
programsthatdonotcrashnomatterwhattheuserdoes.Building
robustprogramsisessentialtothepracticeofprogramming.Writing

robustprogramstakesdisciplineandworkitusuallyentails
findingeverypossibleproblemthatcanoccur,andcomingupwithan
actionplanforyourprogramtotake.

WhereDoestheTimeGo?
Programmersschedulepoorly.Inalmosteveryprogrammingproject,
programmerswilltaketwo,four,oreveneighttimesaslongto
developaprogramorfunctionthantheyoriginallyestimated.There
aremanyreasonsforthisproblem,including:
Programmersdon'talwaysscheduletimeformeetingsorother
noncodingactivitiesthatmakeupeveryday.
Programmersoftenunderestimatefeedbacktimes(howlongittakesto
passchangerequestsandapprovalsbackandforth)forprojects.
Programmersdon'talwaysunderstandthefullscopeofwhattheyare
producing.
Programmersoftenhavetoestimateascheduleonatotallydifferent
kindofprojectthantheyareusedto,andthusareunableto
scheduleaccurately.
Programmersoftenunderestimatetheamountoftimeittakestogeta
programfullyrobust.
Thelastitemistheoneweareinterestedinhere.
Ittakesalotof
timeandefforttodeveloprobustprograms.
Moresothanpeople
usuallyguess,includingexperiencedprogrammers.Programmersgetso
focusedonsimplysolvingtheproblemathandthattheyfailtolook
atthepossiblesideissues.
Inthetoupperprogram,wedonothaveanycourseofactionifthe
filetheuserselectsdoesnotexist.Theprogramwillgoaheadand
trytoworkanyway.Itdoesn'treportanyerrormessagesotheuser
won'tevenknowthattheytypedinthenamewrong.Let'ssaythatthe
destinationfileisonanetworkdrive,andthenetworktemporarily
fails.Theoperatingsystemisreturningastatuscodetousin%eax,
butwearen'tcheckingit.Therefore,ifafailureoccurs,theuser
istotallyunaware.Thisprogramisdefinitelynotrobust.Asyoucan
see,eveninasimpleprogramtherearealotofthingsthatcango
wrongthataprogrammermustcontendwith.
Inalargeprogram,itgetsmuchmoreproblematic.Thereareusually
manymorepossibleerrorconditionsthanpossiblesuccessful
conditions.Therefore,youshouldalwaysexpecttospendthemajority
ofyourtimecheckingstatuscodes,writingerrorhandlers,and
performingsimilartaskstomakeyourprogramrobust.Ifittakestwo
weekstodevelopaprogram,itwilllikelytakeatleasttwomoreto
makeitrobust.Rememberthateveryerrormessagethatpopsupon
yourscreenhadtobeprogrammedinbysomeone.

SomeTipsforDevelopingRobustPrograms
UserTesting
Testingisoneofthemostessentialthingsaprogrammerdoes.Ifyou
haven'ttestedsomething,youshouldassumeitdoesn'twork.However,
testingisn'tjustaboutmakingsureyourprogramworks,it'sabout
makingsureyourprogramdoesn'tbreak.Forexample,ifIhavea
programthatisonlysupposedtodealwithpositivenumbers,youneed
totestwhathappensiftheuserentersanegativenumber.Ora
letter.Orthenumberzero.Youmusttestwhathappensiftheyput
spacesbeforetheirnumbers,spacesaftertheirnumbers,andother
littlepossibilities.Youneedtomakesurethatyouhandlethe
user'sdatainawaythatmakessensetotheuser,andthatyoupass
onthatdatainawaythatmakessensetotherestofyourprogram.
Whenyourprogramfindsinputthatdoesn'tmakesense,itneedsto
performappropriateactions.Dependingonyourprogram,thismay
includeendingtheprogram,promptingtheusertoreentervalues,
notifyingacentralerrorlog,rollingbackanoperation,orignoring
itandcontinuing.
Notonlyshouldyoutestyourprograms,youneedtohaveotherstest
itaswell.Youshouldenlistotherprogrammersandusersofyour
programtohelpyoutestyourprogram.Ifsomethingisaproblemfor
yourusers,evenifitseemsokaytoyou,itneedstobefixed.If
theuserdoesn'tknowhowtouseyourprogramcorrectly,thatshould
betreatedasabugthatneedstobefixed.
Youwillfindthatusersfindalotmorebugsinyourprogramthan
youevercould.Thereasonisthatusersdon'tknowwhatthecomputer
expects.Youknowwhatkindsofdatathecomputerexpects,and
thereforearemuchmorelikelytoenterdatathatmakessensetothe
computer.Usersenterdatathatmakessensetothem.Allowing
nonprogrammerstouseyourprogramfortestingpurposesusually
givesyoumuchmoreaccurateresultsastohowrobustyourprogram
trulyis.
DataTesting
Whendesigningprograms,eachofyourfunctionsneedstobevery
specificaboutthetypeandrangeofdatathatitwillorwon't
accept.Youthenneedtotestthesefunctionstomakesurethatthey
performtospecificationwhenhandedtheappropriatedata.Most
importantistesting
cornercases
or
edgecases.
Cornercasesarethe
inputsthataremostlikelytocauseproblemsorbehaveunexpectedly.

Whentestingnumericdata,thereareseveralcornercasesyoualways
needtotest:
Thenumber0
Thenumber1
Anumberwithintheexpectedrange
Anumberoutsidetheexpectedrange
Thefirstnumberintheexpectedrange
Thelastnumberintheexpectedrange
Thefirstnumberbelowtheexpectedrange
Thefirstnumberabovetheexpectedrange
Forexample,ifIhaveaprogramthatissupposedtoacceptvalues
between5and200,Ishouldtest0,1,4,5,153,200,201,and255
ataminimum(153and255wererandomlychoseninsideandoutsidethe
range,respectively).Thesamegoesforanylistsofdatayouhave.
Youneedtotestthatyourprogrambehavesasexpectedforlistsof0
items,1item,massivenumbersofitems,andsoon.Inaddition,you
shouldalsotestanyturningpointsyouhave.Forexample,ifyou
havedifferentcodetohandlepeopleunderandoverage30,for
example,youwouldneedtotestitonpeopleofages29,30,and31
atleast.
Therewillbesomeinternalfunctionsthatyouassumegetgooddata
becauseyouhavecheckedforerrorsbeforethispoint.However,while
indevelopmentyouoftenneedtocheckforerrorsanyway,asyour
othercodemayhaveerrorsinit.Toverifytheconsistencyand
validityofdataduringdevelopment,mostlanguageshaveafacility
toeasilycheckassumptionsaboutdatacorrectness.IntheClanguage
thereistheassertmacro.Youcansimplyputinyourcodeassert(a
>b),anditwillgiveanerrorifitreachesthatcodewhenthe
conditionisnottrue.Inaddition,sincesuchacheckisawasteof
timeafteryourcodeisstable,theassertmacroallowsyoutoturn
offassertsatcompiletime.Thismakessurethatyourfunctionsare
receivinggooddatawithoutcausingunnecessaryslowdownsforcode
releasedtothepublic.
ModuleTesting
Notonlyshouldyoutestyourprogramasawhole,youneedtotest
theindividualpiecesofyourprogram.Asyoudevelopyourprogram,
youshouldtestindividualfunctionsbyprovidingitwithdatayou
createtomakesureitrespondsappropriately.
Inordertodothiseffectively,youhavetodevelopfunctionswhose
solepurposeistocallfunctionsfortesting.Thesearecalled
drivers
(nottobeconfusedwithhardwaredrivers).Theysimplyload
yourfunction,supplyitwithdata,andchecktheresults.Thisis
especiallyusefulifyouareworkingonpiecesofanunfinished

program.Sinceyoucan'ttestallofthepiecestogether,youcan
createadriverprogramthatwilltesteachfunctionindividually.
Also,thecodeyouaretestingmaymakecallstofunctionsnot
developedyet.Inordertoovercomethisproblem,youcanwritea
smallfunctioncalleda
stub
whichsimplyreturnsthevaluesthat
functionneedstoproceed.Forexample,inanecommerceapplication,
Ihadafunctioncalledis_ready_to_checkout.BeforeIhadtimeto
actuallywritethefunctionIjustsetittoreturntrueonevery
callsothatthefunctionswhichreliedonitwouldhaveananswer.
Thisallowedmetotestfunctionswhichreliedon
is_ready_to_checkoutwithoutthefunctionbeingfullyimplemented.

HandlingErrorsEffectively
Notonlyisitimportanttoknowhowtotest,butitisalso
importanttoknowwhattodowhenanerrorisdetected.
HaveanErrorCodeforEverything
Trulyrobustsoftwarehasauniqueerrorcodeforeverypossible
contingency.Bysimplyknowingtheerrorcode,youshouldbeableto
findthelocationinyourcodewherethaterrorwassignalled.
Thisisimportantbecausetheerrorcodeisusuallyalltheuserhas
togoonwhenreportingerrors.Therefore,itneedstobeasuseful
aspossible.
Errorcodesshouldalsobeaccompaniedbydescriptiveerrormessages.
However,onlyinrarecircumstancesshouldtheerrormessagetryto
predict
why
theerroroccurred.Itshouldsimplyrelatewhat
happened.Backin1995IworkedforanInternetServiceProvider.One
ofthewebbrowserswesupportedtriedtoguessthecauseforevery
networkerror,ratherthanjustreportingtheerror.Ifthecomputer
wasn'tconnectedtotheInternetandtheusertriedtoconnecttoa
website,itwouldsaythattherewasaproblemwiththeInternet
ServiceProvider,thattheserverwasdown,andthattheusershould
contacttheirInternetServiceProvidertocorrecttheproblem.
Nearlyaquarterofourcallswerefrompeoplewhohadreceivedthis
message,butmerelyneededtoconnecttotheInternetbeforetrying
tousetheirbrowser.Asyoucansee,tryingtodiagnosewhatthe
problemiscanleadtoalotmoreproblemsthanitfixes.Itis
bettertojustreporterrorcodesandmessages,andhaveseparate
resourcesfortheusertotroubleshootingtheapplication.A
troubleshootingguide,nottheprogramitself,isanappropriate
placetolistpossiblereasonsandcoursesforactionforeacherror
message.
RecoveryPoints

Inordertosimplifyerrorhandling,itisoftenusefultobreakyour
programapartintodistinctunits,whereeachunitfailsandis
recoveredasawhole.Forexample,youcouldbreakyourprogramupso
thatreadingtheconfigurationfilewasaunit.Ifreadingthe
configurationfilefailedatanypoint(openingthefile,readingthe
file,tryingtodecodethefile,etc.)thentheprogramwouldsimply
treatitasaconfigurationfileproblemandskiptothe
recovery
point
forthatproblem.Thiswayyougreatlyreducethenumberof
errorhandlingmechanismyouneedforyourprogram,becauseerror
recoveryisdoneonamuchmoregenerallevel.
Notethatevenwithrecoverypoints,yourerrormessagesneedtobe
specificastowhattheproblemwas.Recoverypointsarebasicunits
forerrorrecovery,notforerrordetection.Errordetectionstill
needstobeextremelyexact,andtheerrorreportsneedexacterror
codesandmessages.
Whenusingrecoverypoints,youoftenneedtoincludecleanupcodeto
handledifferentcontingencies.Forexample,inourconfiguration
fileexample,therecoveryfunctionwouldneedtoincludecodeto
checkandseeiftheconfigurationfilewasstillopen.Dependingon
wheretheerroroccurred,thefilemayhavebeenleftopen.The
recoveryfunctionneedstocheckforthiscondition,andanyother
conditionthatmightleadtosysteminstability,andreturnthe
programtoaconsistentstate.
Thesimplestwaytohandlerecoverypointsistowrapthewhole
programintoasinglerecoverypoint.Youwouldjusthaveasimple
errorreportingfunctionthatyoucancallwithanerrorcodeanda
message.Thefunctionwouldprintthemandandsimplyexitthe
program.Thisisnotusuallythebestsolutionforrealworld
situations,butitisagoodfallback,lastresortmechanism.

MakingOurProgramMoreRobust
Thissectionwillgothroughmakingtheaddyear.sprogramfrom
Chapter6alittlemorerobust.
Sincethisisaprettysimpleprogram,wewilllimitourselvestoa
singlerecoverypointthatcoversthewholeprogram.Theonlything
wewilldotorecoveristoprinttheerrorandexit.Thecodetodo
thatisprettysimple:
.include"linux.s"
.equST_ERROR_CODE,8
.equST_ERROR_MSG,12
.globlerror_exit
.typeerror_exit,@function
error_exit:

pushl%ebp
movl%esp,%ebp
#Writeouterrorcode
movlST_ERROR_CODE(%ebp),%ecx
pushl%ecx
callcount_chars
popl%ecx
movl%eax,%edx
movl$STDERR,%ebx
movl$SYS_WRITE,%eax
int$LINUX_SYSCALL

#Writeouterrormessage
movlST_ERROR_MSG(%ebp),%ecx
pushl%ecx
callcount_chars
popl%ecx
movl%eax,%edx
movl$STDERR,%ebx
movl$SYS_WRITE,%eax
int$LINUX_SYSCALL

pushl$STDERR
callwrite_newline

#Exitwithstatus1
movl$SYS_EXIT,%eax
movl$1,%ebx
int$LINUX_SYSCALL

Enteritinafilecallederrorexit.s.Tocallit,youjustneedto
pushtheaddressofanerrormessage,andthenanerrorcodeontothe
stack,andcallthefunction.
Nowlet'slookforpotentialerrorspotsinouraddyearprogram.
Firstofall,wedon'tchecktoseeifeitherofouropensystem
callsactuallycompleteproperly.
Linuxreturnsitsstatuscodein%eax,soweneedtocheckandseeif
thereisanerror.
#Openfileforreading
movl$SYS_OPEN,%eax
movl$input_file_name,%ebx
movl$0,%ecx
movl$0666,%edx

int$LINUX_SYSCALL

movl%eax,INPUT_DESCRIPTOR(%ebp)

#Thiswilltestandseeif%eaxis
#negative.Ifitisnotnegative,it
#willjumptocontinue_processing.
#Otherwiseitwillhandletheerror
#conditionthatthenegativenumber
#represents.
cmpl$0,%eax
jlcontinue_processing

#Sendtheerror
.section.data
no_open_file_code:
.ascii"0001:\0"
no_open_file_msg:
.ascii"Can'tOpenInputFile\0"

.section.text
pushl$no_open_file_msg
pushl$no_open_file_code
callerror_exit

continue_processing:
#Restofprogram

So,aftercallingthesystemcall,wecheckandseeifwehavean
errorbycheckingtoseeiftheresultofthesystemcallisless
thanzero.Ifso,wecallourerrorreportingandexitroutine.
Aftereverysystemcall,functioncall,orinstructionwhichcanhave
erroneousresultsyoushouldadderrorcheckingandhandlingcode.
Toassembleandlinkthefiles,do:
asaddyear.soaddyear.o
aserrorexit.soerrorexit.o
ldaddyear.owritenewline.oerrorexit.oreadrecord.owrite
record.ocountchars.ooaddyear

Nowtrytorunitwithoutthenecessaryfiles.Itnowexitscleanly
andgracefully!

Review
KnowtheConcepts
Whatarethereasonsprogrammer'shavetroublewithscheduling?
Findyourfavoriteprogram,andtrytouseitinacompletelywrong
manner.Openupfilesofthewrongtype,chooseinvalidoptions,
closewindowsthataresupposedtobeopen,etc.Counthowmany
differenterrorscenariostheyhadtoaccountfor.
Whatarecornercases?Canyoulistexamplesofnumericcornercases?
Whyisusertestingsoimportant?
Whatarestubsanddriversusedfor?What'sthedifferencebetween
thetwo?
Whatarerecoverypointsusedfor?
Howmanydifferenterrorcodesshouldaprogramhave?
UsetheConcepts
Gothroughtheaddyear.sprogramandadderrorcheckingcodeafter
everysystemcall.
Findoneotherprogramwehavedonesofar,andadderrorcheckingto
thatprogram.
Addarecoverymechanismforaddyear.sthatallowsittoreadfrom
STDINifitcannotopenthestandardfile.
GoingFurther
What,ifanything,shouldyoudoifyourerrorreportingfunction
fails?Why?
Trytofindbugsinatleastoneopensourceprogram.Fileabug
reportforit.
Trytofixthebugyoufoundinthepreviousexercise.

Chapter8:SharingFunctionswith
CodeLibraries
Overview
Bynowyoushouldrealizethatthecomputerhastodoalotofwork
evenforsimpletasks.Becauseofthat,youhavetodoalotofwork
towritethecodeforacomputertoevendosimpletasks.In
addition,programmingtasksareusuallynotverysimple.Therefore,
weneeedawaytomakethisprocesseasieronourselves.Thereare
severalwaystodothis,including:
Writecodeinahighlevellanguageinsteadofassemblylanguage
Havelotsofprewrittencodethatyoucancutandpasteintoyour
ownprograms

Haveasetoffunctionsonthesystemthataresharedamongany
programthatwishestouseit
Allthreeoftheseareusuallyusedtosomedegreeinanygiven
project.ThefirstoptionwillbeexploredfurtherinChapter11.The
secondoptionisusefulbutitsuffersfromsomedrawbacks,
including:
Codethatiscopiedoftenhastobemajorlymodifiedtofitthe
surroundingcode.
Everyprogramcontainingthecopiedcodehasthesamecodeinit,
thuswastingalotofspace.
Ifabugisfoundinanyofthecopiedcodeithastobefixedin
everyapplicationprogram.
Therefore,thesecondoptionisusuallyusedsparingly.Itisusually
onlyusedincaseswhereyoucopyandpasteskeletoncodefora
specifictypeoftask,andaddinyourprogramspecificdetails.The
thirdoptionistheonethatisusedthemostoften.Thethirdoption
includeshavingacentralrepositoryofsharedcode.Then,insteadof
eachprogramwastingspacestoringthesamecopiesoffunctions,they
cansimplypointtothe
dynamiclibraries
whichcontainthefunctions
theyneed.
Ifabugisfoundinoneofthesefunctions,itonlyhastobefixed
withinthesinglefunctionlibraryfile,andallapplicationswhich
useitareautomaticallyupdated.Themaindrawbackwiththis
approachisthatitcreatessomedependencyproblems,including:
Ifmultipleapplicationsareallusingthesamefile,howdoweknow
whenitissafetodeletethefile?Forexample,ifthree
applicationsaresharingafileoffunctionsand2oftheprograms
aredeleted,howdoesthesystemknowthattherestillexistsan
applicationthatusesthatcode,andthereforeitshouldn'tbe
deleted?
Someprogramsinadvertantlyrelyonbugswithinsharedfunctions.
Therefore,ifupgradingthesharedfunctionsfixesabugthata
programdependedon,itcouldcausethatapplicationtocease
functioning.
Theseproblemsarewhatleadtowhatisknownas"DLLhell".However,
itisgenerallyassumedthattheadvantagesoutweighthe
disadvantages.
Inprogramming,thesesharedcodefilesarereferredtoas
shared
libraries
,
dynamiclibraries,sharedobjects,dynamiclinklibraries,
1]
DLLs,
or
.sofiles
.[

Wewillrefertoalloftheseas
dynamic
libraries.
[1]
Eachofthesetermshaveslightlydifferentmeanings,butmost
peopleusetheminterchangeablyanyway.Specifically,thischapter

willcoverdynamiclibraries,butnotsharedlibraries.Shared
librariesaredynamiclibrarieswhicharebuiltusing
positionindependentcode
(oftenabbreviatedPIC)whichisoutside
thescopeofthisbook.However,sharedlibrariesanddynamic
librariesareusedinthesamewaybyusersandprogramsthelinker
justlinksthemdifferently.

UsingaDynamicLibrary
Theprogramwewillexaminehereissimpleitwritesthecharacters
helloworldtothescreenandexits.Theregularprogram,
helloworldnolib.s,lookslikethis:
#PURPOSE:Thisprogramwritesthemessage"helloworld"and
#exits
#

.include"linux.s"

.section.data

helloworld:
.ascii"helloworld\n"
helloworld_end:

.equhelloworld_len,helloworld_endhelloworld

.section.text
.globl_start
_start:
movl$STDOUT,%ebx
movl$helloworld,%ecx
movl$helloworld_len,%edx
movl$SYS_WRITE,%eax
int$LINUX_SYSCALL

movl$0,%ebx
movl$SYS_EXIT,%eax
int$LINUX_SYSCALL

That'snottoolong.However,takealookathowshorthelloworldlib
iswhichusesalibrary:

#PURPOSE:Thisprogramwritesthemessage"helloworld"and
#exits
#

.section.data

helloworld:
.ascii"helloworld\n\0"

.section.text
.globl_start
_start:
pushl$helloworld
callprintf

pushl$0
callexit

It'sevenshorter!
Now,buildingprogramswhichusedynamiclibrariesisalittle
differentthannormal.Youcanbuildthefirstprogramnormallyby
doingthis:
ashelloworldnolib.sohelloworldnolib.o
ldhelloworldnolib.oohelloworldnolib

However,inordertobuildthesecondprogram,youhavetodothis:
ashelloworldlib.sohelloworldlib.o
lddynamiclinker/lib/ldlinux.so.2\
ohelloworldlibhelloworldlib.o1c

Remember,thebackslashinthefirstlinesimplymeansthatthe
commandcontinuesonthenextline.Theoptiondynamiclinker
/lib/ldlinux.so.2allowsourprogramtobelinkedtolibraries.This
buildstheexecutablesothatbeforeexecuting,theoperatingsystem
willloadtheprogram/lib/ldlinux.so.2toloadinexternal
librariesandlinkthemwiththeprogram.Thisprogramisknownasa
dynamiclinker
.
Thelcoptionsaystolinktotheclibrary,namedlibc.soon
GNU/Linuxsystems.Givenalibraryname,cinthiscase(usually
librarynamesarelongerthanasingleletter),theGNU/Linuxlinker
prependsthestringlibtothebeginningofthelibrarynameand
appends.sototheendofittoformthelibrary'sfilename.This
librarycontainsmanyfunctionstoautomatealltypesoftasks.The

twoweareusingareprintf,whichprintsstrings,andexit,which
exitstheprogram.
Noticethatthesymbolsprintfandexitaresimplyreferredtoby
namewithintheprogram.Inpreviouschapters,thelinkerwould
resolveallofthenamestophysicalmemoryaddresses,andthenames
wouldbethrownaway.Whenusingdynamiclinking,thenameitself
resideswithintheexecutable,andisresolvedbythedynamiclinker
whenitisrun.Whentheprogramisrunbytheuser,thedynamic
linkerloadsthedynamiclibrarieslistedinourlinkstatement,and
thenfindsallofthefunctionandvariablenamesthatwerenamedby
ourprogrambutnotfoundatlinktime,andmatchesthemupwith
correspondingentriesinthesharedlibrariesitloads.Itthen
replacesallofthenameswiththeaddresseswhichtheyareloaded
at.Thissoundstimeconsuming.Itistoasmalldegree,butitonly
happensonceatprogramstartuptime.

HowDynamicLibrariesWork
Inourfirstprograms,allofthecodewascontainedwithinthe
sourcefile.Suchprogramsarecalled
staticallylinkedexecutables
,
becausetheycontainedallofthenecessaryfunctionalityforthe
programthatwasn'thandledbythekernel.Intheprogramswewrote
inChapter6,weusedbothourmainprogramfileandfilescontaining
routinesusedbymultipleprograms.Inthesecases,wecombinedall
ofthecodetogetherusingthelinkeratlinktime,soitwasstill
staticallylinked.However,inthehelloworldlibprogram,westarted
usingdynamiclibraries.Whenyouusedynamiclibraries,yourprogram
isthen
dynamicallylinked,
whichmeansthatnotallofthecode
neededtoruntheprogramisactuallycontainedwithintheprogram
fileitself,butinexternallibraries.
Whenweputthelconthecommandtolinkthehelloworldprogram,it
toldthelinkertousetheclibrary(libc.so)tolookupanysymbols
thatweren'talreadydefinedinhelloworld.o.However,itdoesn't
actuallyaddanycodetoourprogram,itjustnotesintheprogram
wheretolook.Whenthehelloworldprogrambegins,thefile
/lib/ldlinux.so.2isloadedfirst.Thisisthedynamiclinker.This
looksatourhelloworldprogramandseesthatitneedstheclibrary
torun.So,itsearchesforafilecalledlibc.sointhestandard
places(listedin/etc/ld.so.confandinthecontentsofthe
LD_LIBRARY_PATHenvironmentvariable),thenlooksinitforallthe
neededsymbols(printfandexitinthiscase),andthenloadsthe
libraryintotheprogram'svirtualmemory.Finally,itreplacesall

instancesofprintfintheprogramwiththeactuallocationofprintf
inthelibrary.
Runthefollowingcommand:
ldd./helloworldnolib

Itshouldreportbacknotadynamicexecutable.Thisisjustlikewe
saidhelloworldnolibisastaticallylinkedexecutable.However,
trythis:
ldd./helloworldlib

Itwillreportbacksomethinglike
libc.so.6=>/lib/libc.so.6(0x4001d000)
/lib/ldlinux.so.2=>/lib/ldlinux.so.2(0x400000000)

Thenumbersinparenthesismaybedifferentonyoursystem.This
meansthattheprogramhelloworldislinkedtolibc.so.6(the.6is
theversionnumber),whichisfoundat/lib/libc.so.6,and
/lib/ldlinux.so.2isfoundat/lib/ldlinux.so.2.Theselibraries
havetobeloadedbeforetheprogramcanberun.Ifyouare
interested,runthelddprogramonvariousprogramsthatareonyour
Linuxdistribution,andseewhatlibrariestheyrelyon.

FindingInformationAboutLibraries
Okay,sonowthatyouknowaboutlibraries,thequestionis,howdo
youfindoutwhatlibrariesyouhaveonyoursystemandwhattheydo?
Well,let'sskipthatquestionforaminuteandaskanotherquestion:
Howdoprogrammersdescribefunctionstoeachotherintheir
documentation?Let'stakealookatthefunctionprintf.Itscalling
interface(usuallyreferredtoasa
prototype
)lookslikethis:
intprintf(char*string,...)

InLinux,functionsaredescribedintheCprogramminglanguage.In
fact,mostLinuxprogramsarewritteninC.Thatiswhymost
documentationandbinarycompatibilityisdefinedusingtheC
language.Theinterfacetotheprintffunctionaboveisdescribed
usingtheCprogramminglanguage.
Thisdefinitionmeansthatthereisafunctionprintf.Thethings
insidetheparenthesisarethefunction'sparametersorarguments.
Thefirstparameterhereischar*string.Thismeansthereisa
parameternamedstring(thenameisn'timportant,excepttousefor
talkingaboutit),whichhasatypechar*.charmeansthatitwantsa

singlebytecharacter.The*afteritmeansthatitdoesn'tactually
wantacharacterasanargument,butinsteaditwantstheaddressof
acharacterorsequenceofcharacters.Ifyoulookbackatour
helloworldprogram,youwillnoticethatthefunctioncalllooked
likethis:
pushl$hello
callprintf

So,wepushedtheaddressofthehellostring,ratherthantheactual
characters.Youmightnoticethatwedidn'tpushthelengthofthe
string.Thewaythatprintffoundtheendofthestringwasbecause
weendeditwithanullcharacter(\0).Manyfunctionsworkthatway,
especiallyClanguagefunctions.Theintbeforethefunction
definitiontellwhattypeofvaluethefunctionwillreturnin%eax
whenitreturns.printfwillreturnanintwhenit'sthrough.Now,
afterthechar*string,wehaveaseriesofperiods,....Thismeans
thatitcantakeanindefinitenumberofadditionalargumentsafter
thestring.Mostfunctionscanonlytakeaspecifiednumberof
arguments.printf,however,cantakemany.Itwilllookintothe
stringparameter,andeverywhereitseesthecharacters%s,itwill
lookforanotherstringfromthestacktoinsert,andeverywhereit
sees%ditwilllookforanumberfromthestacktoinsert.Thisis
bestdescribedusinganexample:
#PURPOSE:Thisprogramistodemonstratehowtocallprintf
#

.section.data

#Thisstringiscalledtheformatstring.It'sthefirst
#parameter,andprintfusesittofindouthowmanyparameters
#itwasgiven,andwhatkindtheyare.
firststring:
.ascii"Hello!%sisa%swholovesthenumber%d\n\0"
name:
.ascii"Jonathan\0"
personstring:
.ascii"person\0"
#Thiscouldalsohavebeenan.equ,butwedecidedtogiveit
#arealmemorylocationjustforkicks
numberloved:
.long3

.section.text

.globl_start
_start:
#notethattheparametersarepassedinthe
#reverseorderthattheyarelistedinthe
#function'sprototype.
pushlnumberloved#Thisisthe%d
pushl$personstring#Thisisthesecond%s
pushl$name#Thisisthefirst%s
pushl$firststring#Thisistheformatstring
#intheprototype
callprintf

pushl$0
callexit

Typeitinwiththefilenameprintfexample.s,andthendothe
followingcommands:
asprintfexample.soprintfexample.o
ldprintfexample.ooprintfexamplelc\
dynamiclinker/lib/ldlinux.so.2

Thenruntheprogramwith./printfexample,anditshouldsaythis:
Hello!Jonathanisapersonwholovesthenumber3

Now,ifyoulookatthecode,you'llseethatweactuallypushthe
formatstringlast,eventhoughit'sthefirstparameterlisted.You
2]
alwayspushafunctionsparametersinreverseorder.[

Youmaybe
wonderinghowtheprintffunctionknowshowmanyparametersthere
are.Well,itsearchesthroughyourstring,andcountshowmany%ds
and%ssitfinds,andthengrabsthatnumberofparametersfromthe
stack.Iftheparametermatchesa%d,ittreatsitasanumber,and
ifitmatchesa%s,ittreatsitasapointertoanullterminated
string.printfhasmanymorefeaturesthanthis,butthesearethe
mostusedones.So,asyoucansee,printfcanmakeoutputalot
easier,butitalsohasalotofoverhead,becauseithastocount
thenumberofcharactersinthestring,lookthroughitforallof
thecontrolcharactersitneedstoreplace,pullthemoffthestack,
convertthemtoasuitablerepresentation(numbershavetobe
convertedtostrings,etc),andstickthemalltogether
appropriately.
We'veseenhowtousetheCprogramminglanguageprototypestocall
libraryfunctions.Tousethemeffectively,however,youneedtoknow

severalmoreofthepossibledatatypesforreadingfunctions.Here
arethemainones:
int
Anintisanintegernumber(4bytesonx86processor).
long
Alongisalsoanintegernumber(4bytesonanx86processor).
longlong
Alonglongisanintegernumberthat'slargerthanalong(8bytes
onanx86processor).
short
Ashortisanintegernumberthat'sshorterthananint(2byteson
anx86processor).
char
Acharisasinglebyteintegernumber.Thisismostlyusedfor
storingcharacterdata,sinceASCIIstringsusuallyarerepresented
withonebytepercharacter.
float
Afloatisafloatingpointnumber(4bytesonanx86processor).
FloatingpointnumberswillbeexplainedinmoredepthintheSection
called
FloatingpointNumbers
inChapter10.
.double
Adoubleisafloatingpointnumberthatislargerthanafloat(8
bytesonanx86processor).
unsigned
unsignedisamodifierusedforanyoftheabovetypeswhichkeeps
themfrombeingusedassignedquantities.Thedifferencebetween
signedandunsignednumberswillbediscussedinChapter10.
*
Anasterisk(*)isusedtodenotethatthedataisn'tanactual
value,butinsteadisapointertoalocationholdingthegivenvalue
(4bytesonanx86processor).So,let'ssayinmemorylocation
my_locationyouhavethenumber20stored.Iftheprototypesaidto
passanint,youwouldusedirectaddressingmodeanddopushl
my_location.However,iftheprototypesaidtopassanint*,you
woulddopushl$my_locationanimmediatemodepushoftheaddress
thatthevalueresidesin.Inadditiontoindicatingtheaddressofa
singlevalue,pointerscanalsobeusedtopassasequenceof
consecutivelocations,startingwiththeonepointedtobythegiven
value.Thisiscalledanarray.
struct
Astructisasetofdataitemsthathavebeenputtogetherundera
name.Forexampleyoucoulddeclare:

structteststruct{
inta
char*b
}

andanytimeyouranintostructteststructyouwouldknowthatitis
actuallytwowordsrightnexttoeachother,thefirstbeingan
integer,andthesecondapointertoacharacterorgroupof
characters.Youneverseestructspassedasargumentstofunctions.
Instead,youusuallyseepointerstostructspassedasarguments.
Thisisbecausepassingstructstofunctionsisfairlycomplicated,
sincetheycantakeupsomanystoragelocations.
typedef
Atypedefbasicallyallowsyoutorenameatype.Forexample,Ican
dotypedefintmyowntypeinaCprogram,andanytimeItyped
myowntype,itwouldbejustasifItypedint.Thiscangetkindof
annoying,becauseyouhavetolookupwhatallofthetypedefsand
structsinafunctionprototypereallymean.However,typedefsare
usefulforgivingtypesmoremeaningfulanddescriptivenames.
CompatibilityNote:
Thelistedsizesareforintelcompatible(x86)
machines.Othermachineswillhavedifferentsizes.Also,evenwhen
parametersshorterthanawordarepassedtofunctions,theyare
passedaslongsonthestack.
That'showtoreadfunctiondocumentation.Now,let'sgetbacktothe
questionofhowtofindoutaboutlibraries.Mostofyoursystem
librariesarein/usr/libor/lib.Ifyouwanttojustseewhat
symbolstheydefine,justrunobjdumpRFILENAMEwhereFILENAMEis
thefullpathtothelibrary.Theoutputofthatisn'ttoohelpful,
though,forfindinganinterfacethatyoumightneed.Usually,you
havetoknowwhatlibraryyouwantatthebeginning,andthenjust
readthedocumentation.Mostlibrarieshavemanualsormanpagesfor
theirfunctions.Thewebisthebestsourceofdocumentationfor
libraries.MostlibrariesfromtheGNUprojectalsohaveinfopages
onthem,whicharealittlemorethoroughthanmanpages.
[2]
Thereasonthatparametersarepushedinthereverseorderis
becauseoffunctionswhichtakeavariablenumberofparameterslike
printf.Theparameterspushedinlastwillbeinaknownposition
relativetothetopofthestack.Theprogramcanthenusethese
parameterstodeterminewhereonthestacktheadditionalarguments
are,andwhattypetheyare.Forexample,printfusestheformat
stringtodeterminehowmanyotherparametersarebeingsent.Ifwe
pushedtheknownargumentsfirst,youwouldn'tbeabletotellwhere
theywereonthestack.

UsefulFunctions
Severalusefulfunctionsyouwillwanttobeawareoffromthec
libraryinclude:
size_tstrlen(constchar*s)calculatesthesizeofnullterminated
strings.
intstrcmp(constchar*sl,constchar*s2)comparestwostrings
alphabetically.
char*strdup(constchar*s)takesthepointertoastring,and
createsanewcopyinanewlocation,andreturnsthenewlocation.
FILE*fopen(constchar*filename,constchar*opentype)opensa
managed,bufferedfile(allowseasierreadingandwritingthanusing
3] [4]
filedescriptorsdirectly).[

,
intfclose(FILE*stream)closesafileopenedwithfopen.
char*fgets(char*s,intcount,FILE*stream)fetchesalineof
charactersintostrings.
intfputs(constchar*s,FILE*stream)writesastringtothegiven
openfile.
intfprintf(FILE*stream,constchar*template,...)isjustlike
printf,butitusesanopenfileratherthandefaultingtousing
standardoutput.
Youcanfindthecompletemanualonthislibrarybygoingto
http://www.gnu.org/software/libc/manual/
[3]
stdin,stdout,andstderr(alllowercase)canbeusedinthese
programstorefertothefilesoftheircorrespondingfile
descriptors.
[4]
FILEisastruct.Youdon'tneedtoknowitscontentstouseit.
Youonlyhavetostorethepointerandpassittotherelevantother
functions.

BuildingaDynamicLibrary
Let'ssaythatwewantedtotakeallofoursharedcodefromChapter
6andbuilditintoadynamiclibrarytouseinourprograms.The
firstthingwewoulddoisassemblethemlikenormal:
aswriterecord.sowriterecord.o
asreadrecord.soreadrecord.o

Now,insteadoflinkingthemintoaprogram,wewanttolinkthem
intoadynamiclibrary.Thischangesourlinkercommandtothis:
ldsharedwriterecord.oreadrecord.oolibrecord.so

Thislinksbothofthesefilestogetherintoadynamiclibrarycalled
librecord.so.Thisfilecannowbeusedformultipleprograms.Ifwe
needtoupdatethefunctionscontainedwithinit,wecanjustupdate
thisonefileandnothavetoworryaboutwhichprogramsuseit.
Let'slookathowwewouldlinkagainstthislibrary.Tolinkthe
writerecordsprogram,wewoulddothefollowing:
aswriterecords.sowriterecords
ldL.dynamiclinker/lib/ldlinux.so.2\
owriterecordslrecordwriterecords.o

Inthiscommand,L.toldthelinkertolookforlibrariesinthe
currentdirectory(itusuallyonlysearches/libdirectory,/usr/lib
directory,andafewothers).Aswe'veseen,theoption
dynamiclinker/lib/ldlinux.so.2specifiedthedynamiclinker.The
optionlrecordtellsthelinkertosearchforfunctionsinthefile
namedlibrecord.so.
Nowthewriterecordsprogramisbuilt,butitwillnotrun.Ifwe
tryit,wewillgetanerrorlikethefollowing:
./writerecords:errorwhileloadingsharedlibraries:
librecord.so:cannotopensharedobjectfile:Nosuch
fileordirectory

Thisisbecause,bydefault,thedynamiclinkeronlysearches/lib,
/usr/lib,andwhateverdirectoriesarelistedin/etc/ld.so.conffor
libraries.Inordertoruntheprogram,youeitherneedtomovethe
librarytooneofthesedirectories,orexecutethefollowing
command:
LD_LIBRARY_PATH=.
exportLD_LIBRARY_PATH

Alternatively,ifthatgivesyouanerror,dothisinstead:
setenvLD_LIBRARY_PATH.

Now,youcanrunwriterecordsnormallybytyping./writerecords.
SettingLD_LIBRARY_PATHtellsthelinkertoaddwhateverpathsyou
giveittothelibrarysearchpathfordynamiclibraries.
Forfurtherinformationaboutdynamiclinking,seethefollowing
sourcesontheInternet:
Themanpageforld.socontainsalotofinformationabouthowthe
Linuxdynamiclinkerworks.
http://www.benyossef.com/presentations/dlink/isagreatpresentation
ondynamiclinkinginLinux.

http://www.linuxjournal.com/article.php?sid=1059and
http://www.linuxjournal.com/article.php?sid=1060provideagood
introductiontotheELFfileformat,withmoredetailavailableat
http://www.cs.ucdavis.edu/~haungs/paper/node10.html
http://www.iecc.com/linker/linker10.htmlcontainsagreatdescription
ofhowdynamiclinkingworkswithELFfiles.
http://linux4u.jinr.ru/usoft/WWW/www_debian.org/Documentation/elf/nod
e21.htmlcontainsagoodintroductiontoprogramming
positionindependentcodeforsharedlibrariesunderLinux.

Review
KnowtheConcepts
Whataretheadvantagesanddisadvantagesofsharedlibraries?
Givenalibrarynamed'foo',whatwouldthelibrary'sfilenamebe?
Whatdoesthelddcommanddo?
Let'ssaywehadthefilesfoo.oandbar.o,andyouwantedtolink
themtogether,anddynamicallylinkthemtothelibrary'kramer'.
Whatwouldthelinkingcommandbetogeneratethefinalexecutable?
Whatis
typedef
for?
Whatare
structs
for?
Whatisthedifferencebetweenadataelementoftype
int
and
int
*?
Howwouldyouaccessthemdifferentlyinyourprogram?
Ifyouhadaobjectfilecalledfoo.o,whatwouldbethecommandto
createasharedlibrarycalled'bar'?
WhatisthepurposeofLD_LIBRARY_PATH?
UsetheConcepts
Rewriteoneormoreoftheprogramsfromthepreviouschaptersto
printtheirresultstothescreenusingprintfratherthanreturning
theresultastheexitstatuscode.Also,maketheexitstatuscode
be0.
UsethefactorialfunctionyoudevelopedintheSectioncalled
RecursiveFunctions
inChapter4tomakeasharedlibrary.Then
rewritethemainprogramsothatitlinkswiththelibrary
dynamically.
Rewritetheprogramabovesothatitalsolinkswiththe'c'library.
Usethe'c'library'sprintffunctiontodisplaytheresultofthe
factorialcall.
Rewritethetoupperprogramsothatitusestheclibraryfunctions
forfilesratherthansystemcalls.
GoingFurther
MakealistofalltheenvironmentvariablesusedbytheGNU/Linux
dynamiclinker.

Researchthedifferenttypesofexecutablefileformatsinusetoday
andinthehistoryofcomputing.Tellthestrengthsandweaknessesof
each.
Whatkindsofprogrammingareyouinterestedin(graphics,
databbases,science,etc.)?Findalibraryforworkinginthatarea,
andwriteaprogramthatmakessomebasicuseofthatlibrary.
ResearchtheuseofLD_PRELOAD.Whatisitusedfor?Trybuildinga
sharedlibrarythatcontainedtheexitfunction,andhaveitwritea
messagetoSTDERRbeforeexitting.UseLD_PRELOADandrunvarious
programswithit.Whataretheresults?

Chapter9:IntermediateMemory
Topics
HowaComputerViewsMemory
Let'sreviewhowmemorywithinacomputerworks.Youmayalsowantto
rereadChapter2.
Acomputerlooksatmemoryasalongsequenceofnumberedstorage
locations.Asequenceof
millions
ofnumberedstoragelocations.
Everythingisstoredintheselocations.Yourprogramsarestored
there,yourdataisstoredthere,everything.Eachstoragelocation
lookslikeeveryotherone.Thelocationsholdingyourprogramare
justliketheonesholdingyourdata.Infact,thecomputerhasno
ideawhicharewhich,exceptthattheexecutablefiletellsitwhere
tostartexecuting.
Thesestoragelocationsarecalledbytes.Thecomputercancombineup
tofourofthemtogetherintoasingleword.Normallynumericdatais
operatedonawordatatime.Aswementioned,instructionsarealso
storedinthissamememory.Eachinstructionisadifferentlength.
Mostinstructionstakeuponeortwostoragelocationsforthe
instructionitself,andthenstoragelocationsfortheinstruction's
arguments.Forexample,theinstruction
movldata_items(,%edi,4),%ebx

takesup7storagelocations.Thefirsttwoholdtheinstruction,the
thirdonetellswhichregisterstouse,andthenextfourholdthe
storagelocationofdata_items.Inmemory,instructionslookjust
likealltheothernumbers,andtheinstructionsthemselvescanbe
movedintoandoutofregistersjustlikenumbers,becausethat's
whattheyare.

Thischapterisfocusedonthedetailsofcomputermemory.Toget
startedlet'sreviewsomebasictermsthatwewillbeusinginthis
chapter:
Byte
Thisisthesizeofastoragelocation.Onx86processors,abytecan
holdnumbersbetween0and255.
Word
Thisisthesizeofanormalregister.Onx86processors,awordis
fourbyteslong.Mostcomputeroperationshandleawordatatime.
Address
Anaddressisanumberthatreferstoabyteinmemory.Forexample,
thefirstbyteonacomputerhasanaddressof0,thesecondhasan
1]
addressof1,andsoon.[

Everypieceofdataonthecomputernot
inaregisterhasanaddress.Theaddressofdatawhichspansseveral
bytesisthesameastheaddressofitsfirstbyte.
Normally,wedon'tevertypethenumericaddressofanything,butwe
lettheassemblerdoitforus.Whenweuselabelsincode,the
symbolusedinthelabelwillbeequivalenttotheaddressitis
labelling.Theassemblerwillthenreplacethatsymbolwithits
addresswhereveryouuseitinyourprogram.Forexample,sayyou
havethefollowingcode:
.section.data
my_data:
.long2,3,4

Now,anytimeintheprogramthatmy_dataisused,itwillbe
replacedbytheaddressofthefirstvalueofthe.longdirective.
Pointer
Apointerisaregisterormemorywordwhosevalueisanaddress.In
ourprogramsweuse%ebpasapointertothecurrentstackframe.All
basepointeraddressinginvolvespointers.Programmingusesalotof
pointers,soit'sanimportantconcepttograsp.
[1]
Youactuallyneveruseaddressesthislow,butitworksfor
discussion.

TheMemoryLayoutofaLinuxProgram
Whenyouprogramisloadedintomemory,each.sectionisloadedinto
itsownregionofmemory.Allofthecodeanddatadeclaredineach
sectionisbroughttogether,eveniftheywereseparatedinyour
sourcecode.
Theactualinstructions(the.textsection)areloadedattheaddress
0x08048000(numbersstartingwith0xareinhexadecimal,whichwill

2]
bediscussedinChapter10).[

The.datasectionisloaded
immediatelyafterthat,followedbythe.bsssection.
ThelastbytethatcanbeaddressedonLinuxislocationOxbfffffff.
Linuxstartsthestackhereandgrowsitdownwardtowardtheother
sections.Betweenthemisahugegap.Theinitiallayoutofthestack
isasfollows:Atthebottomofthestack(thebottomofthestackis
thetopaddressofmemoryseeChapter4),thereisawordofmemory
thatiszero.Afterthatcomesthenullterminatednameofthe
programusingASCIIcharacters.Aftertheprogramnamecomesthe
program'senvironmentvariables(thesearenotimportanttousin
thisbook).Thencometheprogram'scommandlinearguments.Theseare
thevaluesthattheusertypedinonthecommandlinetorunthis
program.Whenwerunas,forexample,wegiveitseveralarguments
as,sourcefile.s,o,andobjectfile.o.Afterthese,wehavethe
numberofargumentsthatwereused.Whentheprogrambegins,thisis
wherethestackpointer,%esp,ispointing.Furtherpushesonthe
stackmove%espdowninmemory.Forexample,theinstruction
pushl%eax

isequivalentto
movl%eax,(%esp)
subl$4,%esp

Likewise,theinstruction
popl%eax

isthesameas
movl(%esp),%eax
addl$4,%esp

Yourprogram'sdataregionstartsatthebottomofmemoryandgoes
up.Thestackstartsatthetopofmemory,andmovesdownwardwith
eachpush.Thismiddlepartbetweenthestackandyourprogram'sdata
sectionsisinaccessiblememoryyouarenotallowedtoaccessit
3]
untilyoutellthekernelthatyouneedit.[

Ifyoutry,youwill
getanerror(theerrormessageisusually"segmentationfault").The
samewillhappenifyoutrytoaccessdatabeforethebeginningof
yourprogram,0x08048000.Thelastaccessiblememoryaddresstoyour
programiscalledthe
systembreak
(alsocalledthe
currentbreak
or
justthe
break
).


MemoryLayoutofaLinuxProgramatStartup
[2]
Addressesmentionedinthischapterarenotsetinstoneandmay
varybasedonkernelversion.
[3]
Thestackcanaccessitasitgrowsdownward,andyoucanaccess
thestackregionsthrough%esp.However,yourprogram'sdatasection
doesn'tgrowthatway.Thewaytogrowthatwillbeexplained
shortly.

EveryMemoryAddressisaLie

So,whydoesthecomputernotallowyoutoaccessmemoryinthebreak
area?Toanswerthisquestion,wewillhavetodelveintothedepths
ofhowyourcomputerreallyhandlesmemory.
Youmayhavewondered,sinceeveryprogramgetsloadedintothesame
placeinmemory,don'ttheysteponeachother,oroverwriteeach
other?Itwouldseemso.However,asaprogramwriter,youonly
access
virtualmemory.
Physicalmemory
referstotheactualRAMchipsinsideyourcomputer
andwhattheycontain.It'susuallybetween16and512Megabyteson
moderncomputers.Ifwetalkabouta
physicalmemoryaddress,
weare
talkingaboutwhereexactlyonthesechipsapieceofmemoryis
located.Virtualmemoryistheway
yourprogram
thinksaboutmemory.
Beforeloadingyourprogram,Linuxfindsanemptyphysicalmemory
spacelargeenoughtofityourprogram,andthentellstheprocessor
topretendthatthismemoryisactuallyattheaddress0x0804800to
loadyourprograminto.Confusedyet?Letmeexplainfurther.
Eachprogramgetsitsownsandboxtoplayin.Everyprogramrunning
onyourcomputerthinksthatitwasloadedatmemoryaddress
0x0804800,andthatitsstackstartsatOxbffffff.WhenLinuxloadsa
program,itfindsasectionofunusedmemory,andthentellsthe
processortousethatsectionofmemoryastheaddress0x0804800for
thisprogram.Theaddressthataprogrambelievesitusesiscalled
thevirtualaddress,whiletheactualaddressonthechipsthatit
referstoiscalledthephysicaladdress.Theprocessofassigning
virtualaddressestophysicaladdressesiscalled
mapping.
Earlierwetalkedabouttheinaccessiblememorybetweenthe.bssand
thestack,butwedidn'ttalkaboutwhyitwasthere.Thereasonis
thatthisregionofvirtualmemoryaddresseshasn'tbeenmappedonto
physicalmemoryaddresses.Themappingprocesstakesupconsiderable
timeandspace,soifeverypossiblevirtualaddressofevery
possibleprogramweremapped,youwouldnothaveenoughphysical
memorytoevenrunoneprogram.So,thebreakisthebeginningofthe
areathatcontainsunmappedmemory.Withthestack,however,Linux
willautomaticallymapinmemorythatisaccessedfromstackpushes.
Ofcourse,thisisaverysimplifiedviewofvirtualmemory.Thefull
conceptismuchmoreadvanced.Forexample,Virtualmemorycanbe
mappedtomorethanjustphysicalmemoryitcanbemappedtodiskas
well.SwappartitionsonLinuxallowLinux'svirtualmemorysystemto
mapmemorynotonlytophysicalRAM,butalsotodiskblocksaswell.
Forexample,let'ssayyouonlyhave16Megabytesofphysicalmemory.
Let'salsosaythat8MegabytesarebeingusedbyLinuxandsome
basicapplications,andyouwanttorunaprogramthatrequires20
Megabytesofmemory.Canyou?Theanswerisyes,butonlyifyouhave

setupaswappartition.Whathappensisthatafterallofyour
remaining8Megabytesofphysicalmemoryhavebeenmappedinto
virtualmemory,Linuxstartsmappingpartsofyourapplication's
virtualmemorytodiskblocks.So,ifyouaccessa"memory"location
inyourprogram,thatlocationmaynotactuallybeinmemoryatall,
butondisk.Astheprogrammeryouwon'tknowthedifference,though,
becauseitisallhandledbehindthescenesbyLinux.
Now,x86processorscannotruninstructionsdirectlyfromdisk,nor
cantheyaccessdatadirectlyfromdisk.Thisrequiresthehelpof
theoperatingsystem.Whenyoutrytoaccessmemorythatismappedto
disk,theprocessornoticesthatitcan'tserviceyourmemoryrequest
directly.ItthenasksLinuxtostepin.Linuxnoticesthatthe
memoryisactuallyondisk.Therefore,itmovessomedatathatis
currentlyinmemoryontodisktomakeroom,andthenmovesthememory
beingaccessedfromthediskbackintophysicalmemory.Itthen
adjuststheprocessor'svirtualtophysicalmemorylookuptablesso
thatitcanfindthememoryinthenewlocation.Finally,Linux
returnscontroltotheprogramandrestartsitattheinstruction
whichwastryingtoaccessthedatainthefirstplace.This
instructioncannowbecompletedsuccessfully,becausethememoryis
4]
nowinphysicalRAM.[

Hereisanoverviewofthewaymemoryaccessesarehandledunder
Linux:
Theprogramtriestoloadmemoryfromavirtualaddress.
Theprocessor,usingtablessuppliedbyLinux,transformsthevirtual
memoryaddressintoaphysicalmemoryaddressonthefly.
Iftheprocessordoesnothaveaphysicaladdresslistedforthe
memoryaddress,itsendsarequesttoLinuxtoloadit.
Linuxlooksattheaddress.Ifitismappedtoadisklocation,it
continuesontothenextstep.Otherwise,itterminatestheprogram
withasegmentationfaulterror.
Ifthereisnotenoughroomtoloadthememoryfromdisk,Linuxwill
moveanotherpartoftheprogramoranotherprogramontodisktomake
room.
Linuxthenmovesthedataintoafreephysicalmemoryaddress.
Linuxupdatestheprocessor'svirtualtophysicalmemorymapping
tablestoreflectthechanges.
Linuxrestorescontroltotheprogram,causingittoreissuethe
instructionwhichcausedthisprocesstohappen.
Theprocessorcannowhandletheinstructionusingthenewlyloaded
memoryandtranslationtables.

It'salotofworkfortheoperatingsystem,butitgivestheuser
andtheprogrammergreatflexibilitywhenitcomestomemory
management.
Now,inordertomaketheprocessmoreefficient,memoryisseparated
outintogroupscalled
pages.
WhenrunningLinuxonx86processors,a
pageis4096bytesofmemory.Allofthememorymappingsaredonea
pageatatime.Physicalmemoryassignment,swapping,mapping,etc.
arealldonetomemorypagesinsteadofindividualmemoryaddresses.
Whatthismeanstoyouasaprogrammeristhatwheneveryouare
programming,youshouldtrytokeepmostmemoryaccesseswithinthe
samebasicrangeofmemory,soyouwillonlyneedapageortwoof
memoryatatime.Otherwise,Linuxmayhavetokeepmovingpageson
andoffofdisktosatisfyyourmemoryneeds.Diskaccessisslow,so
thiscanreallyslowdownyourprogram.
Sometimessomanyprogramscanbeloadedthatthereishardlyenough
physicalmemoryforthem.Theywindupspendingmoretimejust
swappingmemoryonandoffofdiskthantheydoactuallyprocessing
it.Thisleadstoaconditioncalled
swapdeath
whichleadstoyour
systembeingunresponsiveandunproductive.It'susuallyusually
recoverableifyoustartterminatingyourmemoryhungryprograms,but
it'sapain.
ResidentSetSize:
Theamountofmemorythatyourprogramcurrently
hasinphysicalmemoryiscalleditsresidentsetsize,andcanbe
viewedbyusingtheprogramtop.Theresidentsetsizeislisted
underthecolumnlabelled"RSS".
[4]
NotethatnotonlycanLinuxhaveavirtualaddressmaptoa
differentphysicaladdress,itcanalsomovethosemappingsaroundas
needed.

GettingMore

Memory
WenowknowthatLinuxmapsallofourvirtualmemoryintophysical
memoryorswap.Ifyoutrytoaccessapieceofvirtualmemorythat
hasn'tbeenmappedyet,ittriggersanerrorknownasasegmentation
fault,whichwillterminateyourprogram.Theprogrambreakpoint,if
youremember,isthelastvalidaddressyoucanuse.Now,thisisall

greatifyouknowbeforehandhowmuchstorageyouwillneed.Youcan
justaddallthememoryyouneedtoyour.dataor.bsssections,and
itwillallbethere.However,let'ssayyoudon'tknowhowmuch
memoryyouwillneed.Forexample,withatexteditor,youdon'tknow
howlongtheperson'sfilewillbe.Youcouldtrytofindamaximum
filesize,andjusttelltheuserthattheycan'tgobeyondthat,but
that'sawasteifthefileissmall.ThereforeLinuxhasafacility
tomovethebreakpointtoaccomodateanapplication'smemoryneeds.
Ifyouneedmorememory,youcanjusttellLinuxwhereyouwantthe
newbreakpointtobe,andLinuxwillmapallthememoryyouneed
betweenthecurrentandnewbreakpoint,andthenmovethebreak
pointtothespotyouspecify.Thatmemoryisnowavailableforyour
programtouse.ThewaywetellLinuxtomovethebreakpointis
throughthebrksystemcall.Thebrksystemcalliscallnumber45
(whichwillbein%eax).%ebxshouldbeloadedwiththerequested
breakpoint.Thenyoucallint$0x80tosignalLinuxtodoitswork.
Aftermappinginyourmemory,Linuxwillreturnthenewbreakpoint
in%eax.Thenewbreakpointmightactuallybelargerthanwhatyou
askedfor,becauseLinuxroundsuptothenearestpage.Ifthereis
notenoughphysicalmemoryorswaptofulfillyourrequest,Linux
willreturnazeroin%eax.Also,ifyoucallbrkwithazeroin
%ebx,itwillsimplyreturnthelastusablememoryaddress.
Theproblemwiththismethodiskeepingtrackofthememorywe
request.Let'ssayIneedtomovethebreaktohaveroomtoloada
file,andthenneedtomoveabreakagaintoloadanotherfile.Let's
sayIthengetridofthefirstfile.Younowhaveagiantgapin
memorythat'smapped,butthatyouaren'tusing.Ifyoucontinueto
movethebreakinthiswayforeachfileyouload,youcaneasilyrun
outofmemory.So,whatisneededisa
memorymanager.
Amemorymanagerisasetofroutinesthattakescareofthedirty
workofgettingyourprogrammemoryforyou.Mostmemorymanagers
5]
havetwobasicfunctionsallocateanddeallocate.[

Wheneveryou
needacertainamountofmemory,youcansimplytellallocatehow
muchyouneed,anditwillgiveyoubackanaddresstothememory.
Whenyou'redonewithit,youtelldeallocatethatyouarethrough
withit.allocatewillthenbeabletoreusethememory.Thispattern
ofmemorymanagementiscalled
dynamicmemoryallocation.
This
minimizesthenumberof"holes"inyourmemory,makingsurethatyou
aremakingthebestuseofityoucan.Thepoolofmemoryusedby
memorymanagersiscommonlyreferredtoas
theheap.
Thewaymemorymanagersworkisthattheykeeptrackofwherethe
systembreakis,andwherethememorythatyouhaveallocatedis.
Theymarkeachblockofmemoryintheheapasbeingusedorunused.

Whenyourequestmemory,thememorymanagercheckstoseeifthere
areanyunusedblocksoftheappropriatesize.Ifnot,itcallsthe
brksystemcalltorequestmorememory.Whenyoufreememoryitmarks
theblockasunusedsothatfuturerequestscanretrieveit.Inthe
nextsectionwewilllookatbuildingourownmemorymanager.
[5]
Thefunctionnamesusuallyaren'tallocateanddeallocate,butthe
functionalitywillbethesame.IntheCprogramminglanguage,for
example,theyarenamedmallocandfree.

ASimpleMemoryManager
HereIwillshowyouasimplememorymanager.Itisveryprimitive
butitshowstheprinciplesquitewell.Asusual,Iwillgiveyouthe
programfirstforyoutolookthrough.Afterwardswillfollowan
indepthexplanation.Itlookslong,butitismostlycomments.
#PURPOSE:Programtomanagememoryusageallocates
#anddeallocatesmemoryasrequested
#
#NOTES:Theprogramsusingtheseroutineswillask
#foracertainsizeofmemory.Weactually
#usemorethanthatsize,butweputit
#atthebeginning,beforethepointer
#wehandback.Weaddasizefieldand
#anAVAILABLE/UNAVAILABLEmarker.So,the
#memorylookslikethis
#
##########################################################
##AvailableMarker#Sizeofmemory#Actualmemorylocations#
##########################################################
#^Returnedpointer
#pointshere
#Thepointerwereturnonlypointstotheactual
#locationsrequestedtomakeiteasierforthe
#callingprogram.Italsoallowsustochangeour
#structurewithoutthecallingprogramhavingto
#changeatall.

.section.data
#######GLOBALVARIABLES########

#Thispointstothebeginningofthememorywearemanaging
heap_begin:

.long0

#Thispointstoonelocationpastthememorywearemanaging
current_break:
.long0

######STRUCTUREINFORMATION####
#sizeofspaceformemoryregionheader
.equHEADER_SIZE,8
#Locationofthe"available"flagintheheader
.equHDR_AVAIL_OFFSET,0
#Locationofthesizefieldintheheader
.equHDR_SIZE_OFFSET,4

###########CONSTANTS###########
.equUNAVAILABLE,0#Thisisthenumberwewillusetomark
#spacethathasbeengivenout
.equAVAILABLE,1#Thisisthenumberwewillusetomark
#spacethathasbeenreturned,andis
#availableforgiving
.equSYS_BRK,45#systemcallnumberforthebreak
#systemcall

.equLINUX_SYSCALL,0x80#makesystemcallseasiertoread

.section.text
##########FUNCTIONS############

##allocate_init##
#PURPOSE:callthisfunctiontoinitializethe
#functions(specifically,thissetsheap_beginand
#current_break).Thishasnoparametersandno
#returnvalue.
.globlallocate_init
.typeallocate_init,@function
allocate_init:
pushl%ebp#standardfunctionstuff
movl%esp,%ebp

#Ifthebrksystemcalliscalledwith0in%ebx,it
#returnsthelastvalidusableaddress
movl$SYS_BRK,%eax#findoutwherethebreakis
movl$0,%ebx
int$LINUX_SYSCALL

incl%eax#%eaxnowhasthelastvalid
#address,andwewantthe
#memorylocationafterthat

movl%eax,current_break#storethecurrentbreak

movl%eax,heap_begin#storethecurrentbreakasour
#firstaddress.Thiswillcause
#theallocatefunctiontoget
#morememoryfromLinuxthe
#firsttimeitisrun

movl%ebp,%esp#exitthefunction
popl%ebp
ret
#####ENDOFFUNCTION#######

##allocate##
#PURPOSE:Thisfunctionisusedtograbasectionof
#memory.Itcheckstoseeifthereareany
#freeblocks,and,ifnot,itasksLinux
#foranewone.
#
#PARAMETERS:Thisfunctionhasoneparameterthesize
#ofthememoryblockwewanttoallocate
#
#RETURNVALUE:
#Thisfunctionreturnstheaddressofthe
#allocatedmemoryin%eax.Ifthereisno
#memoryavailable,itwillreturn0in%eax
#
######PROCESSING########
#Variablesused:
#
#%ecxholdthesizeoftherequestedmemory
#(first/onlyparameter)

#%eaxcurrentmemoryregionbeingexamined
#%ebxcurrentbreakposition
#%edxsizeofcurrentmemoryregion
#
#Wescanthrougheachmemoryregionstartingwith
#heap_begin.Welookatthesizeofeachone,andif
#ithasbeenallocated.Ifit'sbigenoughforthe
#requestedsize,anditsavailable,itgrabsthatone.
#Ifitdoesnotfindaregionlargeenough,itasks
#Linuxformorememory.Inthatcase,itmoves
#current_breakup
.globlallocate
.typeallocate,@function
.equST_MEM_SIZE,8#stackpositionofthememorysize
#toallocate
allocate:
pushl%ebp#standardfunctionstuff
movl%esp,%ebp

movlST_MEM_SIZE(%ebp),%ecx#%ecxwillholdthesize
#wearelookingfor(whichisthefirst
#andonlyparameter)

movlheap_begin,%eax#%eaxwillholdthecurrent
#searchlocation

movlcurrent_break,%ebx#%ebxwillholdthecurrent
#break

alloc_loop_begin:#hereweiteratethrougheach
#memoryregion

cmpl%ebx,%eax#needmorememoryiftheseareequal
jemove_break

#grabthesizeofthismemory
movlHDR_SIZE_OFFSET(%eax),%edx
#Ifthespaceisunavailable,gotothe
cmpl$UNAVAILABLE,HDR_AVAIL_OFFSET(%eax)
jenext_location#nextone

cmpl%edx,%ecx#Ifthespaceisavailable,compare

jleallocate_here#thesizetotheneededsize.Ifits
#bigenough,gotoallocate_here
next_location:
addl$HEADER_SIZE,%eax#Thetotalsizeofthememory
addl%edx,%eax#regionisthesumofthesize
#requested(currentlystored
#in%edx),plusanother8bytes
#fortheheader(4forthe
#AVAILABLE/UNAVAILABLEflag,
#and4forthesizeofthe
#region).So,adding%edxand$8
#to%eaxwillgettheaddress
#ofthenextmemoryregion

jmpalloc_loop_begin#golookatthenextlocation

allocate_here:#ifwe'vemadeithere,
#thatmeansthatthe
#regionheaderoftheregion
#toallocateisin%eax

#markspaceasunavailable
movl$UNAVAILABLE,HDR_AVAIL_OFFSET(%eax)
addl$HEADER_SIZE,%eax#move%eaxpasttheheaderto
#theusablememory(since
#that'swhatwereturn)

movl%ebp,%esp#returnfromthefunction
popl%ebp
ret

move_break:#ifwe'vemadeithere,that
#meansthatwehaveexhausted
#alladdressablememory,and
#weneedtoaskformore.
#%ebxholdsthecurrent
#endpointofthedata,
#and%ecxholdsitssize

#weneedtoincrease%ebxto
#wherewe_want_memory
#toend,sowe

addl$HEADER_SIZE,%ebx#addspacefortheheaders
#structure
addl%ecx,%ebx#addspacetothebreakfor
#thedatarequested

#nowitstimetoaskLinux
#formorememory

pushl%eax#saveneededregisters
pushl%ecx
pushl%ebx

movl$SYS_BRK,%eax#resetthebreak(%ebxhas
#therequestedbreakpoint)
int$LINUX_SYSCALL
#undernormalconditions,thisshould
#returnthenewbreakin%eax,which
#willbeeither0ifitfails,or
#itwillbeequaltoorlargerthan
#weaskedfor.Wedon'tcare
#inthisprogramwhereitactually
#setsthebreak,soaslongas%eax
#isn't0,wedon'tcarewhatitis

cmpl$0,%eax#checkforerrorconditions
jeerror

popl%ebx#restoresavedregisters
popl%ecx
popl%eax

#setthismemoryasunavailable,sincewe'reaboutto
#giveitaway
movl$UNAVAILABLE,HDR_AVAIL_OFFSET(%eax)
#setthesizeofthememory
movl%ecx,HDR_SIZE_OFFSET(%eax)

#move%eaxtotheactualstartofusablememory.
#%eaxnowholdsthereturnvalue
addl$HEADER_SIZE,%eax

movl%ebx,current_break#savethenewbreak

movl%ebp,%esp#returnthefunction
popl%ebp
ret

error:
movl$0,%eax#onerror,wereturnzero
movl%ebp,%esp
popl%ebp
ret
########ENDOFFUNCTION########

##deallocate##
#PURPOSE:
#Thepurposeofthisfunctionistogiveback
#aregionofmemorytothepoolafterwe'redone
#usingit.
#
#PARAMETERS:
#Theonlyparameteristheaddressofthememory
#wewanttoreturntothememorypool.
#
#RETURNVALUE:
#Thereisnoreturnvalue
#PROCESSING:
#Ifyouremember,weactuallyhandtheprogramthe
#startofthememorythattheycanuse,whichis
#8storagelocationsaftertheactualstartofthe
#memoryregion.Allwehavetodoisgoback
#8locationsandmarkthatmemoryasavailable,
#sothattheallocatefunctionknowsitcanuseit.
.globldeallocate
.typedeallocate,@function
#stackpositionofthememoryregiontofree
.equST_MEMORY_SEG,4
deallocate:
#sincethefunctionissosimple,we
#don'tneedanyofthefancyfunctionstuff

#gettheaddressofthememorytofree
#(normallythisis8(%ebp),butsince
#wedidn'tpush%ebpormove%espto
#%ebp,wecanjustdo4(%esp)

movlST_MEMORY_SEG(%esp),%eax

#getthepointertotherealbeginningofthememory
subl$HEADER_SIZE,%eax

#markitasavailable
movl$AVAILABLE,HDR_AVAIL_OFFSET(%eax)

#return
ret
########ENDOFFUNCTION##########

Thefirstthingtonoticeisthatthereisno_startsymbol.The
reasonisthatthisisjustasetoffunctions.Amemorymanagerby
itselfisnotafullprogramitdoesn'tdoanything.Itissimplya
utilitytobeusedbyotherprograms.
Toassembletheprogram,dothefollowing:
asalloc.soalloc.o

Okay,nowlet'slookatthecode.
VariablesandConstants
Atthebeginningoftheprogram,wehavetwolocationssetup:
heap_begin:
.long0

current_break:
.long0

Remember,thesectionofmemorybeingmanagediscommonlyreferredto
asthe
heap.
Whenweassembletheprogram,wehavenoideawherethe
beginningoftheheapis,norwherethecurrentbreakis.Therefore,
wereservespacefortheiraddresses,butjustfillthemwitha0for
thetimebeing.
Nextwehaveasetofconstantstodefinethestructureoftheheap.
Thewaythismemorymanagerworksisthatbeforeeachregionof
memoryallocated,wewillhaveashortrecorddescribingthememory.
Thisrecordhasawordreservedfortheavailableflagandawordfor
theregion'ssize.Theactualmemoryallocatedimmediatelyfollows
thisrecord.Theavailableflagisusedtomarkwhetherthisregion
isavailableforallocations,orifitiscurrentlyinuse.Thesize
fieldletsusknowbothwhetherornotthisregionisbigenoughfor

anallocationrequest,aswellasthelocationofthenextmemory
region.Thefollowingconstantsdescribethisrecord:
.equHEADER_SIZE,8
.equHDR_AVAIL_OFFSET,0
.equHDR_SIZE_OFFSET,4

Thissaysthattheheaderis8bytestotal,theavailableflagis
offset0bytesfromthebeginning,andthesizefieldisoffset4
bytesfromthebeginning.Ifwearecarefultoalwaysusethese
constants,thenweprotectourselvesfromhavingtodotoomuchwork
ifwelaterdecidetoaddmoreinformationtotheheader.
Thevaluesthatwewilluseforouravailablefieldareeither0for
unavailable,or1foravailable.Tomakethiseasiertoread,wehave
thefollowingdefinitions:
.equUNAVAILABLE,0
.equAVAILABLE,1

Finally,wehaveourLinuxsystemcalldefinitions:
.equBRK,45
.equLINUX_SYSCALL,0x80

Theallocate_initFunction
Okay,thisisasimplefunction.Allitdoesissetuptheheap_begin
andcurrent_breakvariableswediscussedearlier.So,ifyouremember
thediscussionearlier,thecurrentbreakcanbefoundusingthebrk
systemcall.So,thefunctionstartslikethis:
pushl%ebp
movl%esp,%ebp

movl$SYS_BRK,%eax
movl$0,%ebx
int$LINUX_SYSCALL

Anyway,afterint$LINUX_SYSCALL,%eaxholdsthelastvalidaddress.
Weactuallywantthefirstinvalidaddressinsteadofthelastvalid
address,sowejustincrement%eax.Thenwemovethatvaluetothe
heap_beginandcurrent_breaklocations.Thenweleavethefunction.
Thecodelookslikethis:
incl%eax
movl%eax,current_break
movl%eax,heap_begin
movl%ebp,%esp
popl%ebp

ret

Theheapconsistsofthememorybetweenheap_beginandcurrent_break,
sothissaysthatwestartoffwithaheapofzerobytes.Our
allocatefunctionwillthenextendtheheapasmuchasitneedsto
whenitiscalled.
TheallocateFunction
Thisisthedoozyfunction.Let'sstartbylookingatanoutlineof
thefunction:
Startatthebeginningoftheheap.
Checktoseeifwe'reattheendoftheheap.
Ifweareattheendoftheheap,grabthememoryweneedfromLinux,
markitas"unavailable"andreturnit.IfLinuxwon'tgiveusany
more,returna0.
Ifthecurrentmemoryregionismarked"unavailable",gotothenext
one,andgobacktostep2.
Ifthecurrentmemoryregionistoosmalltoholdtherequested
amountofspace,gobacktostep2.
Ifthememoryregionisavailableandlargeenough,markitas
"unavailable"andreturnit.
Now,lookbackthroughthecodewiththisinmind.Besuretoread
thecommentssoyou'llknowwhichregisterholdswhichvalue.
Nowthatyou'velookedbackthroughthecode,let'sexamineitone
lineatatime.Westartofflikethis:
pushl%ebp
movl%esp,%ebp
movlST_MEM_SIZE(%ebp),%ecx
movlheap_begin,%eax
movlcurrent_break,%ebx

Thispartinitializesallofourregisters.Thefirsttwolinesare
standardfunctionstuff.Thenextmovepullsthesizeofthememory
toallocateoffofthestack.Thisisouronlyfunctionparameter.
Afterthat,itmovesthebeginningheapaddressandtheendofthe
heapintoregisters.Iamnowreadytodoprocessing.
Thenextsectionismarkedalloc_loop_begin.Inthisloopweare
goingtoexaminememoryregionsuntilweeitherfindanopenmemory
regionordeterminethatweneedmorememory.Ourfirstinstructions
checktoseeifweneedmorememory:
cmpl%ebx,%eax
jemove_break

%eaxholdsthecurrentmemoryregionbeingexaminedand%ebxholds
thelocationpasttheendoftheheap.Thereforeifthenextregion
tobeexaminedispasttheendoftheheap,itmeansweneedmore
memorytoallocatearegionofthissize.Let'sskipdownto
move_breakandseewhathappensthere:
move_break:
addl$HEADER_SIZE,%ebx
addl%ecx,%ebx
pushl%eax
pushl%ecx
pushl%ebx
movl$SYS_BRK,%eax
int$LINUX_SYSCALL

Whenwereachthispointinthecode,%ebxholdswherewewantthe
nextregionofmemorytobe.So,weaddourheadersizeandregion
sizeto%ebx,andthat'swherewewantthesystembreaktobe.We
thenpushalltheregisterswewanttosaveonthestack,andcall
thebrksystemcall.Afterthatwecheckforerrors:
cmpl$0,%eax
jeerror

Iftherewerenoerrorswepoptheregistersbackoffthestack,mark
thememoryasunavailable,recordthesizeofthememory,andmake
sure%eaxpointstothestartofusablememory(whichis
after
the
header).
popl%ebx
popl%ecx
popl%eax
movl$UNAVAILABLE,HDR_AVAIL_OFFSET(%eax)
movl%ecx,HDR_SIZE_OFFSET(%eax)
addl$HEADER_SIZE,%eax

Thenwestorethenewprogrambreakandreturnthepointertothe
allocatedmemory.
movl%ebx,current_break
movl%ebp,%esp
popl%ebp
ret

Theerrorcodejustreturns0in%eax,sowewon'tdiscussit.

Let'sgobacklookattherestoftheloop.Whathappensifthe
currentmemorybeinglookedatisn'tpasttheendoftheheap?Well,
let'slook.
movlHDR_SIZE_OFFSET(%eax),%edx
cmpl$UNAVAILABLE,HDR_AVAIL_OFFSET(%eax)
jenext_location

Thisfirstgrabsthesizeofthememoryregionandputsitin%edx.
Thenitlooksattheavailableflagtoseeifitissetto
UNAVAILABLE.Ifso,thatmeansthatmemoryregionisinuse,sowe'll
havetoskipoverit.So,iftheavailableflagissetto
UNAVAILABLE,yougotothecodelabelednext_location.Ifthe
availableflagissettoAVAILABLE,thenwekeepongoing.
Let'ssaythatthespacewasavailable,andsowekeepgoing.Thenwe
checktoseeifthisspaceisbigenoughtoholdtherequestedamount
ofmemory.Thesizeofthisregionisbeingheldin%edx,sowedo
this:
cmpl%edx,%ecx
jleallocate_here

Iftherequestedsizeislessthanorequaltothecurrentregion's
size,wecanusethisblock.Itdoesn'tmatterifthecurrentregion
islargerthanrequested,becausetheextraspacewilljustbe
unused.So,let'sjumpdowntoallocate_hereandseewhathappens:
movl$UNAVAILABLE,HDR_AVAIL_OFFSET(%eax)
addl$HEADER_SIZE,%eax
movl%ebp,%esp
popl%ebp
ret

Itmarksthememoryasbeingunavailable.Thenitmovesthepointer
%eaxpasttheheader,andusesitasthereturnvalueforthe
function.Remember,thepersonusingthisfunctiondoesn'tneedto
evenknowaboutourmemoryheaderrecord.Theyjustneedapointerto
usablememory.
Okay,solet'ssaytheregionwasn'tbigenough.Whatthen?Well,we
wouldthenbeatthecodelabelednext_location.Thissectionofcode
isusedanytimethatwefigureoutthatthecurrentmemoryregion
won'tworkforallocatingmemory.Allitdoesisadvance%eaxtothe
nextpossiblememoryregion,andgoesbacktothebeginningofthe
loop.Rememberthat%edxisholdingthesizeofthecurrentmemory
region,andHEADER_SIZEisthesymbolforthesizeofthememory
region'sheader.Sothiscodewillmoveustothenextmemoryregion:

addl$HEADER_SIZE,%eax
addl%edx,%eax
jmpalloc_loop_begin

Andnowthefunctionrunsanotherloop.
Wheneveryouhavealoop,youmustmakesurethatitwill
always
end.
Thebestwaytodothatistoexamineallofthepossibilities,and
makesurethatallofthemeventuallyleadtotheloopending.Inour
case,wehavethefollowingpossibilities:
Wewillreachtheendoftheheap
Wewillfindamemoryregionthat'savailableandlargeenough
Wewillgotothenextlocation
Thefirsttwoitemsareconditionsthatwillcausethelooptoend.
Thethirdonewillkeepitgoing.However,evenifweneverfindan
openregion,wewilleventuallyreachtheendoftheheap,becauseit
isafinitesize.Therefore,weknowthatnomatterwhichcondition
istrue,theloophastoeventuallyhitaterminatingcondition.
ThedeallocateFunction
Thedeallocatefunctionismucheasierthantheallocateone.That's
becauseitdoesn'thavetodoanysearchingatall.Itcanjustmark
thecurrentmemoryregionasAVAILABLE,andallocatewillfindit
nexttimeitiscalled.Sowehave:
movlST_MEMORY_SEG(%esp),%eax
subl$HEADER_SIZE,%eax
movl$AVAILABLE,HDR_AVAIL_OFFSET(%eax)
ret

Inthisfunction,wedon'thavetosave%ebpor%espsincewe'renot
changingthem,nordowehavetorestorethemattheend.Allwe're
doingisreadingtheaddressofthememoryregionfromthestack,
backinguptothebeginningoftheheader,andmarkingtheregionas
available.Thisfunctionhasnoreturnvalue,sowedon'tcarewhat
weleavein%eax.
PerformanceIssuesandOtherProblems
Oursimplisticmemorymanagerisnotreallyusefulforanythingmore
thananacademicexercise.Thissectionlooksattheproblemswith
suchasimplisticallocator.
Thebiggestproblemhereisspeed.Now,ifthereareonlyafew
allocationsmade,thenspeedwon'tbeabigissue.Butthinkabout
whathappensifyoumakeathousandallocations.Onallocationnumber
1000,youhavetosearchthrough999memoryregionstofindthatyou
havetorequestmorememory.Asyoucansee,that'sgettingpretty

slow.Inaddition,rememberthatLinuxcankeeppagesofmemoryon
diskinsteadofinmemory.So,sinceyouhavetogothroughevery
pieceofmemoryyourprogram'smemory,thatmeansthatLinuxhasto
loadeverypartofmemorythat'scurrentlyondisktochecktoseeif
itisavailable.Youcanseehowthiscouldgetreally,reallyslow.
[6]
Thismethodissaidtorunin
linear
time,whichmeansthatevery
elementyouhavetomanagemakesyourprogramtakelonger.Aprogram
thatrunsin
constant
timetakesthesameamountoftimenomatter
howmanyelementsyouaremanaging.Takethedeallocatefunction,for
instance.Itonlyruns4instructions,nomatterhowmanyelementswe
aremanaging,orwheretheyareinmemory.Infact,althoughour
allocatefunctionisoneoftheslowestofallmemorymanagers,the
deallocatefunctionisoneofthefastest.
Anotherperformanceproblemisthenumberoftimeswe'recallingthe
brksystemcall.Systemcallstakealongtime.Theyaren'tlike
functions,becausetheprocessorhastoswitchmodes.Yourprogram
isn'tallowedtomapitselfmemory,buttheLinuxkernelis.So,the
processorhastoswitchinto
kernelmode,
thenLinuxmapsthememory,
andthenswitchesbackto
usermode
foryourapplicationtocontinue
running.Thisisalsocalleda
contextswitch.
Contextswitchesare
relativelyslowonx86processors.Generally,youshouldavoid
callingthekernelunlessyoureallyneedto.
Anotherproblemthatwehaveisthatwearen'trecordingwhereLinux
actuallysetsthebreak.PreviouslywementionedthatLinuxmight
actuallysetthebreakpastwherewerequestedit.Inthisprogram,
wedon'tevenlookatwhereLinuxactuallysetsthebreakwejust
assumeitsetsitwherewerequested.That'snotreallyabug,butit
willleadtounnecessarybrksystemcallswhenwealreadyhavethe
memorymappedin.
Anotherproblemwehaveisthatifwearelookingfora5byteregion
ofmemory,andthefirstopenonewecometois1000bytes,wewill
simplymarkthewholethingasallocatedandreturnit.Thisleaves
995bytesofunused,butallocated,memory.Itwouldbeniceinsuch
situationstobreakitapartsotheother995bytescanbeused
later.Itwouldalsobenicetocombineconsecutivefreespaceswhen
lookingforlargeallocations.
[6]
Thisiswhyaddingmorememorytoyourcomputermakesitrun
faster.Themorememoryyourcomputerhas,thelessitputsondisk,
soitdoesn'thavetoalwaysbeinterruptingyourprogramsto
retreivepagesoffthedisk.

UsingOurAllocator

Theprogramswedointhisbookaren'tcomplicatedenoughto
necessitateamemorymanager.Therefore,wewilljustuseourmemory
managertoallocateabufferforoneofourfilereading/writing
programsinsteadofassigningitinthe.bss.
Theprogramwewilldemonstratethisonisreadrecords.sfrom
Chapter6.Thisprogramusesabuffernamedrecord_buffertohandle
itsinput/outputneeds.Wewillsimplychangethisfrombeinga
bufferdefinedin.bsstobeingapointertoadynamicallyallocated
bufferusingourmemorymanager.Youwillneedtohavethecodefrom
thatprogramhandyaswewillonlybediscussingthechangesinthis
section.
Thefirstchangeweneedtomakeisinthedeclaration.Currentlyit
lookslikethis:
.section.bss
.lcomm,record_buffer,RECORD_SIZE

Itwouldbeamisnomertokeepthesamename,sinceweareswitching
itfrombeinganactualbuffertobeingapointertoabuffer.In
addition,itnowonlyneedstobeonewordbig(enoughtoholda
pointer).Thenewdeclarationwillstayinthe.datasectionandlook
likethis:
record_buffer_ptr:
.long0

Ournextchangeisweneedtoinitializeourmemorymanager
immediatelyafterwestartourprogram.Therefore,rightafterthe
stackissetup,thefollowingcallneedstobeadded:
callallocate_init

Afterthat,thememorymanagerisreadytostartservicingmemory
allocationrequests.Weneedtoallocateenoughmemorytoholdthese
recordsthatwearereading.Therefore,wewillcallallocateto
allocatethismemory,andthensavethepointeritreturnsinto
record_buffer_ptr.Likethis:
pushl$RECORD_SIZE
callallocate
movl%eax,record_buffer_ptr

Now,whenwemakethecalltoread_record,itisexpectingapointer.
Intheoldcode,thepointerwastheimmediatemodereferenceto
record_buffer.Now,record_buffer_ptrjustholdsthepointerrather
thanthebufferitself.Therefore,wemustdoadirectmodeloadto
getthevalueinrecord_buffer_ptr.Weneedtoremovethisline:

pushl$record_buffer

Andputthislineinitsplace:
pushlrecord_buffer_ptr

Thenextchangecomeswhenwearetryingtofindtheaddressofthe
firstnamefieldofourrecord.Intheoldcode,itwas
$RECORD_FIRSTNAME+record_buffer.However,thatonlyworksbecause
itisaconstantoffsetfromaconstantaddress.Inthenewcode,it
istheoffsetofanaddressstoredinrecord_buffer_ptr.Togetthat
value,wewillneedtomovethepointerintoaregister,andthenadd
$RECORD_FIRSTNAMEtoittogetthepointer.Sowherewehavethe
followingcode:
pushl$RECORD_FIRSTNAME+record_buffer

Weneedtoreplaceitwiththis:
movlrecord_buffer_ptr,%eax
addl$RECORD_FIRSTNAME,%eax
pushl%eax

Similarly,weneedtochangethelinethatsays
movl$RECORD_FIRSTNAME+record_buffer,%ecx

sothatitreadslikethis:
movlrecord_buffer_ptr,%ecx
addl$RECORD_FIRSTNAME,%ecx

Finally,onechangethatweneedtomakeistodeallocatethememory
oncewearedonewithit(inthisprogramit'snotnecessary,but
it'sagoodpracticeanyway).Todothat,wejustsend
record_buffer_ptrtothedeallocatefunctionrightbeforeexitting:
pushlrecord_buffer_ptr
calldeallocate

Nowyoucanbuildyourprogramwiththefollowingcommands:
asreadrecords.soreadrecords.o
ldalloc.oreadrecord.oreadrecords.owritenewline.ocount
chars.ooreadrecords

Youcanthenrunyourprogrambydoing./readrecords.

Theusesofdynamicmemoryallocationmaynotbeapparenttoyouat
thispoint,butasyougofromacademicexercisestoreallife
programsyouwilluseitcontinually.

MoreInformation
MoreinformationonmemoryhandlinginLinuxandotheroperating
systemscanbefoundatthefollowinglocations:
MoreinformationaboutthememorylayoutofLinuxprogramscanbe
foundinKonstantinBoldyshev'sdocument,"Startupstateofa
Linux/i386ELFbinary",availableat
http://linuxassembly.org/startup.html
Agoodoverviewofvirtualmemoryinmanydifferentsystemsis
availableathttp://cne.gmu.edu/modules/vm/
SeveralindeptharticlesonLinux'svirtualmemorysubsystemis
availableathttp://www.nongnu.org/lkdp/files.html
DougLeahaswrittenupadescriptionofhispopularmemoryallocator
athttp://gee.cs.oswego.edu/dl/html/malloc.html
Apaperonthe4.4BSDmemoryallocatorisavailableat
http://docs.freebsd.org/44doc/papers/malloc.html

Review
KnowtheConcepts
DescribethelayoutofmemorywhenaLinuxprogramstarts.
Whatistheheap?
Whatisthecurrentbreak?
Whichdirectiondoesthestackgrowin?
Whichdirectiondoestheheapgrowin?
Whathappenswhenyouaccessunmappedmemory?
Howdoestheoperatingsystempreventprocessesfromwritingover
eachother'smemory?
Describetheprocessthatoccursifapieceofmemoryyouareusing
iscurrentlyresidingondisk?
Whydoyouneedanallocator?
UsetheConcepts
Modifythememorymanagersothatitcallsallocate_init
automaticallyifithasn'tbeeninitialized.
Modifythememorymanagersothatiftherequestedsizeofmemoryis
smallerthantheregionchosen,itwillbreakuptheregioninto
multipleparts.Besuretotakeintoaccountthesizeofthenew
headerrecordwhenyoudothis.

Modifyoneofyourprogramsthatusesbufferstousethememory
managertogetbuffermemoryratherthanusingthe.bss.
GoingFurther
Research
garbagecollection.
Whatadvantagesanddisadvantagesdoes
thishaveoverthestyleofmemorymanagementusedhere?
Research
referencecounting.
Whatadvantagesanddisadvantagesdoes
thishaveoverthestyleofmemorymanagementusedhere?
Changethenameofthefunctionstomallocandfree,andbuildthem
intoasharedlibrary.UseLD_PRELOADtoforcethemtobeusedas
yourmemorymanagerinsteadofthedefaultone.Addsomewritesystem
callstoSTDOUTtoverifythatyourmemorymanagerisbeingused
insteadofthedefaultone.

Chapter10:Countinglikea
Computer
Counting
CountinglikeaHuman
Inmanyways,computerscountjustlikehumans.So,beforewestart
learninghowcomputerscount,let'stakeadeeperlookathowwe
count.
Howmanyfingersdoyouhave?No,it'snotatrickquestion.Humans
(normally)havetenfingers.Whyisthatsignificant?Lookatour
numberingsystem.Atwhatpointdoesaonedigitnumberbecomea
twodigitnumber?That'sright,atten.Humanscountanddomath
usingabasetennumberingsystem.Basetenmeansthatwegroup
everythingintens.Let'ssaywe'recountingsheep.1,2,3,4,5,6,
7,8,9,10.Whydidweallofasuddennowhavetwodigits,and
reusethe1?That'sbecausewe'regroupingournumbersbyten,and
wehave1groupoftensheep.Okay,let'sgotothenextnumber11.
Thatmeanswehave1groupoftensheep,and1sheepleftungrouped.
Sowecontinue12,13,14,15,16,17,18,19,20.Nowwehave2
groupsoften.212groupsoften,and1sheepungrouped.222
groupsoften,and2sheepungrouped.So,let'ssaywekeepcounting,
andgetto97,98,99,and100.Look,ithappenedagain!Whathappens
at100?Wenowhavetengroupsoften.At101wehavetengroupsof
ten,and1ungroupedsheep.Sowecanlookatanynumberlikethis.
Ifwecounted60879sheep,thatwouldmeanthatwehad6groupsof
tengroupsoftengroupsoftengroupsoften,0groupsoftengroups

oftengroupsoften,8groupsoftengroupsoften,7groupsoften,
and9sheepleftungrouped.
So,isthereanythingsignificantaboutgroupingthingsbyten?No!
It'sjustthatgroupingbytenishowwe'vealwaysdoneit,because
wehavetenfingers.Wecouldhavegroupedatnineorateleven(in
whichcasewewouldhavehadtomakeupanewsymbol).Theonly
differencebetweenthedifferentgroupingsofnumbersisthatwehave
torelearnourmultiplication,addition,subtraction,anddivision
tablesforeachgrouping.Theruleshaven'tchanged,justthewaywe
representthem.Also,someofourtricksthatwelearneddon'talways
apply,either.Forexample,let'ssaywegroupedbynineinsteadof
ten.Movingthedecimalpointonedigittotherightnolonger
multipliesbyten,itnowmultipliesbynine.Inbasenine,500is
onlyninetimesaslargeas50.
CountinglikeaComputer
Thequestionis,howmanyfingersdoesthecomputerhavetocount
with?Thecomputeronlyhastwofingers.Sothatmeansallofthe
groupsaregroupsoftwo.So,let'scountinbinary0(zero),1
(one),10(twoonegroupoftwo),11(threeonegroupoftwoand
oneleftover),100(fourtwogroupsoftwo),101(fivetwo
groupsoftwoandoneleftover),110(sixtwogroupsoftwoand
onegroupoftwo),andsoon.Inbasetwo,movingthedecimalone
digittotherightmultipliesbytwo,andmovingittotheleft
dividesbytwo.Basetwoisalsoreferredtoasbinary.
Thenicethingaboutbasetwoisthatthebasicmathtablesarevery
short.Inbaseten,themultiplicationtablesaretencolumnswide,
andtencolumnstall.Inbasetwo,itisverysimple:
Tableofbinaryaddition

+|0|1
++
0|0|0
++
1|1|10

Tableofbinarymultiplication
*|0|1
++
0|0|0
++
1|0|1

So,let'saddthenumbers10010101with1100101:

10010101
+1100101

11111010

Now,let'smultiplythem:
10010101
*1100101

10010101
00000000
10010101
00000000
00000000
10010101
10010101

11101011001001

ConversionsbetweenBinaryandDecimal
Let'slearnhowtoconvertnumbersfrombinary(basetwo)todecimal
(baseten).Thisisactuallyarathersimpleprocess.Ifyou
remember,eachdigitstandsforsomegroupingoftwo.So,wejust
needtoaddupwhateachdigitrepresents,andwewillhaveadecimal
number.Takethebinarynumber10010101.Tofindoutwhatitisin
decimal,wetakeitapartlikethis:
10010101
||||||||
|||||||Individualunits(2^0)
||||||0groupsof2(2^1)
|||||1groupof4(2^2)
||||0groupsof8(2^3)
|||1groupof16(2^4)
||0groupsof32(2^5)
|0groupsof64(2^6)
1groupof128(2^7)

andthenweaddallofthepiecestogether,likethis:
1*128+0*64+0*32+1*16+0*8+1*4+0*2+1*1=
128+16+4+1=
149

So10010101inbinaryis149indecimal.Let'slookat1100101.It
canbewrittenas
1*64+1*32+0*16+0*8+1*4+0*2+1*1=
64+32+4+1=
101

Soweseethat1100101inbinaryis101indecimal.Let'slookatone
morenumber,11101011001001.Youcanconvertittodecimalbydoing
1*8192+1*4096+1*2048+0*1024+1*512+0*256
+1*128+1*64+0*32+0*16+1*8+0*4
+0*2+1*1=

8192+4096+2048+512+128+64+8+1=

15049

Now,ifyou'vebeenpayingattention,youhavenoticedthatthe
numberswejustconvertedarethesameonesweusedtomultiplywith
earlier.So,let'scheckourresults:101*149=15049.Itworked!
Nowlet'slookatgoingfromdecimalbacktobinary.Inordertodo
theconversion,youhaveto
divide
thenumberintogroupsoftwo.So,
let'ssayyouhadthenumber17.Ifyoudivideitbytwo,youget8
with1leftover.Sothatmeansthereare8groupsoftwo,and1
ungrouped.Thatmeansthattherightmostdigitwillbe1.Now,we
havetherigtmostdigitfiguredout,and8groupsof2leftover.
Now,let'sseehowmanygroupsoftwogroupsoftwowehave,by
dividing8by2.Weget4,withnothingleftover.Thatmeansthat
allgroupstwocanbefurtherdividedintomoregroupsoftwo.So,we
have0groupsofonlytwo.Sothenextdigittotheleftis0.So,we
divide4by2andgettwo,with0leftover,sothenextdigitis0.
Then,wedivide2by2andget1,with0leftover.Sothenextdigit
is0.Finally,wedivide1by2andget0with1leftover,sothe
nextdigittotheleftis1.Now,there'snothingleft,sowe're
done.So,thenumberwewoundupwithis10001.
Previously,weconvertedtobinary11101011001001todecimal15049.
Let'sdothereversetomakesurethatwediditright:
15049/2=7524Remaining1
7524/2=3762Remaining0
3762/2=1881Remaining0
1881/2=940Remaining1
940/2=470Remaining0
470/2=235Remaining0
235/2=117Remaining1

117/2=58Remaining1
58/2=29Remaining0
29/2=14Remaining1
14/2=7Remaining0
7/2=3Remaining1
3/2=1Remaining1
1/2=0Remaining1

Then,weputtheremainingnumbersbacktogether,andwehavethe
originalnumber!Rememberthefirstdivisionremaindergoestothe
farright,sofromthebottomupyouhave11101011001001.
Eachdigitinabinarynumberiscalleda
bit,
whichstandsfor
binarydigit.
Remember,computersdivideuptheirmemoryintostorage
locationscalledbytes.Eachstoragelocationonanx86processor
(andmostothers)is8bitslong.Earlierwesaidthatabytecan
holdanynumberbetween0and255.Thereasonforthisisthatthe
largestnumberyoucanfitinto8bitsis255.Youcanseethisfor
yourselfifyouconvertbinary11111111intodecimal:
11111111=

(1*2^7)+(1*2^6)+(1*2^5)+(1*2^4)+(1*2^3)
+(1*2^2)+(1*2^1)+(1*2^0)=

128+64+32+16+8+4+2+1=

255

Thelargestnumberthatyoucanholdin16bitsis65535.Thelargest
numberyoucanholdin32bitsis4294967295(4billion).Thelargest
numberyoucanholdin64bitsis18,446,744,073,709,551,615.The
largestnumberyoucanholdin128bitsis
340,282,366,920,938,463,463,374,607,431,768,211,456.Anyway,yousee
thepicture.Forx86processors,mostofthetimeyouwilldealwith
4bytenumbers(32bits),becausethat'sthesizeoftheregisters.

Truth,Falsehood,andBinaryNumbers
Nowwe'veseenthatthecomputerstoreseverythingassequencesof
1'sand0's.Let'slookatsomeotherusesofthis.Whatif,instead
oflookingatasequenceofbitsasanumber,weinsteadlookedatit
asasetofswitches.Forexample,let'ssaytherearefourswitches
thatcontrollightinginthehouse.Wehaveaswitchforoutside
lights,aswitchforthehallwaylights,aswitchforthelivingroom

lights,andaswitchforthebedroomlights.Wecouldmakealittle
tableshowingwhichofthesewereonandoff,likeso:
OutsideHallwayLivingRoomBedroom
OnOffOnOn

It'sobviousfromlookingatthisthatallofthelightsareon
exceptthehallwayones.Now,insteadofusingthewords"On"and
"Off",let'susethenumbers1and0.1willrepresenton,and0will
representoff.So,wecouldrepresentthesameinformationas
OutsideHallwayLivingRoomBedroom
1011

Now,insteadofhavinglabelsonthelightswitches,let'ssaywe
justmemorizedwhichpositionwentwithwhichswitch.Then,thesame
informationcouldberepresentedas
1011

oras
1011

Thisisjustoneofmanywaysyoucanusethecomputersstorage
locationstorepresentmorethanjustnumbers.Thecomputersmemory
justseesnumbers,butprogrammerscanusethesenumberstorepresent
anythingtheirimaginationscancomeupwith.Theyjustsometimes
havetobecreativewhenfiguringoutthebestrepresentation.
Notonlycanyoudoregulararithmeticwithbinarynumbers,theyalso
haveafewoperationsoftheirown,calledbinaryorlogical
operations.Thestandardbinaryoperationsare
AND
OR
NOT
XOR
Beforewelookatexamples,I'lldescribethemforyou.ANDtakestwo
bitsandreturnsonebit.ANDwillreturna1onlyifbothbitsare
1,anda0otherwise.Forexample,1AND1is1,but1AND0is0,0
AND1is0,and0AND0is0.
ORtakestwobitsandreturnsonebit.Itwillreturn1ifeitherof
theoriginalbitsis1.Forexample,1OR1is1,1OR0isone,0OR
1is1,but0OR0is0.
NOTonlytakesonebitandreturnsitsopposite.NOT1is0andNOT0
is1.
Finally,XORislikeOR,exceptitreturns0ifbothbitsare1.

Computerscandotheseoperationsonwholeregistersatatime.For
example,ifaregisterhas10100010101010010101101100101010and
anotheronehas10001000010101010101010101111010,youcanrunanyof
theseoperationsonthewholeregisters.Forexample,ifwewereto
ANDthem,thecomputerwillrunfromthefirstbittothe32ndand
runtheANDoperationonthatbitinbothregisters.Inthiscase:
10100010101010010101101100101010AND
10001000010101010101010101111010

10000000000000010101000100101010

You'llseethattheresultingsetofbitsonlyhasaonewhere
both
numbershadaone,andineveryotherpositionithasazero.Let's
lookatwhatanORlookslike:
10100010101010010101101100101010OR
10001000010101010101010101111010

10101010111111010101111101111010

Inthiscase,theresultingnumberhasa1whereeithernumberhasa
1inthegivenposition.Let'slookattheNOToperation:
NOT10100010101010010101101100101010

01011101010101101010010011010101

Thisjustreverseseachdigit.Finally,wehaveXOR,whichislikean
OR,exceptif
both
digitsare1,itreturns0.
10100010101010010101101100101010XOR
10001000010101010101010101111010

00101010111111000000111001010000

ThisisthesametwonumbersusedintheORoperation,soyoucan
comparehowtheywork.Also,ifyouXORanumberwithitself,you
willalwaysget0,likethis:
10100010101010010101101100101010XOR
10100010101010010101101100101010

00000000000000000000000000000000

Theseoperationsareusefulfortworeasons:
Thecomputercandothemextremelyfast

Youcanusethemtocomparemanytruthvaluesatthesametime
Youmaynothaveknownthatdifferentinstructionsexecuteat
differentspeeds.It'strue,theydo.Andtheseoperationsarethe
fastestonmostprocessors.Forexample,yousawthatXORinganumber
withitselfproduces0.Well,theXORoperationisfasterthanthe
loadingoperation,somanyprogrammersuseittoloadaregisterwith
zero.Forexample,thecode
movl$0,%eax

isoftenreplacedby
xorl%eax,%eax

We'lldiscussspeedmoreinChapter12,butIwantyoutoseehow
programmersoftendotrickythings,especiallywiththesebinary
operators,tomakethingsfast.Nowlet'slookathowwecanuse
theseoperatorstomanipulatetrue/falsevalues.Earlierwediscussed
howbinarynumberscanbeusedtorepresentanynumberofthings.
Let'susebinarynumberstorepresentwhatthingsmyDadandIlike.
First,let'slookatthethingsIlike:
Food:yes
HeavyMetalMusic:yes
WearingDressyClothes:no
Football:yes

Now,let'slookatwhatmyDadlikes:
Food:yes
HeavyMetalMusic:no
WearingDressyClothes:yes
Football:yes

Now,let'susea1tosayyeswelikesomething,anda0tosaynowe
don't.Nowwehave:
Me
Food:1
HeavyMetalMusic:1
WearingDressyClothes:0
Football:1

Dad
Food:1
HeavyMetalMusic:0
WearingDressyClothes:1

Football:1

Now,ifwejustmemorizewhichpositioneachofthesearein,wehave
Me
1101

Dad
1011

Now,let'sseewewanttogetalistofthingsbothmyDadandI
like.YouwouldusetheANDoperation.So
1101AND
1011

1001

Whichtranslatesto
Thingswebothlike
Food:yes
HeavyMetalMusic:no
WearingDressyClothes:no
Football:yes

Remember,thecomputerhasnoideawhattheonesandzeroes
represent.That'syourjobandyourprogram'sjob.Ifyouwrotea
programaroundthisrepresentationyourprogramwouldatsomepoint
examineeachbitandhavecodetotelltheuserwhatit'sfor(ifyou
askedacomputerwhattwopeopleagreedonanditanswered1001,it
wouldn'tbeveryuseful).Anyway,let'ssaywewanttoknowthe
thingsthatwedisagreeon.ForthatwewoulduseXOR,becauseit
willreturn1onlyifoneortheotheris1,butnotboth.So
1101XOR
1011

0110

AndI'llletyoutranslatethatbackout.
Thepreviousoperations:AND,OR,NOT,andXORarecalled
boolean
operators
becausetheywerefirststudiedbyGeorgeBoole.So,if
someonementionesbooleanoperatorsorbooleanalgebra,younowknow
whattheyaretalkingabout.

Inadditiontothebooleanoperations,therearealsotwobinary
operatorsthataren'tboolean,shiftandrotate.Shiftsandrotates
eachdowhattheirnameimplies,andcandosototherightorthe
left.Aleftshiftmoveseachdigitofabinarynumberonespaceto
theleft,putsazerointheonesspot,andchopsoffthefurthest
digittotheleft.Aleftrotatedoesthesamething,buttakesthe
furthestdigittotheleftandputsitintheonesspot.Forexample,
Shiftleft10010111=00101110
Rotateleft10010111=00101111

Noticethatifyourotateanumberforeverydigitithas(i.e.
rotatinga32bitnumber32times),youwindupwiththesamenumber
youstartedwith.However,ifyou
shift
anumberforeverydigityou
have,youwindupwith0.So,whataretheseshiftsusefulfor?Well,
ifyouhavebinarynumbersrepresentingthings,youuseshiftsto
peekateachindividualvalue.Let'ssay,forinstance,thatwehad
myDad'slikesstoredinaregister(32bits).Itwouldlooklike
this:
00000000000000000000000000001011

Now,aswesaidpreviously,thisdoesn'tworkasprogramoutput.So,
inordertodooutput,wewouldneedtodoshiftingand
masking.
Maskingistheprocessofeliminatingeverythingyoudon'twant.In
thiscase,foreveryvaluewearelookingfor,wewillshiftthe
numbersothatvalueisintheonesplace,andthenmaskthatdigit
sothatitisallwesee.MaskingisaccomplishedbydoinganAND
withanumberthathasthebitsweareinterestedinsetto1.For
example,let'ssaywewantedtoprintoutwhethermyDadlikesdressy
clothesornot.Thatdataisthesecondvaluefromtheright.So,we
havetoshiftthenumberright1digitsoitlookslikethis:
00000000000000000000000000000101

andthen,wejustwanttolookatthatdigit,sowemaskitbyANDing
itwith00000000000000000000000000000001.
00000000000000000000000000000101AND
00000000000000000000000000000001

00000000000000000000000000000001

Thiswillmakethevalueoftheregister1ifmyDadlikesdressy
clothes,and0ifhedoesn't.Thenwecandoacomparisonto1and
printtheresults.Thecodewouldlooklikethis:

#NOTEassumethattheregister%ebxholds
#myDad'spreferences

movl%ebx,%eax#Thiscopiestheinformationinto%eaxso
#wedon'tlosetheoriginaldata

shrl$1,%eax#Thisistheshiftoperator.Itstands
#forShiftRightLong.Thisfirstnumber
#isthenumberofpositionstoshift,
#andthesecondistheregistertoshift

#Thisdoesthemasking
andl$0b00000000000000000000000000000001,%eax

#Checktoseeiftheresultis1or0
cmpl$0b00000000000000000000000000000001,%eax

jeyes_he_likes_dressy_clothes

jmpno_he_doesnt_like_dressy_clothes

Andthenwewouldhavetwolabelswhichprintedsomethingabout
whetherornothelikesdressyclothesandthenexits.The0b
notationmeansthatwhatfollowsisabinarynumber.Inthiscaseit
wasn'tneeded,because1isthesameinanynumberingsystem,butI
putitthereforclarity.Wealsodidn'tneedthe31zeroes,butI
putthemintomakeapointthatthenumberyouareusingis32bits.
Whenanumberrepresentsasetofoptionsforafunctionorsystem
call,theindividualtrue/falseelementsarecalled
flags.
Many
systemcallshavenumerousoptionsthatareallsetinthesame
registerusingamechanismlikewe'vedescribed.Theopensystem
call,forexample,hasasitssecondparameteralistofflagsto
telltheoperatingsystemhowtoopenthefile.Someoftheflags
include:
O_WRONLY
Thisflagis0b00000000000000000000000000000001inbinary,or01in
octal(oranynumbersystemforthatmatter).Thissaystoopenthe
fileinwriteonlymode.
O_RDWR
Thisflagis0b00000000000000000000000000000010inbinary,or02in
octal.Thissaystoopenthefileforbothreadingandwriting.
O_CREAT

Thisflagis0b00000000000000000000000001000000inbinary,or0100in
octal.Itmeanstocreatethefileifitdoesn'talreadyexist.
O_TRUNC
Thisflagis0b00000000000000000000001000000000inbinary,or01000
inoctal.Itmeanstoerasethecontentsofthefileifthefile
alreadyexists.
O_APPEND
Thisflagis0b00000000000000000000010000000000inbinary,or02000
inoctal.Itmeanstostartwritingattheendofthefilerather
thanatthebeginning.
Tousetheseflags,yousimplyORthemtogetherinthecombination
thatyouwant.Forexample,toopenafileinwriteonlymode,and
haveitcreatethefileifitdoesn'texist,IwoulduseO_WRONLY
(01)andO_CREAT(0100).OR'dtogether,Iwouldhave0101.
Notethatifyoudon'tseteitherO_WRONLYorO_RDWR,thenthefile
isautomaticallyopenedinreadonlymode(O_RDONLY,exceptthatit
isn'treallyaflagsinceit'szero).
Manyfunctionsandsystemcallsuseflagsforoptions,asitallowsa
singlewordtoholdupto32possibleoptionsifeachoptionis
representedbyasinglebit.

TheProgramStatusRegister
We'veseenhowbitsonaregistercanbeusedtogivetheanswersof
yes/noandtrue/falsestatements.Onyourcomputer,thereisa
registercalledthe
programstatusregister.
Thisregisterholdsa
lotofinformationaboutwhathappensinacomputation.Forexample,
haveyoueverwonderedwhatwouldhappenifyouaddedtwonumbersand
theresultwaslargerthanwouldfitinaregister?Theprogram
statusregisterhasaflagcalledthecarryflag.Youcantestitto
seeifthelastcomputationoverflowedtheregister.Thereareflags
foranumberofdifferentstatuses.Infact,whenyoudoacompare
(cmpl)instruction,theresultisstoredinthisregister.The
conditionaljumpinstructions(jge,jne,etc)usetheseresultsto
tellwhetherornottheyshouldjump.jmp,theunconditionaljump,
doesn'tcarewhatisinthestatusregister,sinceitis
unconditional.
Let'ssayyouneededtostoreanumberlargerthan32bits.So,let's
saythenumberis2registerswide,or64bits.Howcouldyouhandle
this?Ifyouwantedtoaddtwo64bitnumbers,youwouldaddthe
leastsignificantregistersfirst.Then,ifyoudetectedancarry,
youcouldaddItothemostsignificantregister.Infact,thisis

probablythewayyoulearnedtododecimaladdition.Iftheresultin
onecolumnismorethan9,yousimplycarriedthenumbertothenext
mostsignificantcolumn.Ifyouadded65and37,firstyouadd7and
4toget12.Youkeepthe2intherightcolumn,andcarrytheoneto
thenextcolumn.Thereyouadd6,3,andthe1youcarried.This
resultsin10.So,youkeepthezerointhatcolumnandcarrytheone
tothenextmostsignificantcolumn,whichisempty,soyoujustput
theonethere.Luckily,32bitsisusuallybigenoughtoholdthe
numbersweuseregularly.
AdditionalprogramstatusregisterflagsareexaminedinAppendixB.

OtherNumberingSystems
Whatwehavestudiedsofaronlyappliestopositiveintegers.
However,realworldnumbersarenotalwayspositiveintegers.
Negativenumbersandnumberswithdecimalsarealsoused.

FloatingPointNumbers
Sofar,theonlynumberswe'vedealtwithareintegersnumberswith
nodecimalpoint.Computershaveageneralproblemwithnumberswith
decimalpoints,becausecomputerscanonlystorefixedsize,finite
values.Decimalnumberscanbeanylength,includinginfinitelength
(thinkofarepeatingdecimal,liketheresultof1/3).
Thewayacomputerhandlesdecimalsisbystoringthematafixed
precision(numberofsignificantbits).Acomputerstoresdecimal
numbersintwopartsthe
exponent
andthe
mantissa.
Themantissa
containstheactualdigitsthatwillbeused,andtheexponentis
whatmagnitudethenumberis.Forexample,12345.2canberepresented
as1.23452*10^4.Themantissais1.23452andtheexponentis4with
abaseof10.Computers,however,useabaseof2.Allnumbersare
storedasX.XXXXX*2^XXXX.Thenumber1,forexample,isstoredas
1.00000*2^0.Separatingthemantissaandtheexponentintotwo
differentvaluesiscalleda
floatingpoint
representation,because
thepositionofthesignificantdigitswithrespecttothedecimal
pointcanvarybasedontheexponent.
Now,themantissaandtheexponentareonlysolong,whichleadsto
someinterestingproblems.Forexample,whenacomputerstoresan
integer,ifyouadd1toit,theresultingnumberisonelarger.This
doesnotnecessarilyhappenwithfloatingpointnumbers.Ifthe
numberissufficientlybig,adding1toitmightnotevenregisterin

themantissa(remember,bothpartsareonlysolong).Thisaffects
severalthings,especiallyorderofoperations.Ifyouadd1.0toa
givenfloatingpointnumber,itmightnotevenaffectthenumberif
itislargeenough.Forexample,onx86platforms,afourbyte
floatingpointnumber,althoughitcanrepresentverylargenumbers,
cannothave1.0addedtoitpast16777216.0,becauseitisnolonger
significant.Thenumbernolongerchangeswhen1.0isaddedtoit.
So,ifthereisamultiplicationfollowedbyanadditionitmaygive
adifferentresultthaniftheadditionisperformedfirst.
Youshouldnotethatittakesmostcomputersalotlongertodo
floatingpointarithmeticthanitdoesintegerarithmetic.So,for
programsthatreallyneedspeed,integersaremostlyused.

NegativeNumbers
Howwouldyouthinkthatnegativenumbersonacomputermightbe
represented?Onethoughtmightbetousethefirstdigitofanumber
asthesign,so00000000000000000000000000000001wouldrepresentthe
number1,and10000000000000000000000000000001wouldrepresent1.
Thismakesalotofsense,andinfactsomeoldprocessorsworkthis
way.However,ithassomeproblems.Firstofall,ittakesalotmore
circuitrytoaddandsubtractsignednumbersrepresentedthisway.
Evenmoreproblematic,thisrepresentationhasaproblemwiththe
number0.Inthissystem,youcouldhavebothanegativeanda
positive0.Thisleadstoalotofquestions,like"shouldnegative
zerobeequaltopositivezero?",and"Whatshouldthesignofzero
beinvariouscircumstances?".
Theseproblemswereovercomebyusingarepresentationofnegative
numberscalled
two'scomplement
representation.Togetthenegative
representationofanumberintwo'scomplementform,youmustperform
thefollowingsteps:
1.PerformaNOToperationonthenumber
2.Addonetotheresultingnumber
So,togetthenegativeof00000000000000000000000000000001,you
wouldfirstdoaNOToperation,whichgives
1111111111111111111111111111110,andthenaddone,giving
11111111111111111111111111111111.Togetnegativetwo,firsttake
00000000000000000000000000000010.TheNOTofthatnumberis
11111111111111111111111111111101.Addingonegives
11111111111111111111111111111110.Withthisrepresentation,youcan
addnumbersjustasiftheywerepositive,andcomeoutwiththe
rightanswers.Forexample,ifyouaddoneplusnegativeonein
binary,youwillnoticethatallofthenumbersfliptozero.Also,

thefirstdigitstillcarriesthesignbit,makingitsimpleto
determinewhetherornotthenumberispositiveornegative.Negative
numberswillalwayshavea1intheleftmostbit.Thisalsochanges
whichnumbersarevalidforagivennumberofbits.Withsigned
numbers,thepossiblemagnitudeofthevaluesissplittoallowfor
bothpositiveandnegativenumbers.Forexample,abytecannormally
havevaluesupto255.Asignedbyte,however,canstorevaluesfrom
128to127.
Onethingtonoteaboutthetwo'scomplementrepresentationofsigned
numbersisthat,unlikeunsignedquantities,ifyouincreasethe
numberofbits,youcan'tjustaddzeroestotheleftofthenumber.
Forexample,let'ssaywearedealingwithfourbitquantitiesandwe
hadthenumber3,1101.Ifweweretoextendthisintoaneightbit
register,wecouldnotrepresentitas00001101asthiswould
represent13,not3.Whenyouincreasethesizeofasignedquantity
intwo'scomplementrepresentation,youhavetoperform
sign
extension.
Signextensionmeansthatyouhavetopadthelefthand
sideofthequantitywithwhateverdigitisinthesigndigitwhen
youaddbits.So,ifweextendanegativenumberby4digits,we
shouldfillthenewdigitswitha1.Ifweextendapositivenumber
by4digits,weshouldfillthenewdigitswitha0.So,the
extensionof3fromfourtoeightbitswillyield11111101.
Thex86processorhasdifferentformsofseveralinstructions
dependingonwhethertheyexpectthequantitiestheyoperateontobe
signedorunsigned.ThesearelistedinAppendixB.Forexample,the
x86processorhasbothasignpreservingshiftright,sarl,anda
shiftrightwhichdoesnotpreservethesignbit,shrl.

OctalandHexadecimalNumbers
Thenumberingsystemsdiscussedsofarhavebeendecimalandbinary.
However,twoothersareusedcommonincomputingoctaland
hexadecimal.Infact,theyareprobablywrittenmoreoftenthan
binary.Octalisarepresentationthatonlyusesthenumbers0
through7.Sotheoctalnumber10isactually8indecimalbecauseit
isonegroupofeight.Octal121isdecimal81(onegroupof64
(8^2),twogroupsof8,andoneleftover).Whatmakesoctalniceis
thatevery3binarydigitsmakeoneoctaldigit(thereisnosuch
groupingofbinarydigitsintodecimal).So0is000,1is001,2is
010,3is011,4is100,5is101,6is110,and7is111.
PermissionsinLinuxaredoneusingoctal.ThisisbecauseLinux
permissionsarebasedontheabilitytoread,writeandexecute.The

firstbitisthereadpermission,thesecondbitisthewrite
permission,andthethirdbitistheexecutepermission.So,0(000)
givesnopermissions,6(110)givesreadandwritepermission,and5
(101)givesreadandexecutepermissions.Thesenumbersarethenused
forthethreedifferentsetsofpermissionstheowner,thegroup,
andeveryoneelse.Thenumber0644meansreadandwriteforthefirst
permissionset,andreadonlyforthesecondandthirdset.Thefirst
permissionsetisfortheownerofthefile.Thethirdpermissionset
isforthegroupownerofthefile.Thelastpermissionsetisfor
everyoneelse.So,0751meansthattheownerofthefilecanread,
write,andexecutethefile,thegroupmemberscanreadandexecute
thefile,andeveryoneelsecanonlyexecutethefile.
Anyway,asyoucansee,octalisusedtogroupbits(binarydigits)
intothrees.Thewaytheassemblerknowsthatanumberisoctalis
becauseoctalnumbersareprefixedwithazero.Forexample010means
10inoctal,whichis8indecimal.Ifyoujustwrite10thatmeans
10indecimal.Thebeginningzeroiswhatdifferentiatesthetwo.So,
becarefulnottoputanyleadingzeroesinfrontofdecimalnumbers,
ortheywillbeinterepretedasoctalnumbers
!
Hexadecimalnumbers(alsocalledjust"hex")usethenumbers115for
eachdigit.however,since1015don'thavetheirownnumbers,
hexadecimalusesthelettersathroughftorepresentthem.For
example,theletterarepresents10,theletterbrepresents11,and
soon.10inhexadecimalis16indecimal.Inoctal,eachdigit
representedthreebits.Inhexadecimal,eachdigitrepresentsfour
bits.Everytwodigitsisafullbyte,andeightdigitsisa32bit
word.Soyousee,itisconsiderablyeasiertowriteahexadecimal
numberthanitistowriteabinarynumber,becauseit'sonlya
quarterasmanydigits.Themostimportantnumbertorememberin
hexadecimalisf,whichmeansthatallbitsareset.So,ifIwantto
setallofthebitsofaregisterto1,Icanjustdo
movl$0xFFFFFFFF,%eax

Whichisconsiderablyeasierandlesserrorpronethanwriting
movl$0b11111111111111111111111111111111,%eax

Notealsothathexadecimalnumbersareprefixedwith0x.So,whenwe
do
int$0x80

Wearecallinginterruptnumber128(8groupsof16),orinterrupt
number0b00000000000000000000000010000000.

Hexadecimalandoctalnumberstakesomegettingusedto,buttheyare
heavilyusedincomputerprogramming.Itmightbeworthwhiletomake
upsomenumbersinhexandtrytoconvertthembackandforthto
binary,decimal,andoctal.

OrderofBytesinaWord
Onethingthatconfusesmanypeoplewhendealingwithbitsandbytes
onalowlevelisthat,whenbytesarewrittenfromregistersto
memory,theirbytesarewrittenoutleastsignificantportionfirst.
[1]
Whatmostpeopleexpectisthatiftheyhaveawordinaregister,
say0x5d23efee(thespacingissoyoucanseewherethebytes
are),thebyteswillbewrittentomemoryinthatorder.However,on
x86processors,thebytesareactuallywritteninreverseorder.In
memorythebyteswouldbe0xeeef235donx86processors.Thebytes
arewritteninreverseorderfromwhattheywouldappear
conceptually,butthebitswithinthebytesareorderednormally.
Notallprocessorsbehavethisway.Thex86processorisa
littleendian
processor,whichmeansthatitstoresthe"littleend",
orleastsignificantbyteofitswordsfirst.

Registertomemorytransfersonlittleendiansystems
Otherprocessorsare
bigendian
processors,whichmeansthatthey
storethe"bigend",ormostsignificantbyte,oftheirwordsfirst,
thewaywewouldnaturallyreadanumber.


Registertomemorytransfersonbigendiansystems
Thisdifferenceisnotnormallyaproblem(althoughithassparked
manytechnicalcontroversiesthroughouttheyears).Becausethebytes
arereversedagain(ornot,ifitisabigendianprocessor)when
beingreadbackintoaregister,theprogrammerusuallynevernotices
whatorderthebytesarein.Thebyteswitchingmagichappens
automaticallybehindthescenesduringregistertomemorytransfers.
However,thebyteordercancauseproblemsinseveralinstances:
Ifyoutrytoreadinseveralbytesatatimeusingmovlbutdeal
withthemonabytebybytebasisusingtheleastsignificantbyte
(i.e.byusing%aland/orshiftingoftheregister),thiswillbe
inadifferentorderthantheyappearinmemory.
Ifyoureadorwritefileswrittenfordifferentarchitectures,you
mayhavetoaccountforwhateverordertheywritetheirbytesin.
Ifyoureadorwritetonetworksockets,youmayhavetoaccountfor
adifferentbyteorderintheprotocol.
Aslongasyouareawareoftheissue,itusuallyisn'tabigdeal.
Formoreindepthlookatbyteorderissues,youshouldreadDAV's
EndianFAQathttp://www.rdrop.com/~cary/html/endian_faq.html,
especiallythearticle"OnHolyWarsandaPleaforPeace"byDaniel
Cohen.
[1]
Significance
inthiscontextisreferringtowhichdigitthey
represent.Forexample,inthenumber294,thedigit2isthemost
significantbecauseitrepresentsthehundredsplace,9isthenext
mostsignificant,and4istheleastsignificant.

ConvertingNumbersforDisplay
Sofar,wehavebeenunabletodisplayanynumberstoredtotheuser,
exceptbytheextremelylimittedmeansofpassingitthroughexit
codes.Inthissection,wewilldiscussconvertingpositivenumbers
intostringsfordisplay.
Thefunctionwillbecalledinteger2string,anditwilltaketwo
parametersanintegertoconvertandastringbufferfilledwith
nullcharacters(zeroes).Thebufferwillbeassumedtobebigenough
tostoretheentirenumberasastring.(atleast11characterslong,
toincludeatrailingnullcharacter).
Rememberthatthewaythatweseenumbersisinbase10.Therefore,
toaccesstheindividualdecimaldigitsofanumber,weneedtobe
dividingby10anddisplayingtheremainderforeachdigit.
Therefore,theprocesswilllooklikethis:
Dividethenumberbyten
Theremainderisthecurrentdigit.Convertittoacharacterand
storeit.
Wearefinishedifthequotientiszero.
Otherwise,takethequotientandthenextlocationinthebufferand
repeattheprocess.
Theonlyproblemisthatsincethisprocessdealswiththeone's
placefirst,itwillleavethenumberbackwards.Therefore,wewill
havetofinishbyreversingthecharacters.Wewilldothisby
storingthecharactersonthestackaswecomputethem.Thisway,as
wepopthembackofftofillinthebuffer,itwillbeinthereverse
orderthatwepushedthemon.
Thecodeforthefunctionshouldbeputinafilecalled
integertostring.sandshouldbeenteredasfollows:
#PURPOSE:Convertanintegernumbertoadecimalstring
#fordisplay
#
#INPUT:Abufferlargeenoughtoholdthelargest
#possiblenumber
#Anintegertoconvert
#
#OUTPUT:Thebufferwillbeoverwrittenwiththe
#decimalstring
#
#Variables:
#
#%ecxwillholdthecountofcharactersprocessed

#%eaxwillholdthecurrentvalue
#%ediwillholdthebase(10)
#
.equST_VALUE,8
.equST_BUFFER,12

.globlinteger2string
.typeinteger2string,@function
integer2string:
#Normalfunctionbeginning
pushl%ebp
movl%esp,%ebp
#Currentcharactercount
movl$0,%ecx

#Movethevalueintoposition
movlST_VALUE(%ebp),%eax

#Whenwedivideby10,the10
#mustbeinaregisterormemorylocation
movl$10,%edi

conversion_loop:
#Divisionisactuallyperformedonthe
#combined%edx:%eaxregister,sofirst
#clearout%edx
movl$0,%edx

#Divide%edx:%eax(whichareimplied)by10.
#Storethequotientin%eaxandtheremainder
#in%edx(bothofwhichareimplied).
divl%edi

#Quotientisintherightplace.%edxhas
#theremainder,whichnowneedstobeconverted
#intoanumber.So,%edxhasanumberthatis
#0through9.Youcouldalsointerpretthisas
#anindexontheASCIItablestartingfromthe
#character'0'.Theasciicodefor'0'pluszero
#isstilltheasciicodefor'0'.Theasciicode
#for'0'plus1istheasciicodeforthe
#character'1'.Therefore,thefollowing
#instructionwillgiveusthecharacterforthe

#numberstoredin%edx
addl$'0',%edx

#Nowwewilltakethisvalueandpushitonthe
#stack.Thisway,whenwearedone,wecanjust
#popoffthecharactersonebyoneandtheywill
#beintherightorder.Notethatwearepushing
#thewholeregister,butweonlyneedthebyte
#in%dl(thelastbyteofthe%edxregister)for
#thecharacter.
pushl%edx

#Incrementthedigitcount
incl%ecx

#Checktoseeif%eaxiszeroyet,gotonext
#stepifso.
cmpl$0,%eax
jeend_conversion_loop

#%eaxalreadyhasitsnewvalue.

jmpconversion_loop

end_conversion_loop:
#Thestringisnowonthestack,ifwepopit
#offacharacteratatimewecancopyitinto
#thebufferandbedone.

#Getthepointertothebufferin%edx
movlST_BUFFER(%ebp),%edx

copy_reversing_loop:
#Wepushedawholeregister,butweonlyneed
#thelastbyte.Sowearegoingtopopoffto
#theentire%eaxregister,butthenonlymovethe
#smallpart(%al)intothecharacterstring.
popl%eax
movb%al,(%edx)
#Decreasing%ecxsoweknowwhenwearefinished
decl%ecx
#Increasing%edxsothatitwillbepointingto
#thenextbyte

incl%edx

#Checktoseeifwearefinished
cmpl$0,%ecx
#Ifso,jumptotheendofthefunction
jeend_copy_reversing_loop
#Otherwise,repeattheloop
jmpcopy_reversing_loop

end_copy_reversing_loop:
#Donecopying.Nowwriteanullbyteandreturn
movb$0,(%edx)

movl%ebp,%esp
popl%ebp
ret

Toshowthisusedinafullprogram,usethefollowingcode,along
withthecount_charsandwrite_newlinefunctionswrittenaboutin
previouschapters.Thecodeshouldbeinafilecalled
conversionprogram.s.
.include"linux.s"

.section.data

#Thisiswhereitwillbestored
tmp_buffer:
.ascii"\0\0\0\0\0\0\0\0\0\0\0"
.section.text

.globl_start
_start:
movl%esp,%ebp

#Storagefortheresult
pushl$tmp_buffer
#Numbertoconvert
pushl$824
callinteger2string
addl$8,%esp

#Getthecharactercountforoursystemcall
pushl$tmp_buffer

callcount_chars
addl$4,%esp

#Thecountgoesin%edxforSYS_WRITE
movl%eax,%edx

#Makethesystemcall
movl$SYS_WRITE,%eax
movl$STDOUT,%ebx
movl$tmp_buffer,%ecx

int$LINUX_SYSCALL

#Writeacarriagereturn
pushl$STDOUT
callwrite_newline

#Exit
movl$SYS_EXIT,%eax
movl$0,%ebx
int$LINUX_SYSCALL

Tobuildtheprogram,issuethefollowingcommands:
asintegertostring.sointegertonumber.o
ascountchars.socountchars.o
aswritenewline.sowritenewline.o
asconversionprogram.soconversionprogram.o
ldintegertonumber.ocountchars.owritenewline.oconversion
program.ooconversionprogram

Torunjusttype./conversionprogramandtheoutputshouldsay824.

Review
KnowtheConcepts
Convertthedecimalnumber5,294tobinary.
Whatnumberdoes0x0234aeffrepresent?Specifyinbinary,octal,and
decimal.
Addthebinarynumbers10111001and101011.
Multiplythebinarynumbers11001010110.
Converttheresultsoftheprevioustwoproblemsintodecimal.
DescribehowAND,OR,NOT,andXORwork.
Whatismaskingfor?

Whatnumberwouldyouusefortheflagsoftheopensystemcallif
youwantedtoopenthefileforwriting,andcreatethefileifit
doesn'texist?
Howwouldyourepresent55inathirtytwobitregister?
Signextendthepreviousquantityintoa64bitregister.
Describethedifferencebetweenlittleendianandbigendianstorage
ofwordsinmemory.
UsetheConcepts
Gobacktopreviousprogramsthatreturnednumericresultsthrough
theexitstatuscode,andrewritethemtoprintouttheresults
insteadusingourintegertostringconversionfunction.
Modifytheinteger2stringcodetoreturnresultsinoctalratherthan
decimal.
Modifytheinteger2stringcodesothattheconversionbaseisa
parameterratherthanhardcoded.
Writeafunctioncalledis_negativethattakesasingleintegerasa
parameterandreturns1iftheparameterisnegative,and0ifthe
parameterispositive.
GoingFurther
Modifytheinteger2stringcodesothattheconversionbasecanbe
greaterthan10(thisrequiresyoutouselettersfornumberspast
9).
Createafunctionthatdoesthereverseofinteger2stringcalled
number2integerwhichtakesacharacterstringandconvertsittoa
registersizedinteger.Testitbyrunningthatintegerbackthrough
theinteger2stringfunctionanddisplayingtheresults.
Writeaprogramthatstoreslikesanddislikesintoasinglemachine
word,andthencomparestwosetsoflikesanddislikesfor
commonalities.
WriteaprogramthatreadsastringofcharactersfromSTDINand
convertsthemtoanumber.

Chapter11:HighLevelLanguages
Overview
Inthischapterwewillbegintolookatourfirst"realworld"
programminglanguage.Assemblylanguageisthelanguageusedatthe
machine'slevel,butmostpeoplefindcodinginassemblylanguagetoo
cumbersomeforeverydayuse.Manycomputerlanguageshavebeen
inventedtomaketheprogrammingtaskeasier.Knowingawidevariety
oflanguagesisusefulformanyreasons,including

Differentlanguagesarebasedondifferentconcepts,whichwillhelp
youtolearndifferentandbetterprogrammingmethodsandideas.
Differentlanguagesaregoodfordifferenttypesofprojects.
Differentcompanieshavedifferentstandardlanguages,soknowing
morelanguagesmakesyourskillsmoremarketable.
Themorelanguagesyouknow,theeasieritistopickupnewones.
Asaprogrammer,youwilloftenhavetopickupnewlanguages.
Professionalprogrammerscanusuallypickupanewlanguagewith
aboutaweeksworthofstudyandpractice.Languagesaresimply
tools,andlearningtouseanewtoolshouldnotbesomethinga
programmerflinchesat.Infact,ifyoudocomputerconsultingyou
willoftenhavetolearnnewlanguagesonthespotinordertokeep
yourselfemployed.Itwilloftenbeyourcustomer,notyou,who
decideswhatlanguageisused.Thischapterwillintroduceyoutoa
fewofthelanguagesavailabletoyou.Iencourageyoutoexploreas
manylanguagesasyouareinterestedin.Ipersonallytrytolearna
newlanguageeveryfewmonths.

CompiledandInterpretedLanguages
Manylanguagesare
compiled
languages.Whenyouwriteassembly
language,eachinstructionyouwriteistranslatedintoexactlyone
machineinstructionforprocessing.Withcompilers,astatementcan
translateintooneorhundredsofmachineinstructions.Infact,
dependingonhowadvancedyourcompileris,itmightevenrestructure
partsofyourcodetomakeitfaster.Inassemblylanguagewhatyou
writeiswhatyouget.
Therearealsolanguagesthatare
interpreted
languages.These
languagesrequirethattheuserrunaprogramcalledan
interpreter
thatinturnrunsthegivenprogram.Theseareusuallyslowerthan
compiledprograms,sincetheinterpreterhastoreadandinterpret
thecodeasitgoesalong.However,inwellmadeinterpreters,this
timecanbefairlynegligible.Thereisalsoaclassofhybrid
languageswhichpartiallycompileaprogrambeforeexecutioninto
bytecodes.Thisisdonebecausetheinterpretercanreadthe
bytecodesmuchfasterthanitcanreadtheregularlanguage.
Therearemanyreasonstochooseoneortheother.Compiledprograms
arenice,becauseyoudon'thavetoalreadyhaveaninterpreter
installedintheuser'smachine.Youhavetohaveacompilerforthe
language,buttheusersofyourprogramdon't.Inaninterpreted
language,youhavetobesurethattheuserhasaninterpreter
installedforyourprogram,andthatthecomputerknowswhich

interpretertorunyourprogramwith.However,interpetedlanguages
tendtobemoreflexible,whilecompiledlanguagesaremorerigid.
Languagechoiceisusuallydrivenbyavailabletoolsandsupportfor
programmingmethodsratherthanbywhetheralanguageiscompiledor
interpretted.Infactmanylanguageshaveoptionsforeitherone.
Highlevellanguages,whethercompiledorinterpreted,areoriented
aroundyou,theprogrammer,insteadofaroundthemachine.Thisopens
themuptoawidevarietyoffeatures,whichcanincludethe
following:
Beingabletogroupmultipleoperationsintoasingleexpression
Beingabletouse"bigvalues"valuesthataremuchmoreconceptual
thanthe4bytewordsthatcomputersnormallydealwith(forexample,
beingabletoviewtextstringsasasinglevalueratherthanasa
stringofbytes).
Havingaccesstobetterflowcontrolconstructsthanjustjumps.
Havingacompilertochecktypesofvalueassignmentsandother
assertions.
Havingmemoryhandledautomatically.
Beingabletoworkinalanguagethatresemblestheproblemdomain
ratherthanthecomputerhardware.
Sowhydoesonechooseonelanguageoveranother?Forexample,many
choosePerlbecauseithasavastlibraryoffunctionsforhandling
justabouteveryprotocolortypeofdataontheplanet.Python,
however,hasacleanersyntaxandoftenlendsitselftomore
straightforwardsolutions.ItscrossplatformGUItoolsarealso
excellent.PHPmakeswritingwebapplicationssimple.CommonLISPhas
morepowerandfeaturesthananyotherenvironmentforthosewilling
tolearnit.Schemeisthemodelofsimplicityandpowercombined
together.Ciseasytointerfacewithotherlanguages.
Eachlanguageisdifferent,andthemorelanguagesyouknowthe
betterprogrammeryouwillbe.Knowingtheconceptsofdifferent
languageswillhelpyouinallprogramming,becauseyoucanmatchthe
programminglanguagetotheproblembetter,andyouhavealargerset
oftoolstoworkwith.Evenifcertainfeaturesaren'tdirectly
supportedinthelanguageyouareusing,oftentheycanbesimulated.
However,ifyoudon'thaveabroadexperiencewithlanguages,you
won'tknowofallthepossibilitiesyouhavetochoosefrom.

YourFirstCProgram
HereisyourfirstCprogram,whichprints"Helloworld"tothe
screenandexits.Typeitin,andgiveitthenameHelloWorld.c
#include<stdio.h>

/*PURPOSE:Thisprogramismeantoshowabasic*/
/*Cprogram.Allitdoesisprint*/
/*"HelloWorld!"tothescreenand*/
/*exit.*/

/*MainProgram*/
intmain(intargc,char**argv)
{
/*Printourstringtostandardoutput*/
puts("HelloWorld!\n")

/*Exitwithstatus0*/
return0
}

Asyoucansee,it'saprettysimpleprogram.Tocompileit,runthe
command
gccoHelloWorldHelloWorld.c

Toruntheprogram,do
./HelloWorld

Let'slookathowthisprogramwasputtogether.
CommentsinCarestartedwith/*andendedwith*/.Commentscan
spanmultiplelines,butmanypeopleprefertostartandendcomments
onthesamelinesotheydon'tgetconfused.
#include<stdio.h>isthefirstpartoftheprogram.Thisisa
preprocessordirective.
Ccompilingissplitintotwostagesthe
preprocessorandthemaincompiler.Thisdirectivetellsthe
preprocessortolookforthefilestdio.handpasteitintoyour
program.Thepreprocessorisresponsibleforputtingtogetherthe
textoftheprogram.Thisincludesstickingdifferentfilestogether,
runningmacrosonyourprogramtext,etc.Afterthetextisput
together,thepreprocessorisdoneandthemaincompilergoesto
work.
Now,everythinginstdio.hisnowinyourprogramjustasifyou
typeditthereyourself.Theanglebracketsaroundthefilenametell

thecompilertolookinitsstandardpathsforthefile(/usr/include
and/usr/local/include,usually).Ifitwasinquotes,like#include
"stdio.h"itwouldlookinthecurrentdirectoryforthefile.
Anyway,stdio.hcontainsthedeclarationsforthestandardinputand
outputfunctionsandvariables.Thesedeclarationstellthecompiler
whatfunctionsareavailableforinputandoutput.Thenextfewlines
aresimplycommentsabouttheprogram.
Thenthereisthelineintmain(intargc,char**argv).Thisisthe
startofafunction.CFunctionsaredeclaredwiththeirname,
argumentsandreturntype.Thisdeclarationsaysthatthefunction's
nameismain,itreturnsanint(integer4byteslongonthex86
platform),andhastwoargumentsanintcalledargcandachar**
calledargv.Youdon'thavetoworryaboutwheretheargumentsare
positionedonthestacktheCcompilertakescareofthatforyou.
Youalsodon'thavetoworryaboutloadingvaluesintoandoutof
registersbecausethecompilertakescareofthat,too.
ThemainfunctionisaspecialfunctionintheClanguageitisthe
startofallCprograms(muchlike_startinourassemblylanguage
programs).Italwaystakestwoparameters.Thefirstparameteristhe
numberofargumentsgiventothiscommand,andthesecondparameter
isalistoftheargumentsthatweregiven.
Thenextlineisafunctioncall.Inassemblylanguage,youhadto
pushtheargumentsofafunctionontothestack,andthencallthe
function.Ctakescareofthiscomplexityforyou.Yousimplyhaveto
callthefunctionwiththeparametersinparenthesis.Inthiscase,
wecallthefunctionputs,withasingleparameter.Thisparameteris
thecharacterstringwewanttoprint.Wejusthavetotypeinthe
stringinquotations,andthecompilertakescareofdefiningstorage
andmovingthepointerstothatstorageontothestackbeforecalling
thefunction.Asyoucansee,it'salotlesswork.
Finallyourfunctionreturnsthenumber0.Inassemblylanguage,we
storedourreturnvaluein%eax,butinCwejustusethereturn
commandandittakescareofthatforus.Thereturnvalueofthe
mainfunctioniswhatisusedastheexitcodefortheprogram.
As you can see, using high-level languages makes life much easier. It also allows our
programs to run on multiple platforms more easily. In assembly language, your program
is tied to both the operating system and the hardware platform, while in compiled and
interpreted languages the same code can usually run on multiple operating systems and
hardware platforms. For example, this program can be built and executed on x86
hardware running Linux, Windows, UNIX, or most other operating systems. In
addition, it can also run on Macintosh hardware running a number of operating systems.
AdditionalinformationontheCprogramminglanguagecanbefoundin
AppendixE.

Perl
Perlisaninterpretedlanguage,existingmostlyonLinuxand
UNIXbasedplatforms.Itactuallyrunsonalmostallplatforms,but
youfinditmostoftenonLinuxandUNIXbasedones.Anyway,hereis
thePerlversionoftheprogram,whichshouldbetypedintoafile
namedHelloWorld.pl:
#!/usr/bin/perl

print("Helloworld!\n")

SincePerlisinterpreted,youdon'tneedtocompileorlinkit.Just
runinwiththefollowingcommand:
perlHelloWorld.pl

Asyoucansee,thePerlversionisevenshorterthantheCversion.
WithPerlyoudon'thavetodeclareanyfunctionsorprogramentry
points.Youcanjuststarttypingcommandsandtheinterpreterwill
runthemasitcomestothem.Infactthisprogramonlyhastwolines
ofcode,oneofwhichisoptional.
Thefirst,optionallineisusedforUNIXmachinestotellwhich
interpretertousetoruntheprogram.The#!tellsthecomputerthat
thisisaninterpretedprogram,andthe/usr/bin/perltellsthe
computertousetheprogram/usr/bin/perltointerprettheprogram.
However,sincewerantheprogrambytypinginperlHelloWorld.pl,
wehadalreadyspecifiedthatwewereusingtheperlinterpreter.
ThenextlinecallsaPerlbuiltinfunction,print.Thishasone
parameter,thestringtoprint.Theprogramdoesn'thaveanexplicit
returnstatementitknowstoreturnsimplybecauseitrunsoffthe
endofthefile.Italsoknowstoreturn0becausetherewereno
errorswhileitran.Youcanseethatinterpretedlanguagesareoften
focusedonlettingyougetworkingcodeasquicklyaspossible,
withouthavingtodoalotofextralegwork.
OnethingaboutPerlthatisn'tsoevidentfromthisexampleisthat
Perltreatsstringsasasinglevalue.Inassemblylanguage,wehad
toprogramaccordingtothecomputer'smemoryarchitecture,which
meantthatstringshadtobetreatedasasequenceofmultiple
values,withapointertothefirstletter.Perlpretendsthat
stringscanbestoreddirectlyasvalues,andthushidesthe
complicationofmanipulatingthemforyou.Infact,oneofPerl's
mainstrengthsisitsabilityandspeedatmanipulatingtext.

Python
ThePythonversionoftheprogramlooksalmostexactlylikethePerl
one.However,PythonisreallyaverydifferentlanguagethanPerl,
evenifitdoesn'tseemsofromthistrivialexample.Typethe
programintoafilenamedHelloWorld.py.Theprogramfollows:
#!/usr/bin/python
print"HelloWorld"

Youshouldbeabletotellwhatthedifferentlinesoftheprogram
do.

Review
KnowtheConcepts
Whatisthedifferencebetweenaninteprettedlanguageandacompiled
language?
Whatreasonsmightcauseyoutoneedtolearnanewprogramming
language?
UsetheConcepts
Learnthebasicsyntaxofanewprogramminglanguage.Recodeoneof
theprogramsinthisbookinthatlanguage.
Intheprogramyouwroteinthequestionabove,whatspecificthings
wereautomatedintheprogramminglanguageyouchose?
Modifyyourprogramsothatitruns10,000timesinarow,bothin
assemblylanguageandinyournewlanguage.Thenrunthetimecommand
toseewhichisfaster.Whichdoescomeoutahead?Whydoyouthink
thatis?
Howdoestheprogramminglanguage'sinput/outputmethodsdifferfrom
thatoftheLinuxsystemcalls?
GoingFurther
HavingseenlanguageswhichhavesuchbrevityasPerl,whydoyou
thinkthisbookstartedyouwithalanguageasverboseasassembly
language?
Howdoyouthinkhighlevellanguageshaveaffectedtheprocessof
programming?
Whydoyouthinksomanylanguagesexist?
Learntwonewhighlevellanguages.Howdotheydifferfromeach
other?Howaretheysimilar?Whatapproachtoproblemsolvingdoes
eachtake?

Chapter12:Optimization
Optimizationistheprocessofmakingyourapplicationrunmore
effectively.Youcanoptimizeformanythingsspeed,memoryspace
usage,diskspaceusage,etc.Thischapter,however,focusesonspeed
optimization.

WhentoOptimize
Itisbettertonotoptimizeatallthantooptimizetoosoon.When
youoptimize,yourcodegenerallybecomeslessclear,becauseit
becomesmorecomplex.Readersofyourcodewillhavemoretrouble
discoveringwhyyoudidwhatyoudidwhichwillincreasethecostof
maintenanceofyourproject.Evenwhenyouknowhowandwhyyour
programrunsthewayitdoes,optimizedcodeishardertodebugand
extend.Itslowsthedevelopmentprocessdownconsiderably,both
becauseofthetimeittakestooptimizethecode,andthetimeit
takestomodifyyouroptimizedcode.
Compoundingthisproblemisthatyoudon'tevenknowbeforehandwhere
thespeedissuesinyourprogramwillbe.Evenexperienced
programmershavetroublepredictingwhichpartsoftheprogramwill
bethebottleneckswhichneedoptimization,soyouwillprobablyend
upwastingyourtimeoptimizingthewrongparts.theSectioncalled
WheretoOptimize
willdiscusshowtofindthepartsofyourprogram
thatneedoptimization.
Whileyoudevelopyourprogram,youneedtohavethefollowing
priorities:
Everythingisdocumented
Everythingworksasdocumented
Thecodeiswritteninanmodular,easilymodifiableform
Documentationisessential,especiallywhenworkingingroups.The
properfunctioningoftheprogramisessential.You'llnotice
applicationspeedwasnotanywhereonthatlist.Optimizationisnot
necessaryduringearlydevelopmentforthefollowingreasons:
Minorspeedproblemscanbeusuallysolvedthroughhardware,
whichisoftenmuchcheaperthanaprogrammer'stime.
Yourapplicationwillchangedramaticallyasyoureviseit,
1]
thereforewastingmostofyoureffortstooptimizeit.[

Speedproblemsareusuallylocalizedinafewplacesinyour
codefindingtheseisdifficultbeforeyouhavemostofthe
programfinished.

Therefore,thetimetooptimizeistowardtheendofdevelopment,
whenyouhavedeterminedthatyourcorrectcodeactuallyhas
performanceproblems.
InawebbasedecommerceprojectIwasinvolvedin,Ifocused
entirelyoncorrectness.Thiswasmuchtothedismayofmy
colleagues,whowereworriedaboutthefactthateachpagetook
twelvesecondstoprocessbeforeiteverstartedloading(mostweb
pagesprocessinunderasecond).However,Iwasdeterminedtomake
ittherightwayfirst,andputoptimizationasalastpriority.When
thecodewasfinallycorrectafter3monthsofwork,ittookonly
threedaystofindandeliminatethebottlenecks,bringingthe
averageprocessingtimeunderaquarterofasecond.Byfocusingon
thecorrectorder,Iwasabletofinishaprojectthatwasboth
correctandefficient.
[1]
Manynewprojectsoftenhaveafirstcodebasewhichiscompletely
rewrittenasdeveloperslearnmoreabouttheproblemtheyaretrying
tosolve.Anyoptimizationdoneonthefirstcodebaseiscompletely
wasted.

WheretoOptimize
Onceyouhavedeterminedthatyouhaveaperformanceissueyouneed
todeterminewhereinthecodetheproblemsoccur.Youcandothisby
runninga
profiler.
Aprofilerisaprogramthatwillletyourun
yourprogram,anditwilltellyouhowmuchtimeisspentineach
function,andhowmanytimestheyarerun.gprofisthestandard
GNU/Linuxprofilingtool,butadiscussionofusingprofilersis
outsidethescopeofthistext.Afterrunningaprofiler,youcan
determinewhichfunctionsarecalledthemostorhavethemosttime
spentinthem.Thesearetheonesyoushouldfocusyouroptimization
effortson.
Ifaprogramonlyspends1%ofitstimeinagivenfunction,thenno
matterhowmuchyouspeeditupyouwillonlyachievea
maximum
ofa
1%overallspeedimprovement.However,ifaprogramspends20%ofits
timeinagivenfunction,thenevenminorimprovementstothat
functionsspeedwillbenoticeable.Therefore,profilinggivesyou
theinformationyouneedtomakegoodchoicesaboutwheretospend
yourprogrammingtime.
Inordertooptimizefunctions,youneedtounderstandinwhatways
theyarebeingcalledandused.Themoreyouknowabouthowandwhen

afunctioniscalled,thebetterpositionyouwillbeintooptimize
itappropriately.
Therearetwomaincategoriesofoptimizationlocaloptimizations
andglobaloptimizations.Localoptimizationsconsistof
optimizationsthatareeitherhardwarespecificsuchasthefastest
waytoperformagivencomputationorprogramspecificsuchas
makingaspecificpieceofcodeperformthebestforthemost
oftenoccuringcase.Globaloptimizationconsistofoptimizations
whicharestructural.Forexample,ifyouweretryingtofindthe
bestwayforthreepeopleindifferentcitiestomeetinSt.Louis,a
localoptimizationwouldbefindingabetterroadtogetthere,while
aglobaloptimizationwouldbetodecidetoteleconferenceinsteadof
meetinginperson.Globaloptimizationofteninvolvesrestructuring
codetoavoidperformanceproblems,ratherthantryingtofindthe
bestwaythroughthem.

LocalOptimizations
Thefollowingaresomewellknownmethodsofoptimizingpiecesof
code.Whenusinghighlevellanguages,someofthesemaybedone
automaticallybyyourcompiler'soptimizer.
PrecomputingCalculations
Sometimesafunctionhasalimittednumberofpossibleinputs
andoutputs.Infact,itmaybesofewthatyoucanactually
precomputeallofthepossibleanswersbeforehand,andsimply
lookuptheanswerwhenthefunctioniscalled.Thistakesup
somespacesinceyouhavetostorealloftheanswers,butfor
smallsetsofdatathisworksoutreallywell,especiallyif
thecomputationnormallytakesalongtime.
RememberingCalculationResults
Thisissimilartothepreviousmethod,butinsteadof
computingresultsbeforehand,theresultofeachcalculation
requestedisstored.Thiswaywhenthefunctionstarts,ifthe
resulthasbeencomputedbeforeitwillsimplyreturnthe
previousanswer,otherwiseitwilldothefullcomputationand
storetheresultforlaterlookup.Thishastheadvantageof
requiringlessstoragespacebecauseyouaren'tprecomputing
allresults.Thisissometimestermed
caching
or
memoizing.
LocalityofReference
Localityofreference
isatermforwhereinmemorythedata
itemsyouareaccessingare.Withvirtualmemory,youmay
accesspagesofmemorywhicharestoredondisk.Insucha
case,theoperatingsystemhastoloadthatmemorypagefrom

disk,andunloadotherstodisk.Let'ssay,forinstance,that
theoperatingsystemwillallowyoutohave20kofmemoryin
physicalmemoryandforcestherestofittobeondisk,and
yourapplicationuses60kofmemory.Let'ssayyourprogramhas
todo5operationsoneachpieceofdata.Ifitdoesone
operationoneverypieceofdata,andthengoesthroughand
doesthenextoperationoneachpieceofdata,eventuallyevery
pageofdatawillbeloadedandunloadedfromthedisk5times.
Instead,ifyoudidall5operationsonagivendataitem,you
onlyhavetoloadeachpagefromdiskonce.Whenyoubundleas
manyoperationsondatathatisphysicallyclosetoeachother
inmemory,thenyouaretakingadvantageoflocalityof
reference.Inaddition,processorsusuallystoresomedata
onchipinacache.Ifyoukeepallofyouroperationswithina
smallareaofphysicalmemory,yourprogrammaybypasseven
mainmemoryandonlyusethechip'sultrafastcachememory.
Thisisalldoneforyouallyouhavetodoistotryto
operateonsmallsectionsofmemoryatatime,ratherthan
bouncingallovertheplace.
RegisterUsage
Registersarethefastestmemorylocationsonthecomputer.
Whenyouaccessmemory,theprocessorhastowaitwhileitis
loadedfromthememorybus.However,registersarelocatedon
theprocessoritself,soaccessisextremelyfast.Therefore
makingwiseusageofregistersisextremelyimportant.Ifyou
havefewenoughdataitemsyouareworkingwith,trytostore
themallinregisters.Inhighlevellanguages,youdonot
alwayshavethisoptionthecompilerdecideswhatgoesin
registersandwhatdoesn't.
InlineFunctions
Functionsaregreatfromthepointofviewofprogram
managementtheymakeiteasytobreakupyourprograminto
independent,understandable,andreuseableparts.However,
functioncallsdoinvolvetheoverheadofpushingarguments
ontothestackanddoingthejumps(rememberlocalityof
referenceyourcodemaybeswappedoutondiskinsteadofin
memory).Forhighlevellanguages,it'softenimpossiblefor
compilerstodooptimizationsacrossfunctioncallboundaries.
However,somelanguagessupportinlinefunctionsorfunction
macros.Thesefunctionslook,smell,taste,andactlikereal
functions,exceptthecompilerhastheoptiontosimplyplug
thecodeinexactlywhereitwascalled.Thismakestheprogram
faster,butitalsoincreasesthesizeofthecode.Thereare

alsomanyfunctions,likerecursivefunctions,whichcannotbe
inlinedbecausetheycallthemselveseitherdirectlyor
indirectly.
OptimizedInstructions
Oftentimestherearemultipleassemblylanguageinstructions
whichaccomplishthesamepurpose.Askilledassemblylanguage
programmerknowswhichinstructionsarethefastest.However,
thiscanchangefromprocessortoprocessor.Formore
informationonthistopic,youneedtoseetheuser'smanual
thatisprovidedforthespecificchipyouareusing.Asan
example,let'slookattheprocessofloadingthenumber0into
aregister.Onmostprocessors,doingamovl$0,%eaxisnot
thequickestway.Thequickestwayistoexclusiveorthe
registerwithitself,xorl%eax,%eax.Thisisbecauseitonly
hastoaccesstheregister,anddoesn'thavetotransferany
data.Forusersofhighlevellanguages,thecompilerhandles
thiskindofoptimizationsforyou.Forassemblylanguage
programmers,youneedtoknowyourprocessorwell.
AddressingModes
Differentaddressingmodesworkatdifferentspeeds.The
fastestaretheimmediateandregisteraddressingmodes.Direct
isthenextfastest,indirectisnext,andbasepointerand
indexedindirectaretheslowest.Trytousethefaster
addressingmodes,whenpossible.Oneinterestingconsequenceof
thisisthatwhenyouhaveastructuredpieceofmemorythat
youareaccessingusingbasepointeraddressing,thefirst
elementcanbeaccessedthequickest.Sinceitsoffsetis0,
youcanaccessitusingindirectaddressinginsteadofbase
pointeraddressing,whichmakesitfaster.
DataAlignment
Someprocessorscanaccessdataonwordalignedmemory
boundaries(i.e.addressesdivisiblebythewordsize)faster
thannonaligneddata.So,whensettingupstructuresin
memory,itisbesttokeepitwordaligned.Somenonx86
processors,infact,cannotaccessnonaligneddatainsome
modes.
Thesearejustasmatteringofexamplesofthekindsoflocal
optimizationspossible.However,rememberthatthemaintainability
andreadabilityofcodeismuchmoreimportantexceptunderextreme
circumstances.

GlobalOptimization
Globaloptimizationhastwogoals.Thefirstoneistoputyourcode
inaformwhereitiseasytodolocaloptimiztions.Forexample,if
youhavealargeprocedurethatperformsseveralslow,complex
calculations,youmightseeifyoucanbreakpartsofthatprocedure
intotheirownfunctionswherethevaluescanbeprecomputedor
memoized.
Statelessfunctions(functionsthatonlyoperateontheparameters
thatwerepassedtothemi.e.noglobalsorsystemcalls)arethe
easiesttypeoffunctionstooptimizeinacomputer.Themore
statelesspartsofyourprogramyouhave,themoreopportunitiesyou
havetooptimize.IntheecommercesituationIwroteaboutabove,
thecomputerhadtofindalloftheassociatedpartsforspecific
inventoryitems.Thisrequiredabout12databasecalls,andinthe
worstcasetookabout20seconds.However,thegoalofthisprogram
wastobeinteractive,andalongwaitwoulddestroythatgoal.
However,Iknewthattheseinventoryconfigurationsdonotchange.
Therefore,Iconvertedthedatabasecallsintotheirownfunctions,
whichwerestateless.Iwasthenabletomemoizethefunctions.At
thebeginningofeachday,thefunctionresultswereclearedincase
anyonehadchangedthem,andseveralinventoryitemswere
automaticallypreloaded.Fromthenonduringtheday,thefirsttime
someoneaccessedaninventoryitem,itwouldtakethe20secondsit
didbeforehand,butafterwardsitwouldtakelessthanasecond,
becausethedatabaseresultshadbeenmemoized.
Globaloptimizationusuallyofteninvolvesachievingthefollowing
propertiesinyourfunctions:
Parallelization
Parallelizationmeansthatyouralgorithmcaneffectivelybesplit
amongmultipleprocesses.Forexample,pregnancyisnotvery
parallelizablebecausenomatterhowmanywomenyouhave,itstill
takesninemonths.However,buildingacarisparallelizablebecause
youcanhaveoneworkerworkingontheenginewhileanotheroneis
workingontheinterior.Usually,applicationshavealimittohow
parallelizabletheyare.Themoreparallelizableyourapplicationis,
thebetteritcantakeadvantageofmultiprocessorandclustered
computerconfigurations.
Statelessness
Aswe'vediscussed,statelessfunctionsandprogramsarethosethat
relyentirelyonthedataexplicitlypassedtothemforfunctioning.
Mostprocessesarenotentirelystateless,buttheycanbewithin

limits.Inmyecommerceexample,thefunctionwasn'tentirely
stateless,butitwaswithintheconfinesofasingleday.Therefore,
Ioptimizeditasifitwereastatelessfunction,butmade
allowancesforchangesatnight.Twogreatbenefitsresultingfrom
statelessnessisthatmoststatelessfunctionsareparallelizableand
oftenbenefitfrommemoization.
Globaloptimizationtakesquiteabitofpracticetoknowwhatworks
andwhatdoesn't.Decidinghowtotackleoptimizationproblemsin
codeinvolveslookingatalltheissues,andknowingthatfixingsome
issuesmaycauseothers.

Review
KnowtheConcepts
Atwhatlevelofimportanceisoptimizationcomparedtotheother
prioritiesinprogramming?
Whatisthedifferencebetweenlocalandglobaloptimizations?
Namesometypesoflocaloptimizations.
Howdoyoudeterminewhatpartsofyourprogramneedoptimization?
Atwhatlevelofimportanceisoptimizationcomparedtotheother
prioritiesinprogramming?WhydoyouthinkIrepeatedthatquestion?
UsetheConcepts
Gobackthrougheachprograminthisbookandtrytomake
optimizationsaccordingtotheproceduresoutlinedinthischapter
Pickaprogramfromthepreviousexerciseandtrytocalculatethe
2]
performanceimpactonyourcodeunderspecificinputs.[

GoingFurther
Findanopensourceprogramthatyoufindparticularlyfast.Contact
oneofthedevelopersandaskaboutwhatkindsofoptimizationsthey
performedtoimprovethespeed.
Findanopensourceprogramthatyoufindparticularlyslow,andtry
toimaginethereasonsfortheslowness.Then,downloadthecodeand
trytoprofileitusinggproforsimilartool.Findwherethecodeis
spendingthemajorityofthetimeandtrytooptimizeit.Wasthe
reasonfortheslownessdifferentthanyouimagined?
Hasthecompilereliminatedtheneedforlocaloptimizations?Whyor
whynot?
Whatkindofproblemsmightacompilerrunintoifittriedto
optimizecodeacrossfunctioncallboundaries?
[2]
Sincetheseprogramsareusuallyshortenoughnottohave
noticeableperformanceproblems,loopingthroughtheprogram

thousandsoftimeswillexaggeratethetimeittakestorunenoughto
makecalculations.

Chapter13:

MovingonFromHere
Overview
Congratulationsongettingthisfar.Youshouldnowhaveabasisfor
understandingtheissuesinvolvedinmanyareasofprogramming.Even
ifyouneveruseassemblylanguageagain,youhavegainedavaluable
perspectiveandmentalframeworkforunderstandingtherestof
computerscience.
Thereareessentiallythreemethodstolearntoprogram:
FromtheBottomUpThisishowthisbookteaches.Itstartswith
lowlevelprogramming,andworkstowardmoregeneralizedteaching.
FromtheTopDownThisistheoppositedirection.Thisfocuseson
whatyouwanttodowiththecomputer,andteachesyouhowtobreak
itdownmoreandmoreuntilyougettothelowlevels.
FromtheMiddleThisischaracterizedbybookswhichteacha
specificprogramminglanguageorAPI.Thesearenotasconcernedwith
conceptsastheyarewithspecifics.
Differentpeoplelikedifferentapproaches,butagoodprogrammer
takesallofthemintoaccount.Thebottomupapproacheshelpyou
understandthemachineaspects,thetopdownapproacheshelpyou
understandtheproblemareaaspects,andthemiddleapproacheshelp
youwithpracticalquestionsandanswers.Toleaveanyofthese
aspectsoutwouldbeamistake.
ComputerProgrammingisavastsubject.Asaprogrammer,youwill
needtobepreparedtobeconstantlylearningandpushingyour
limits.Thesebookswillhelpyoudothat.Theynotonlyteachtheir
subjects,butalsoteachvariouswaysandmethodsof
thinking.
As
AlanPerlissaid,"Alanguagethatdoesn'taffectthewayyouthink
aboutprogrammingisnotworthknowing"
(http://www.cs.yale.edu/homes/perlisalan/quotes.html).Ifyouare
constantlylookingfornewandbetterwaysofdoingandthinking,you

willmakeasuccessfulprogrammer.Ifyoudonotseektoenhance
yourself,"Alittlesleep,alittleslumber,alittlefoldingofthe
handstorestandpovertywillcomeonyoulikeabanditand
scarcitylikeanarmedman."(Proverbs24:3334NIV).Perhapsnot
quitethatsevere,butstill,itisbesttoalwaysbelearning.
Thesebookswereselectedbecauseoftheircontentandtheamountof
respecttheyhaveinthecomputerscienceworld.Eachofthembrings
somethingunique.Therearemanybookshere.Thebestwaytostart
wouldbetolookthroughonlinereviewsofseveralofthebooks,and
findastartingpointthatinterestsyou.

FromtheBottomUp
ThislistisinthebestreadingorderIcouldfind.It'snot
necessarilyeasiesttohardest,butbasedonsubjectmatter.
ProgrammingfromtheGroundUp
byJonathanBartlett

IntroductiontoAlgorithms
byThomasH.Cormen,CharlesE.Leiserson,
andRonaldL.Rivest

TheArtofComputerProgramming
byDonaldKnuth(3volumesetvolume
1isthemostimportant)
ProgrammingLanguages
bySamuelN.Kamin
ModernOperatingSystems
byAndrewTanenbaum
LinkersandLoaders
byJohnLevine
ComputerOrganizationandDesign:TheHardware/SoftwareInterface
by
DavidPattersonandJohnHennessy

FromtheTopDown
Thesebooksarearrangedfromthesimplesttothehardest.However,
theycanbereadinanyorderyoufeelcomfortablewith.
HowtoDesignPrograms
byMatthiasFelleisen,RobertBruceFindler,
MatthewFlatt,andShiramKrishnamurthi,availableonlineat
http://www.htdp.org/
SimplyScheme:AnIntroductiontoComputerScience
byBrianHarveyand
MatthewWright
HowtoThinkLikeaComputerScientist:LearningwithPython
byAllen
Downey,JeffElkner,andChrisMeyers,availableonlineat
http://www.greenteapress.com/thinkpython/

StructureandInterpretationofComputerPrograms
byHaroldAbelson
andGeraldJaySussmanwithJulieSussman,availableonlineat
http://mitpress.mit.edu/sicp/

FromtheMiddleOut
Eachoftheseisthebestbookonitssubject.Ifyouneedtoknow
theselanguages,thesewilltellyouallyouneedtoknow.
ProgrammingPerl
byLarryWall,TomChristiansen,andJonOrwant
CommonLISP:TheLanguage
byGuyR.Steele
ANSICommonLISP
byPaulGraham
TheCProgrammingLanguage
byBrianW.KernighanandDennisM.
Ritchie
TheWaiteGroup'sCPrimerPlus
byStephenPrata

TheC++ProgrammingLanguage
byBjarneStroustrup
ThinkinginJava
byBruceEckel,availableonlineat
http://www.mindview.net/Books/TIJ/
TheSchemeProgrammingLanguage
byKentDybvig

LinuxAssemblyLanguageProgramming
byBobNeveln

DesignPatterns
byErichGamma,RichardHelm,RalphJohnson,andJohn
Vlissides
WhatnotHow:TheRulesApproachtoApplicationDevelopment
byChris
Date
TheAlgorithmDesignManual
bySteveSkiena
ProgrammingLanguagePragmatics
byMichaelScott
EssentialsofProgrammingLanguages
byDanielP.Friedman,Mitchell
Wand,andChristopherT.Haynes

TheGNOMELibraries

TheGNOMEprojectsisoneofseveralprojectstoprovideacomplete
desktoptoLinuxusers.TheGNOMEprojectincludesapaneltohold
applicationlaunchersandminiapplicationscalledapplets,several
standardapplicationstodothingssuchasfilemanagement,session
management,andconfiguration,andanAPIforcreatingapplications
whichfitinwiththewaytherestofthesystemworks.
OnethingtonoticeabouttheGNOMElibrariesisthattheyconstantly
createandgiveyoupointerstolargedatastructures,butyounever
needtoknowhowtheyarelaidoutinmemory.Allmanipulationofthe
GUIdatastructuresaredoneentirelythroughfunctioncalls.Thisis
acharacteristicofgoodlibrarydesign.Librarieschangefrom
versiontoversion,andsodoesthedatathateachdatastructure
holds.Ifyouhadtoaccessandmanipulatethatdatayourself,then
whenthelibraryisupdatedyouwouldhavetomodifyyourprogramsto
workwiththenewlibrary,oratleastrecompilethem.Whenyou
accessthedatathroughfunctions,thefunctionstakecareofknowing
whereinthestructureeachpieceofdatais.Thepointersyou
receivefromthelibraryare
opaque
youdon'tneedtoknow
specificallywhatthestructuretheyarepointingtolookslike,you
onlyneedtoknowthefunctionsthatwillproperlymanipulateit.
Whendesigninglibraries,evenforusewithinonlyoneprogram,this
isagoodpracticetokeepinmind.
ThischapterwillnotgointodetailsabouthowGNOMEworks.Ifyou
wouldliketoknowmore,visittheGNOMEdeveloperwebsiteat
http://developer.gnome.org/.Thissitecontainstutorials,mailing
lists,APIdocumentation,andeverythingelseyouneedtostart
programmingintheGNOMEenvironment.

ASimpleGNOMEPrograminSeveralLanguages
ThisprogramwillsimplyshowaWindowthathasabuttontoquitthe
application.Whenthatbuttonisclickeditwillaskyouifyouare
sure,andifyouclickyesitwillclosetheapplication.Torunthis
program,typeinthefollowingas
gnomeexample.s:

#PURPOSE:Thisprogramismeanttobeanexample
#ofwhatGUIprogramslooklikewritten
#withtheGNOMElibraries
#
#INPUT:Theusercanonlyclickonthe"Quit"
#buttonorclosethewindow

#
#OUTPUT:Theapplicationwillclose
#
#PROCESS:Iftheuserclicksonthe"Quit"button,
#theprogramwilldisplayadialogasking
#iftheyaresure.IftheyclickYes,it
#willclosetheapplication.Otherwise
#itwillcontinuerunning
#

.section.data

###GNOMEdefinitionsThesewerefoundintheGNOME
#headerfilesfortheClanguage
#andconvertedintotheirassembly
#equivalents

#GNOMEButtonNames
GNOME_STOCK_BUTTON_YES:
.ascii"Button_Yes\0"
GNOME_STOCK_BUTTON_NO:
.ascii"Button_No\0"

#GnomeMessageBoxTypes
GNOME_MESSAGE_BOX_QUESTION:
.ascii"question\0"

#StandarddefinitionofNULL
.equNULL,0

#GNOMEsignaldefinitions
signal_destroy:
.ascii"destroy\0"
signal_delete_event:
.ascii"delete_event\0"
signal_clicked:
.ascii"clicked\0"

###Applicationspecificdefinitions

#Applicationinformation
app_id:
.ascii"gnomeexample\0"

app_version:
.ascii"1.000\0"
app_title:
.ascii"GnomeExampleProgram\0"

#TextforButtonsandwindows
button_quit_text:
.ascii"IWanttoQuittheGNOMEExampleProgram\0"
quit_question:
.ascii"Areyousureyouwanttoquit?\0"

.section.bss

#Variablestosavethecreatedwidgetsin
.equWORD_SIZE,4
.lcommappPtr,WORD_SIZE
.lcommbtnQuit,WORD_SIZE

.section.text

.globlmain
.typemain,@function
main:
pushl%ebp
movl%esp,%ebp

#InitializeGNOMElibraries
pushl12(%ebp)#argv
pushl8(%ebp)#argc
pushl$app_version
pushl$app_id
callgnome_init
addl$16,%esp#recoverthestack

#Createnewapplicationwindow
pushl$app_title#Windowtitle
pushl$app_id#ApplicationID
callgnome_app__new
addl$8,%esp#recoverthestack
movl%eax,appPtr#savethewindowpointer
#Createnewbutton
pushl$button_quit_text#buttontext

callgtk_button_new_with_label
addl$4,%esp#recoverthestack
movl%eax,btnQuit#savethebuttonpointer

#Makethebuttonshowupinsidetheapplicationwindow
pushlbtnQuit
pushlappPtr
callgnome_app_set_contents
addl$8,%esp

#Makesthebuttonshowup(onlyafterit'swindow
#showsup,though)
pushlbtnQuit
callgtk_widget_show
addl$4,%esp

#Makestheapplicationwindowshowup
pushlappPtr
callgtk_widget_show
addl$4,%esp

#HaveGNOMEcallourdelete_handlerfunction
#whenevera"delete"eventoccurs
pushl$NULL#extradatatopasstoour
#function(wedon'tuseany)
pushl$delete_handler#functionaddresstocall
pushl$signal_delete_event#nameofthesignal
pushlappPtr#widgettolistenforeventson
callgtk_signal_connect
addl$16,%esp#recoverstack

#HaveGNOMEcallourdestroy_handlerfunction
#whenevera"destroy"eventoccurs
pushl$NULL#extradatatopasstoour
#function(wedon'tuseany)
pushl$destroy_handler#functionaddresstocall
pushl$signal_destroy#nameofthesignal
pushlappPtr#widgettolistenforeventson
callgtk_signal_connect
addl$16,%esp#recoverstack

#HaveGNOMEcallourclick_handlerfunction
#whenevera"click"eventoccurs.Notethat

#theprevioussignalswerelisteningonthe
#applicationwindow,whilethisoneisonly
#listeningonthebutton
pushl$NULL
pushl$click_handler
pushl$signal_clicked
pushlbtnQuit
callgtk_signal_connect
addl$16,%esp

#TransfercontroltoGNOME.Everythingthat
#happensfromhereoutisinreactiontouser
#events,whichcallsignalhandlers.Thismain
#functionjustsetsupthemainwindowandconnects
#signalhandlers,andthesignalhandlerstake
#careoftherest
callgtk_main

#Aftertheprogramisfinished,leave
movl$0,%eax
leave
ret

#A"destroy"eventhappenswhenthewidgetisbeing
#removed.Inthiscase,whentheapplicationwindow
#isbeingremoved,wesimplywanttheeventloopto
#quit
destroy_handler:
pushl%ebp
movl%esp,%ebp

#Thiscausesgtktoexitit'seventloop
#assoonasitcan.
callgtk_main_quit

movl$0,%eax
leave
ret

#A"delete"eventhappenswhentheapplicationwindow
#getsclickedinthe"x"thatyounormallyuseto
#closeawindow
delete_handler:

movl$1,%eax
ret

#A"click"eventhappenswhenthewidgetgetsclicked
click_handler:
pushl%ebp
movl%esp,%ebp

#Createthe"Areyousure"dialog
pushl$NULL#Endofbuttons
pushl$GNOME_STOCK_BUTTON_NO#Button1
pushl$GNOME_STOCK_BUTTON_YES#Button0
pushl$GNOME_MESSAGE_BOX_QUESTION#Dialogtype
pushl$quit_question#Dialogmesasge
callgnome_message_box_new
addl$16,%esp#recoverstack
#%eaxnowholdsthepointertothedialogwindow

#SettingModalto1preventsanyotheruser
#interactionwhilethedialogisbeingshown
pushl$1
pushl%eax
callgtk_window_set_modal
popl%eax
addl$4,%esp

#Nowweshowthedialog
pushl%eax
callgtk_widget_show
popl%eax

#Thissetsupallthenecessarysignalhandlers
#inordertojustshowthedialog,closeitwhen
#oneofthebuttonsisclicked,andreturnthe
#numberofthebuttonthattheuserclickedon.
#Thebuttonnumberisbasedontheorderthebuttons
#werepushedoninthegnome_message_box_newfunction
pushl%eax
callgnome_dialog_run_and_close
addl$4,%esp

#Button0istheYesbutton.Ifthisisthe
#buttontheyclickedon,tellGNOMEtoquit

#it'seventloop.Otherwise,donothing
cmpl$0,%eax
jneclick_handler_end

callgtk_main_quit

click_handler_end:
leave
ret

Tobuildthisapplication,executethefollowingcommands:
asgnomeexample.sognomeexample.o
gccgnomeexample.o'gnomeconfiglibsgnomeui'\
ognomeexample

Thentypein./gnomeexampletorunit.
Thisprogram,likemostGUIprograms,makesheavyuseofpassing
pointerstofunctionsasparameters.Inthisprogramyoucreate
widgetswiththeGNOMEfunctionsandthenyousetupfunctionstobe
calledwhencertaineventshappen.Thesefunctionsarecalled
callback
functions.Alloftheeventprocessingishandledbythe
functiongtk_main,soyoudon'thavetoworryabouthowtheevents
arebeingprocessed.Allyouhavetodoishavecallbackssetupto
waitforthem.
HereisashortdescriptionofalloftheGNOMEfunctionsthatwere
usedinthisprogram:
gnome_init
Takesthecommandlinearguments,argumentcount,applicationid,and
applicationversionandinitializestheGNOMElibraries.
gnome_app_new
Createsanewapplicationwindow,andreturnsapointertoit.Takes
theapplicationidandthewindowtitleasarguments.
gtk_button_new_with_label
Createsanewbuttonandreturnsapointertoit.Takesoneargument
thetextthatisinthebutton.
gnome_app_set_contents
Thistakesapointertothegnomeapplicationwindowandwhatever
widgetyouwant(abuttoninthiscase)andmakesthewidgetbethe
contentsoftheapplicationwindow
gtk_widget_show
Thismustbecalledoneverywidgetcreated(applicationwindow,
buttons,textentryboxes,etc)inorderforthemtobevisible.

However,inorderforagivenwidgettobevisible,allofits
parentsmustbevisibleaswell.
gtk_signal_connect
Thisisthefunctionthatconnectswidgetsandtheirsignalhandling
callbackfunctions.Thisfunctiontakesthewidgetpointer,thename
ofthesignal,thecallbackfunction,andanextradatapointer.
Afterthisfunctioniscalled,anytimethegiveneventistriggered,
thecallbackwillbecalledwiththewidgetthatproducedthesignal
andtheextradatapointer.Inthisapplication,wedon'tusethe
extradatapointer,sowejustsetittoNULL,whichis0.
gtk_main
ThisfunctioncausesGNOMEtoenterintoitsmainloop.Tomake
applicationprogrammingeasier,GNOMEhandlesthemainloopofthe
programforus.GNOMEwillcheckforeventsandcalltheappropriate
callbackfunctionswhentheyoccur.Thisfunctionwillcontinueto
processeventsuntilgtk_main_quitiscalledbyasignalhandler.
gtk_main_quit
ThisfunctioncausesGNOMEtoexititsmainloopattheearliest
opportunity.
gnome_message_box_new
Thisfunctioncreatesadialogwindowcontainingaquestionand
responsebuttons.Ittakesasparametersthemessagetodisplay,the
typeofmessageitis(warning,question,etc),andalistofbuttons
todisplay.ThefinalparametershouldbeNULLtoindicatethatthere
arenomorebuttonstodisplay.
gtk_window_set_modal
Thisfunctionmakesthegivenwindowamodalwindow.InGUI
programming,amodalwindowisonethatpreventseventprocessingin
otherwindowsuntilthatwindowisclosed.Thisisoftenusedwith
Dialogwindows.
gnome_dialog_run_and_close
Thisfunctiontakesadialogpointer(thepointerreturnedby
gnome_message_box_newcanbeusedhere)andwillsetupallofthe
appropriatesignalhandlerssothatitwillrununtilabuttonis
pressed.Atthattimeitwillclosethedialogandreturntoyou
whichbuttonwaspressed.Thebuttonnumberreferstotheorderin
whichthebuttonsweresetupingnome_message_box_new.
ThefollowingisthesameprogramwrittenintheClanguage.Typeit
inasgnomeexamplec.c:
/*PURPOSE:Thisprogramismeanttobeanexample
ofwhatGUIprogramslooklikewritten
withtheGNOMElibraries
*/


#include<gnome.h>

/*Programdefinitions*/
#defineMY_APP_TITLE"GnomeExampleProgram"
#defineMY_APP_ID"gnomeexample"
#defineMY_APP_VERSION"1.000"
#defineMY_BUTTON_TEXT"IWanttoQuittheExampleProgram"
#defineMY_QUIT_QUESTION"Areyousureyouwanttoquit?"

/*Mustdeclarefunctionsbeforetheyareused*/
intdestroy_handler(gpointerwindow,
GdkEventAny*e,
gpointerdata)
intdelete_handler(gpointerwindow,
GdkEventAny*e,
gpointerdata)
intclick__handler(gpointerwindow,
GdkEventAny*e,
gpointerdata)

intmain(intargc,char**argv)
{
gpointerappPtr/*applicationwindow*/
gpointerbtnQuit/*quitbutton*/

/*InitializeGNOMElibraries*/
gnome_init(MY_APP_ID,MY_APP_VERSION,argc,argv)

/*Createnewapplicationwindow*/
appPtr=gnome_app_new(MY_APP_ID,MY_APP_TITLE)

/*Createnewbutton*/
btnQuit=gtk_button_new_with_label(MY_BUTTON_TEXT)

/*Makethebuttonshowupinsidetheapplicationwindow*/
gnome_app_set_contents(appPtr,btnQuit)

/*Makesthebuttonshowup*/
gtk_widget_show(btnQuit)

/*Makestheapplicationwindowshowup*/
gtk_widget_show(appPtr)


/*Connectthesignalhandlers*/
gtk_signal_connect(appPtr,"delete_event",
GTK_SIGNAL_FUNC(delete_handler),NULL)
gtk_signal_connect(appPtr,"destroy",
GTK_SIGNAL_FUNC(destroy_handler),NULL)
gtk_signal_connect(btnQuit,"clicked",
GTK_SIGNAL_FUNC(click_handler),NULL)

/*TransfercontroltoGNOME*/
gtk_main()

return0
}

/*Functiontoreceivethe"destroy"signal*/
intdestroy_handler(gpointerwindow,
GdkEventAny*e,
gpointerdata)
{
/*LeaveGNOMEeventloop*/
gtk_main_quit()
return0
}

/*Functiontoreceivethe"delete_event"signal*/
intdelete_handler(gpointerwindow,
GdkEventAny*e,
gpointerdata)
{
return0
}
/*Functiontoreceivethe"clicked"signal*/
intclick_handler(gpointerwindow,
GdkEventAny*e,
gpointerdata)
{
gpointermsgbox
intbuttonClicked

/*Createthe"Areyousure"dialog*/
msgbox=gnome_message_box_new(
MY_QUIT_QUESTION,

GNOME_MESSAGE_BOX_QUESTION,
GNOME_STOCK_BUTTON_YES,
GNOME_STOCK_BUTTON_NO,
NULL)
gtk_window_set_modal(msgbox,1)
gtk_widget_show(msgbox)

/*Rundialogbox*/
buttonClicked=gnome_dialog_run_and_close(msgbox)

/*Button0istheYesbutton.Ifthisisthe
buttontheyclickedon,tellGNOMEtoquit
it'seventloop.Otherwise,donothing*/
if(buttonClicked==0)
{
gtk_main_quit()
}

return0
}

Tocompileit,type
gccgnomeexamplec.c'gnomeconfigcflags\
libsgnomeui'ognomeexamplec

Runitbytyping./gnomeexamplec.
Finally,wehaveaversioninPython.Typeitinasgnomeexample.py:
#PURPOSE:Thisprogramismeanttobeanexample
#ofwhatGUIprogramslooklikewritten
#withtheGNOMElibraries
#

#lmportGNOMElibraries
importgtk
importgnome.ui

####DEFINECALLBACKFUNCTIONSFIRST####

#InPython,functionshavetobedefinedbefore
#theyareused,sowehavetodefineourcallback
#functionsfirst.

defdestroy_handler(event):

gtk.mainquit()
return0

defdelete_handler(window,event):
return0

defclick_handler(event):
#Createthe"Areyousure"dialog
msgbox=gnome.ui.GnomeMessageBox(
"Areyousureyouwanttoquit?",
gnome.ui.MESSAGE_BOX_QUESTION,
gnome.ui.STOCK_BUTTON_YES,
gnome.ui.STOCK_BUTTON_NO)
msgbox.set_modal(1)
msgbox.show()

result=msgbox.run_and_close()

#Button0istheYesbutton.Ifthisisthe
#buttontheyclickedon,tellGNOMEtoquit
#it'seventloop.Otherwise,donothing
if(result==0):
gtk.mainquit()

return0

####MAINPROGRAM####

#Createnewapplicationwindow
myapp=gnome.ui.GnomeApp(
"gnomeexample","GnomeExampleProgram")

#Createnewbutton
mybutton=gtk.GtkButton(
"IWanttoQuittheGNOMEExampleprogram")
myapp.set_contents(mybutton)

#Makesthebuttonshowup
mybutton.show()

#Makestheapplicationwindowshowup
myapp.show()

#Connectsignalhandlers
myapp.connect("delete_event",delete_handler)
myapp.connect("destroy",destroy_handler)
mybutton.connect("clicked",click_handler)
#TransfercontroltoGNOME
gtk.mainloop()

Torunittypepythongnomeexample.py.

GUIBuilders
Inthepreviousexample,youhavecreatedtheuserinterfaceforthe
applicationbycallingthecreatefunctionsforeachwidgetand
placingitwhereyouwantedit.However,thiscanbequiteburdensome
formorecomplexapplications.Manyprogrammingenvironments,
includingGNOME,haveprogramscalledGUIbuildersthatcanbeused
toautomaticallycreateyourGUIforyou.Youjusthavetowritethe
codeforthesignalhandlersandforinitializingyourprogram.The
mainGUIbuilderforGNOMEapplicationsiscalledGLADE.GLADEships
withmostLinuxdistributions.
ThereareGUIbuildersformostprogrammingenvironments.Borlandhas
arangeoftoolsthatwillbuildGUIsquicklyandeasilyonLinuxand
Win32systems.TheKDEenvironmenthasatoolcalledQTDesigner
whichhelpsyouautomaticallydeveloptheGUIfortheirsystem.
Thereisabroadrangeofchoicesfordevelopinggraphical
applications,buthopefullythisappendixgaveyouatasteofwhat
GUIprogrammingislike.

AppendixB:Commonx86
Instructions
ReadingtheTables
Thetablesofinstructionspresentedinthisappendixinclude:
Theinstructioncode
Theoperandsused
Theflagsused
Abriefdescriptionofwhattheinstructiondoes

Intheoperandssection,itwilllistthetypeofoperandsittakes.
Ifittakesmorethanoneoperand,eachoperandwillbeseparatedby
acomma.Eachoperandwillhavealistofcodeswhichtellwhether
theoperandcanbeanimmediatemodevalue(I),aregister(R),ora
memoryaddress(M).Forexample,themovlinstructionislistedas
I/R/M,R/M.Thismeansthatthefirstoperandcanbeanykindof
value,whilethesecondoperandmustbearegisterormemory
location.Note,however,thatinx86assemblylanguageyoucannot
havemorethanoneoperandbeamemorylocation.
Intheflagssection,itliststheflagsinthe%eflagsregister
affectedbytheinstruction.Thefollowingflagsarementioned:
O
Overflowflag.Thisissettotrueifthedestinationoperandwasnot
largeenoughtoholdtheresultoftheinstruction.
S
Signflag.Thisissettothesignofthelastresult.
Z
Zeroflag.Thisflagissettotrueiftheresultoftheinstruction
iszero.
A
Auxiliarycarryflag.Thisflagissetforcarriesandborrows
betweenthethirdandfourthbit.Itisnotoftenused.
P
Parityflag.Thisflagissettotrueifthelowbyteofthelast
resulthadanevennumberof1bits.
C
Carryflag.Usedinarithmetictosaywhetherornottheresult
shouldbecarriedovertoanadditionalbyte.Ifthecarryflagis
set,thatusuallymeansthatthedestinationregistercouldnothold
thefullresult.Itisuptotheprogrammertodecideonwhataction
totake(i.e.propogatetheresulttoanotherbyte,signalan
error,orignoreitentirely).
Otherflagsexist,buttheyaremuchlessimportant.

DataTransferInstructions
Theseinstructionsperformlittle,ifanycomputation.Insteadthey
aremostlyusedformovingdatafromoneplacetoanother.
TableB1:DataTransferInstructions
Instruction
Operands
AffectedFlags

movl
I/R/M,I/R/M
O/S/Z/A/C
Thiscopiesawordofdatafromonelocationtoanother.movl%eax,
%ebxcopiesthecontentsof%eaxto%ebx
movb
I/R/M,I/R/M
O/S/Z/A/C
Sameasmovl,butoperatesonindividualbytes.
leal
M,I/R/M
O/S/Z/A/C
Thistakesamemorylocationgiveninthestandardformat,and,
insteadofloadingthecontentsofthememorylocation,loadsthe
computedaddress.Forexample,leal5(%ebp,%ecx,1),%eaxloadsthe
addresscomputedby5+%ebp+1*%ecxandstoresthatin%eax
popl
R/M
O/S/Z/A/C
Popsthetopofthestackintothegivenlocation.Thisisequivalent
toperformingmovl(%esp),R/Mfollowedbyaddl$4,%esp.popflisa
variantwhichpopsthetopofthestackintothe%eflagsregister.
pushl
I/R/M
O/S/Z/A/C
Pushesthegivenvalueontothestack.Thisistheequivalentto
performingsubl$4,%espfollowedbymovlI/R/M,(%esp).pushflisa
variantwhichpushesthecurrentcontentsofthe%eflagsregister
ontothe
top
ofthestack.
xchgl
R/M,R/M
O/S/Z/A/C
Exchangethevaluesofthegivenoperands.

IntegerInstructions
Thesearebasiccalculatinginstructionsthatoperateonsignedor
unsignedintegers.
Instruction

Operands

AffectedFlags

adcl

I/R/M,R/M

O/S/Z/A/P/C

Addwithcarry.Addsthecarrybitandthefirstoperandtothe
second,and,ifthereisanoverflow,setsoverflowandcarryto

true.Thisisusuallyusedforoperationslargerthanamachine
word.Theadditionontheleastsignificantwordwouldtakeplace
usingaddl,whileadditionstotheotherwordswouldusedtheadcl
instructiontotakethecarryfromthepreviousaddintoaccount.
Fortheusualcase,thisisnotused,andaddlisusedinstead.
addl

I/R/M,R/M

O/S/Z/A/P/C

Addition.Addsthefirstoperandtothesecond,storingtheresult
inthesecond.Iftheresultislargerthanthedestination
register,theoverflowandcarrybitsaresettotrue.This
instructionoperatesonbothsignedandunsignedintegers.
cdq

O/S/Z/A/P/C

Convertsthe%eaxwordintothedoublewordconsistingof%edx:%eax
withsignextension.Theqsignifiesthatitisa
quadword.
It's
actuallyadoubleword,butit'scalledaquadwordbecauseofthe
terminologyusedinthe16bitdays.Thisisusuallyusedbefore
issuinganidivlinstruction.
cmpl

I/R/M,R/M

O/S/Z/A/P/C

Comparestwointegers.Itdoesthisbysubtractingthefirst
operandfromthesecond.Itdiscardstheresults,butsetsthe
flagsaccordingly.Usuallyusedbeforeaconditionaljump.
decl

R/M

O/S/Z/A/P

Decrementstheregisterormemorylocation.Usedecbtodecrementa
byteinsteadofaword.
divl

R/M

O/S/Z/A/P

Performsunsigneddivision.Dividesthecontentsofthedoubleword
containedinthecombined%edx:%eaxregistersbythevalueinthe
registerormemorylocationspecified.The%eaxregistercontains
theresultingquotient,andthe%edxregistercontainsthe
resultingremainder.Ifthequotientistoolargetofitin%eax,
ittriggersatype0interrupt.
idivl

R/M

O/S/Z/A/P

Performssigneddivision.Operatesjustlikedivlabove.

imull

R/M/I,R

O/S/Z/A/P/C

Performssignedmultiplicationandstorestheresultinthesecond
operand.Ifthesecondoperandisleftout,itisassumedtobe
%eax,andthefullresultisstoredinthedoubleword%edx:%eax.
incl

R/M

O/S/Z/A/P

Incrementsthegivenregisterormemorylocation.Useincbto
incrementabyteinsteadofaword.
mull

R/M/I,R

O/S/Z/A/P/C

Performunsignedmultiplication.Samerulesasapplytoimull.
negl

R/M

O/S/Z/A/P/C

Negates(givesthetwo'scomplementinversionof)thegiven
registerormemorylocation.
sbbl

I/R/M,R/M

O/S/Z/A/P/C

Subtractwithborrowing.Thisisusedinthesamewaythatadcis,
exceptforsubtraction.Normallyonlysublisused.
subl

I/R/M,R/M

O/S/Z/A/P/C

Subtractthetwooperands.Thissubtractsthefirstoperandfrom
thesecond,andstorestheresultinthesecondoperand.This
instructioncanbeusedonbothsignedandunsignednumbers.

LogicInstructions
Theseinstructionsoperateonmemoryasbitsinsteadofwords.
Instruction

Operands

AffectedFlags

andl

I/R/M,R/M

O/S/Z/P/C

Performsalogicalandofthecontentsofthetwooperands,and
storestheresultinthesecondoperand.Setstheoverflowand
carryflagstofalse.
notl

R/M

Performsalogicalnotoneachbitintheoperand.Alsoknownasa
one'scomplement.
orl

I/R/M,R/M

O/S/Z/A/P/C

Performsalogicalorbetweenthetwooperands,andstoresthe
resultinthesecondoperand.Setstheoverflowandcarryflagsto
false.
rcll

I/%c1,R/M

O/C

Rotatesthegivenlocation'sbitstotheleftthenumberoftimes
inthefirstoperand,whichiseitheranimmediatemodevalueor
theregister%cl.Thecarryflagisincludedintherotation,
makingituse33bitsinsteadof32.Alsosetstheoverflowflag.
rcrl

I/%cl,R/M

O/C

Sameasabove,butrotatesright.
roll

I/%cl,R/M

O/C

Rotatebitstotheleft.Itsetstheoverflowandcarryflags,but
doesnotcountthecarryflagaspartoftherotation.Thenumber
ofbitstorolliseitherspecifiedinimmediatemodeoris
containedinthe%clregister.
rorl

I/%cl,R/M

O/C

Sameasabove,butrotatesright.
sall

I/%cl,R/M

Arithmeticshiftleft.Thesignbitisshiftedouttothecarry
flag,andazerobitisplacedintheleastsignificantbit.Other
bitsaresimplyshiftedtotheleft.Thisisthesameasthe
regularshiftleft.Thenumberofbitstoshiftiseitherspecified
inimmediatemodeoriscontainedinthe%clregister.
sarl

I/%cl,R/M

Arithmeticshiftright.Theleastsignificantbitisshiftedoutto
thecarryflag.Thesignbitisshiftedin,andkeptasthesign
bit.Otherbitsaresimplyshiftedtotheright.Thenumberofbits
toshiftiseitherspecifiedinimmediatemodeoriscontainedin

the%clregister.
shll

I/%cl,R/M

Logicalshiftleft.Thisshiftsallbitstotheleft(signbitis
nottreatedspecially).Theleftmostbitispushedtothecarry
flag.Thenumberofbitstoshiftiseitherspecifiedinimmediate
modeoriscontainedinthe%clregister.
shrl

I/%cl,R/M

Logicalshiftright.Thisshiftsallbitsintheregistertothe
right(signbitisnottreatedspecially).Therightmostbitis
pushedtothecarryflag.Thenumberofbitsoshiftiseither
specifiedinimmediatemodeoriscontainedinthe%clregister.
testl

I/R/M,R/M

O/S/Z/A/P/C

Doesalogicalandofbothoperandsanddiscardstheresults,but
setstheflagsaccordingly.
xorl

I/R/M,R/M

O/S/Z/A/P/C

Doesanexclusiveoronthetwooperands,andstorestheresultin
thesecondoperand.Setstheoverflowandcarryflagstofalse.

FlowControlInstructions
Theseinstructionsmayaltertheflowoftheprogram.
Instruction

Operands

AffectedFlags

call

destinationaddress

O/S/Z/A/C

Thispusheswhatwouldbethenextvaluefor%eipontothestack,
andjumpstothedestinationaddress.Usedforfunctioncalls.
Alternatively,thedestinationaddresscanbeanasteriskfollowed
byaregisterforanindirectfunctioncall.Forexample,call
*%eaxwillcallthefunctionattheaddressin%eax.
int

O/S/Z/A/C

Causesaninterruptofthegivennumber.Thisisusuallyusedfor
systemcallsandotherkernelinterfaces.
Jcc

destinationaddress

O/S/Z/A/C

Conditionalbranch.ccisthe
conditioncode.
Jumpstothegiven
addressiftheconditioncodeistrue(setfromtheprevious
instruction,probablyacomparison).Otherwise,goestothenext
instruction.Theconditioncodesare:
[n]a[e]above(unsignedgreaterthan).Anncanbeaddedfor
"not"andanecanbeaddedfor"orequalto"
[n]b[e]below(unsignedlessthan)
[n]eequalto
[n]zzero
[n]g[e]greaterthan(signedcomparison)
[n]l[e]lessthan(signedcomparison)
[n]ccarryflagset
[n]ooverflowflagset
[p]pparityflagset
[n]ssignflagset
ecxz%ecxiszero
jmp

destinationaddress

O/S/Z/A/C

Anunconditionaljump.Thissimplysets%eiptothedestination
address.Alternatively,thedestinationaddresscanbeanasterisk
followedbyaregisterforanindirectjump.Forexample,jmp*%eax
willjumptotheaddressin%eax.
ret

O/S/Z/A/C

Popsavalueoffofthestackandthensets%eiptothatvalue.
Usedtoreturnfromfunctioncalls.

AssemblerDirectives
Theseareinstructionstotheassemblerandlinker,insteadof
instructionstotheprocessor.Theseareusedtohelptheassembler
putyourcodetogetherproperly,andmakeiteasiertouse.
TableB5:AssemblerDirectives
Directive
Operands

.ascii
QUOTEDSTRING

Takesthegivenquotedstringandconvertsitintobytedata.

.byte
ALLIESVALUES

Takesacommaseparatedlistofvaluesandinsertsthemrightthere
intheprogramasdata.
.endr

Endsarepeatingsectiondefinedwith.rept.
.equ
LABEL,VALUE

Setsthegivenlabelequivalenttothegivenvalue.Thevaluecanbe
anumber,acharacter,oranconstantexpressionthatevaluatestoa
anumberorcharacter.promthatpointon,useofthelabelwillbe
substitutedforthegivenvalue.
.globl
LABEL

Setsthegivenlabelasglobal,meaningthatitcanbeusedfrom
separatelycompiledobjectfiles.
.include
FILE
Includesthegivenfilejustasifitweretypedinrightthere.
.lcomm
SYMBOL,SIZE

Thisisusedinthe.bsssectiontospecifystoragethatshouldbe
allocatedwhentheprogramisexecuted.Definesthesymbolwiththe
addresswherethestoragewillbelocated,andmakessurethatitis
thegivennumberofbyteslong.
.long
VALUES

Takesasequenceofnumbersseparatedbycommas,andinsertsthose
numbersas4bytewordsrightwheretheyareintheprogram.
.rept
COUNT

Repeatseverythingbetweenthisdirectiveandthe.endrdirectives
thenumberoftimesspecified.
.section
SECTIONNAME

Switchesthesectionthatisbeingworkedon.Commonsectionsinclude
.text(forcode),.data(fordataembeddedintheprogramitself),
and.bss(foruninitializedglobaldata).
.type
SYMBOL,@function

Tellsthelinkerthatthegivensymbolisafunction.

DifferencesinOtherSyntaxesandTerminology
Thesyntaxforassemblylanguageusedinthisbookisknownatthe
AT&T
syntax. It is the one supported by the GNU tool chain that comes standard with
every Linux distribution. However, the official syntax for x86 assembly language (known
as the Intel syntax) is different. It is the same assembly language for the same
platform, but it looks different. Some of the differences include:
InIntelsyntax,theoperandsofinstructionsareoftenreversed.The
destinationoperandislistedbeforethesourceoperand.
InIntelsyntax,registersarenotprefixedwiththepercentsign
(%).
InIntelsyntax,adollarsign($)isnotrequiredtodo
immediatemodeaddressing.Instead,nonimmediateaddressingis
accomplishedbysurroundingtheaddresswithbrackets([]).
InIntelsyntax,theinstructionnamedoesnotincludethesizeof
databeingmoved.Ifthatisambiguous,itisexplicitlystatedas
BYTE,WORD,OrDWORDimmediatelyaftertheinstructionname.
ThewaythatmemoryaddressesarerepresentedinIntelassembly
languageismuchdifferent(shownbelow).
Becausethex86processorlineoriginallystartedoutasa16bit
processor,mostliteratureaboutx86processorsrefertowordsas
16bitvalues,andcall32bitvaluesdoublewords.However,weuse
theterm"word"torefertothestandardregistersizeona
processor,whichis32bitsonanx86processor.Thesyntaxalso
keepsthisnamingconventionDWORDstandsfor"doubleword"in
Intelsyntaxandisusedforstandardsizedregisters,whichwewould
callsimplya"word".
Intelassemblylanguagehastheabilitytoaddressmemoryasa
segment/offsetpair.WedonotmentionthisbecauseLinuxdoesnot
supportsegmentedmemory,andisthereforeirrelevanttonormalLinux
programming.
Otherdifferencesexist,buttheyaresmallincomparison.Toshow
someofthedifferences,considerthefollowinginstruction:

movl%eax,8(%ebx,%edi,4)

InIntelsyntax,thiswouldbewrittenas:
mov[8+%ebx+1*edi],eax

ThememoryreferenceisabiteasiertoreadthanitsAT&T
counterpartbecauseitspellsoutexactlyhowtheaddresswillbe
computed.However,buttheorderofoperandsinIntelsyntaxcanbe
confusing.

WheretoGoforMoreInformation
Intelhasasetofcomprehensiveguidestotheirprocessors.These
areavailableathttp://www.intel.com/design/pentium/manuals/Note
thatalloftheseusetheIntelsyntax,nottheAT&Tsyntax.Themost
importantonesaretheir
IA32IntelArchitectureSoftwareDeveloper's
Manual
initsthreevolumes::
Volume1:SystemProgrammingGuide
(http://developer.intel.com/design/pentium4/manuals/245470.htm)
Volume2:InstructionSetReference
(http://developer.intel.com/design/pentium4/manuals/245471.htm)
Volume3:SystemProgrammingGuide
(http://developer.intel.com/design/pentium4/manuals/245472.htm)
Inaddition,youcanfindalotofinformationinthemanualforthe
GNUassembler,availableonlineat
http://www.gnu.org/software/binutils/manual/gas2.9.1/as.html.
Similarly,themanualfortheGNUlinkerisavailableonlineat
http://www.gnu.org/software/binutils/manual/ld2.9.1/ld.html.

AppendixC:ImportantSystem
Calls
Thesearesomeofthemoreimportantsystemcallstousewhendealing
withLinux.Formostcases,however,itisbesttouselibrary
functionsratherthandirectsystemcalls,becausethesystemcalls
weredesignedtobeminimalisticwhilethelibraryfunctionswere
designedtobeeasytoprogramwith.ForinformationabouttheLinux
Clibrary,seethemanualathttp://www.gnu.org/software/libc/manual/
Rememberthat%eaxholdsthesystemcallnumbers,andthatthereturn
valuesanderrorcodesarealsostoredin%eax.

%eax Name %ebx

%ecx

%edx

Notes

exit return
value(int)

Exitstheprogram

read file
descriptor

buffer
start

buffer
size
(int)

Readsintothegiven
buffer

writ file
e
descriptor

buffer
start

buffer
size
(int)

Writesthebufferto
thefiledescriptor

open nulltermin
atefile
name

option
list

permiss
ion
mode

Opensthegivenfile.
Returnsthefile
descriptororanerror
number.

clos file
e
descriptor

Closesthegivefile
descriptor

12

chdi nulltermin
r
ated
directory
name

Changesthecurrent
directoryofyour
program.

19

lsee file
k
descriptor

offset

mode

Repositionswhereyou
areinthegivenfile.
Themode(calledthe
"whence")shouldbe0
forabsolute
positioning,and1for
relativepositioning.

20

getp
id

ReturnstheprocessID
ofthecurrentprocess.

39

mkdi nulltermin
r
ated
directory
name

permiss
ion
mode

Createsthegiven
directory.Assumesall
directoriesleadingup
toitalreadyexist.

40

rmdi nulltermin
r
ated

Removesthegiven
directory.

directory
name
41

dup

file
descriptor

Returnsanewfile
descriptorpatworks
justliketheexisting
filedescriptor.

42

pipe pipearray

Createstwofile
descriptors,where
writingononeproduces
datatoreadonthe
otherandviceversa.
%ebxisapointerto
twowordsofstorageto
holdthefile
descriptors.

45

brk

Setsthesystembreak
(i.e.theendofthe
datasection).Ifthe
systembreakis0,it
simplyreturnsthe
currentsystembreak.

54

ioct file
l
descriptor

request

argumen
ts

Thisisusedtoset
parametersondevice
files.Itsactualusage
variesbasedonthe
typeoffileordevice
yourdescriptor
references.

newsystem
break

Amorecompletelistingofsystemcalls,alongwithadditional
informationisavailableat
http://www.lxhp.inberlin.de/lhpsyscal.htmlYoucanalsogetmore
informationaboutasystemcallbytypinginman2SYSCALLNAMEwhich
willreturnyoutheinformationaboutthesystemcallfromsection2
oftheUNIXmanual.However,thisreferstotheusageofthesystem
callfromtheCprogramminglanguage,andmayormaynotbedirectly
helpful.
ForinformationonhowsystemcallsareimplementedonLinux,seethe
LinuxKernel2.4Internalssectiononhowsystemcallsare
implementedathttp://www.faqs.org/docs/kernel_2_4/lki2.html#ss2.11

AppendixD:Tableof
ASCIICodes
Tousethistable,simplyfindthecharacterorescapethatyouwant
thecodefor,andaddthenumberontheleftandthetop.

+0

+1

+2

+3

+4

+5

+6

+7

NUL

SOH

STX

ETX

EOT

ENQ

ACK

BEL

BS

HT

LF

VT

FF

CR

SO

SI

16

DLE

DC1

DC2

DC3

DC4

NAK

SYN

ETB

24

CAN

EM

SUB

ESC

FS

GS

RS

US

32

"

&

'

40

48

56

<

>

64

72

80

88

96

'

10
4

11
2

12
0

DEL

ASCII is actually being phased out in favor of an international standard known as


Unicode, which allows you to display any character from any known writing system in the
world. As you may have noticed, ASCII only has support for English characters. Unicode
is much more complicated, however, because it requires more than one byte to encode a
single character. There are several different methods for encoding Unicode characters.
The most common is UTF-8 and UTF-32. UTF-8 is somewhat backwards-compatible with
ASCII (it is stored the same for English characters, but expands into multiple byte for
international characters). UTF-32 simply requires four bytes for each character rather
than one. Windows uses UTF-16, which is a variable-length encoding which requires at
least 2 bytes per character, so it is not backwards-compatible with ASCII.
Agoodtutorialoninternationalizationissues,fonts,andUnicodeis
availableinagreatArticlebyJoeSpolsky,called"TheAbsolute
MinimumEverySoftwareDeveloperAbsolutely,PositivelyMustKnow
AboutUnicodeandCharacterSets(NoExcuses!)",availableonlineat
http://www.joelonsoftware.com/articles/Unicode.html

AppendixE:CIdiomsinAssembly
Language
ThisappendixisforCprogrammerslearningassemblylanguage.Itis
meanttogiveageneralideaabouthowCconstructscanbe
implementedinassemblylanguage.

IfStatement
InC,anifstatementconsistsofthreepartsthecondition,the
truebranch,andthefalsebranch.However,sinceassemblylanguage
isnotablockstructuredlanguage,youhavetoworkalittleto
implementtheblocklikenatureofC.Forexample,lookatthe
followingCcode:
if(a==b)
{
/*TrueBranchCodeHere*/
}
else
{
/*FalseBranchCodeHere*/
}

/*AtThisPoint,Reconverge*/

Inassemblylanguage,thiscanberenderedas:

#Moveaandbintoregistersforcomparison
movla,%eax
movlb,%ebx

#Compare
cmpl%eax,%ebx

#IfTrue,gototruebranch
jetrue_branch
false_branch:#Thislabelisunnecessary,
#onlyherefordocumentation
#FalseBranchCodeHere

#Jumptorecovergencepoint
jmpreconverge

true_branch:
#TrueBranchCodeHere

reconverge:
#Bothbranchesrecovergetothispoint

Asyoucansee,sinceassemblylanguageislinear,theblockshaveto
jumparoundeachother.Recovergenceishandledbytheprogrammer,
notthesystem.
Acasestatementiswrittenjustlikeasequenceofifstatements.

FunctionCall
Afunctioncallinassemblylanguagesimplyrequirespushingthe
argumentstothefunctionontothestackin
reverse
order,and
issuingacallinstruction.Aftercalling,theargumentsarethen
poppedbackoffofthestack.Forexample,considertheCcode:
printf("Thenumberis%d",88)

Inassemblylanguage,thiswouldberenderedas:
.section.data
text_string:
.ascii"Thenumberis%d\0"
.section.text

pushl$88
pushl$text_string
callprintf
popl%eax
popl%eax#%eaxisjustadummyvariable,
#nothingisactuallybeingdone
#withthevalue.Youcanalso
#directlyreadjust%esptothe
#properlocation.

VariablesandAssignment
Globalandstaticvariablesaredeclaredusing.dataor.bssentries.
Localvariablesaredeclaredbyreservingspaceonthestackatthe
beginningofthefunction.Thisspaceisgivenbackattheendofthe
function.
Interestingly,globalvariablesareaccesseddifferentlythanlocal
variablesinassemblylanguage.Globalvariablesareaccessedusing
directaddressing,whilelocalvariablesareaccessedusingbase
pointeraddressing.Forexample,considerthefollowingCcode:
intmy_global_var

intfoo()
{
intmy_local_var

my_local_var=1
my_global_var=2

return0
}

Thiswouldberenderedinassemblylanguageas:
.section.data
.lcommmy_global_var,4

.typefoo,@function
foo:
pushl%ebp#Saveoldbasepointer
movl%esp,$ebp#makestackpointerbasepointer

subl$4,%esp#Makeroomformy_local_var
.equmy_local_var,4#Cannowusemy_local_varto
#findthelocalvariable

movl$1,my_local_var(%ebp)
movl$2,my_global_var

movl%ebp,%esp#Cleanupfunctionandreturn
popl%ebp
ret

Whatmaynotbeobviousisthataccessingtheglobalvariabletakes
fewermachinecyclesthanaccessingthelocalvariable.However,that
maynotmatterbecausethestackismorelikelytobeinphysical
memory(insteadofswap)thantheglobalvariableis.
AlsonotethatintheCprogramminglanguage,afterthecompiler
loadsavalueintoaregister,thatvaluewilllikelystayinthat
registeruntilthatregisterisneededforsomethingelse.Itmay
alsomoveregisters.Forexample,ifyouhaveavariablefoo,itmay
startonthestack,butthecompilerwilleventuallymoveitinto
registersforprocessing.Iftherearen'tmanyvariablesinuse,the
valuemaysimplystayintheregisteruntilitisneededagain.
Otherwise,whenthatregisterisneededforsomethingelse,the
value,ifit'schanged,iscopiedbacktoitscorrespondingmemory
location.InC,youcanusethekeywordvolatiletomakesureall
modificationsandreferencestothevariablearedonetothememory
locationitself,ratherthanaregistercopyofit,incaseother
processes,threads,orhardwaremaybemodifyingthevaluewhileyour
functionisrunning.

Loops
Loopsworkalotlikeifstatementsinassemblylanguagetheblocks
areformedbyjumpingaround.InC,awhileloopconsistsofaloop
body,andatesttodeterminewhetherornotitistimetoexitthe
loop.Aforloopisexactlythesame,withoptionalinitialization
andcounterincrementsections.Thesecansimplybemovedaroundto
makeawhileloop.
InC,awhilelooplookslikethis:
while(a<b)
{

/*Dostuffhere*/
}

/*FinishedLooping*/

Thiscanberenderedinassemblylanguagelikethis:
loop_begin:
movla,%eax
movlb,%ebx
cmpl%eax,%ebx
jgeloop_end

loop_body:
#Dostuffhere

jmploop_begin

loop_end:
#Finishedlooping

Thex86assemblylanguagehassomedirectsupportforloopingas
well.The%ecxregistercanbeusedasacounterthat
ends
withzero.
Theloopinstructionwilldecrement%ecxandjumptoaspecified
addressunless%ecxiszero.Forexample,ifyouwantedtoexecutea
statement100times,youwoulddothisinC:
for(i=0i<100i++)
{
/*Doprocesshere*/
}

Inassemblylanguageitwouldbewrittenlikethis:
loop_initialize:
movl$100,%ecx
loop_begin:
#
#DoProcessHere
#

#Decrement%ecxandloopsifnotzero
looploop_begin

rest_of_program:

#Continuesontohere

Onethingtonoticeisthattheloopinstruction
requiresyoutobe
countingbackwardstozero.
Ifyouneedtocountforwardsoruse
anotherendingnumber,youshouldusetheloopformwhichdoesnot
includetheloopinstruction.
Forreallytightloopsofcharacterstringoperations,thereisalso
therepinstruction,butwewillleavelearningaboutthatasan
exercisetothereader.

Structs
Structsaresimplydescriptionsofmemoryblocks.Forexample,inC
youcansay:
structperson{
charfirstname[40]
charlastname[40]
intage
}

Thisdoesn'tdoanythingbyitself,exceptgiveyouwaysof
intelligentlyusing84bytesofdata.Youcandobasicallythesame
thingusing.equdirectivesinassemblylanguage.Likethis:
.equPERSON_SIZE,84
.equPERSON_FIRSTNAME_OFFSET,0
.equPERSON_LASTNAME_OFFSET,40
.equPERSON_AGE_OFFSET,80

Whenyoudeclareavariableofthistype,allyouaredoingis
reserving84bytesofspace.So,ifyouhavethisinC:
voidfoo()
{
structpersonp

/*Dostuffhere*/
}

Inassemblylanguageyouwouldhave:
foo:
#Standardheaderbeginning
pushl%ebp
movl%esp,%ebp

#Reserveourlocalvariable

subl$PERSON_SIZE,%esp
#Thisisthevariable'soffsetfrom%ebp
.equP_VAR,0PERSON_SIZE

#DoStuffHere

#Standardfunctionending
movl%ebp,%esp
popl%ebp
ret

Toaccessstructuremembers,youjusthavetousebasepointer
addressingwiththeoffsetsdefinedabove.Forexample,inCyou
couldsettheperson'sagelikethis:
p.age=30

Inassemblylanguageitwouldlooklikethis:
movl$30,P_VAR+PERSON_AGE_OFFSET(%ebp)

Pointers
Pointersareveryeasy.Remember,pointersaresimplytheaddress
thatavalueresidesat.Let'sstartbytakingalookatglobal
variables.Forexample:
intglobal_data=30

Inassemblylanguage,thiswouldbe:
.section.data
global_data:
.long30

TakingtheaddressofthisdatainC:
a=&global_data

Takingtheaddressofthisdatainassemblylanguage:
movl$global_data,%eax

Yousee,withassemblylanguage,youarealmostalwaysaccessing
memorythroughpointers.That'swhatdirectaddressingis.Togetthe
pointeritself,youjusthavetogowithimmediatemodeaddressing.

Localvariablesarealittlemoredifficult,butnotmuch.Hereis
howyoutaketheaddressofalocalvariableinC:
voidfoo()
{
inta
int*b

a=30

b=&a

*b=44
}

Thesamecodeinassemblylanguage:
foo:
#Standardopening
pushl%ebp
movl%esp,%ebp

#Reservetwowordsofmemory
subl$8,$esp
.equA_VAR,4
.equB_VAR,8

#a=30
movl$30,A_VAR(%ebp)

#b=&a
movl$A_VAR,B_VAR(%ebp)
addl%ebp,B_VAR(%ebp)

#*b=30
movlB_VAR(%ebp),%eax
movl$30,(%eax)

#Standardclosing
movl%ebp,%esp
popl%ebp
ret

Asyoucansee,totaketheaddressofalocalvariable,theaddress
hastobecomputedthesamewaythecomputercomputestheaddresses

inbasepointeraddressing.Thereisaneasierwaytheprocessor
providestheinstructionleal,whichstandsfor"loadeffective
address".Thisletsthecomputercomputetheaddress,andthenload
itwhereveryouwant.So,wecouldjustsay:
#b=&a
lealA_VAR(%ebp),%eax
movl%eax,B_VAR(%ebp)

It'sthesamenumberoflines,butalittlecleaner.Then,touse
thisvalue,yousimplyhavetomoveittoageneralpurposeregister
anduseindirectaddressing,asshownintheexampleabove.

GettingGCCtoHelp
OneofthenicethingsaboutGCCisitsabilitytospitoutassembly
languagecode.ToconvertaClanguagefiletoassembly,youcan
simplydo:
gccSfile.c

Theoutputwillbeinfile.s.It'snotthemostreadableoutput
mostofthevariablenameshavebeenremovedandreplacedeitherwith
numericstacklocationsorreferencestoautomaticallygenerated
labels.Tostartwith,youprobablywanttoturnoffoptimizations
withO0sothattheassemblylanguageoutputwillfollowyoursource
codebetter.
SomethingelseyoumightnoticeisthatGCCreservesmorestackspace
1]
forlocalvariablesthanwedo,andthenAND's%esp[

Thisisto
increasememoryandcacheefficiencybydoublewordaligning
variables.
Finally,attheendoffunctions,weusuallydothefollowing
instructionstocleanupthestackbeforeissuingaretinstruction:
movl%ebp,%esp
popl%ebp

However,GCCoutputwillusuallyjustincludetheinstructionleave.
Thisinstructionissimplythecombinationoftheabovetwo
instructions.Wedonotuseleaveinthistextbecausewewanttobe
clearaboutexactlywhatishappeningattheprocessorlevel.
IencourageyoutotakeaCprogramyouhavewrittenandcompileit
toassemblylanguageandtracethelogic.Then,addinoptimizations
andtryagain.Seehowthecompilerchosetorearrangeyourprogram

tobemoreoptimized,andtrytofigureoutwhyitchosethe
arrangementandinstructionsitdid.
[1]
NotethatdifferentversionsofGCCdothisdifferently.

AppendixF:UsingtheGDB
Debugger
Overview
Bythetimeyoureadthisappendix,youwilllikelyhavewrittenat
leastoneprogramwithanerrorinit.Inassemblylanguage,even
minorerrorsusuallyhaveresultssuchasthewholeprogramcrashing
withasegmentationfaulterror.Inmostprogramminglanguages,you
cansimplyprintoutthevaluesinyourvariablesasyougoalong,
andusethatoutputtofindoutwhereyouwentwrong.Inassembly
language,callingoutputfunctionsisnotsoeasy.Therefore,toaid
indeterminingthesourceoferrors,youmustusea
sourcedebugger.
Adebuggerisaprogramthathelpsyoufindbugsbysteppingthrough
theprogramonestepatatime,lettingyouexaminememoryand
registercontentsalongtheway.A
sourcedebugger
isadebuggerthat
allowsyoutotiethedebuggingoperationdirectlytothesourcecode
ofaprogram.Thismeansthatthedebuggerallowsyoutolookatthe
sourcecodeasyoutypeditincompletewithsymbols,labels,and
comments.
ThedebuggerwewillbelookingatisGDBtheGNUDebugger.This
applicationispresentonalmostallGNU/Linuxdistributions.Itcan
debugprogramsinmultipleprogramminglanguages,includingassembly
language.

AnExampleDebuggingSession
Thebestwaytoexplainhowadebuggerworksisbyusingit.The
programwewillbeusingthedebuggeronisthemaximumprogramused
inChapter3.Let'ssaythatyouenteredtheprogramperfectly,
exceptthatyouleftouttheline:
incl%edi

Whenyouruntheprogram,itjustgoesinaninfiniteloopitnever
exits.Todeterminethecause,youneedtoruntheprogramunderGDB.

However,todothis,youneedtohavetheassemblerincludedebugging
informationintheexecutable.Allyouneedtodotoenablethisis
toaddthegstabsoptiontotheascommand.So,youwouldassemble
itlikethis:
asgstabsmaximum.somaximum.o

Linkingwouldbethesameasnormal."stabs"isthedebuggingformat
usedbyGDB.Now,toruntheprogramunderthedebugger,youwould
typeingdb./maximum.Besurethatthesourcefilesareinthe
currentdirectory.Theoutputshouldlooksimilartothis:
GNUgdbRedHatLinux(5.2.14)
Copyright2002FreeSoftwareFoundation,Inc.
GDBisfreesoftware,coveredbytheGNUGeneralPublic
License,andyouarewelcometochangeitand/or
distributecopiesofitundercertainconditions.Type
"showcopying"toseetheconditions.Thereis
absolutelynowarrantyforGDB.Type"showwarranty"
fordetails.
ThisGDBwasconfiguredas"i386redhatlinux"...
(gdb)

DependingonwhichversionofGDByouarerunning,thisoutputmay
varyslightly.Atthispoint,theprogramisloaded,butisnot
runningyet.Thedebuggeriswaitingyourcommand.Torunyour
program,justtypeinrun.Thiswillnotreturn,becausetheprogram
isrunninginaninfiniteloop.Tostoptheprogram,hitcontrolc.
Thescreenwillthensaythis:
Startingprogram:/home/johnnyb/maximum

ProgramreceivedsignalSIGINT,Interrupt.
start_loop()atmaximum.s:34
34movldata_items(,%edi,4),%eax
Currentlanguage:autocurrentlyasm
(gdb)

ThistellsyouthattheprogramwasinterruptedbytheSIGINTsignal
(fromyourcontrolc),andwaswithinthesectionlabelled
start_loop,andwasexecutingonline34whenitstopped.Itgives
youthecodethatitisabouttoexecute.
Dependingonexactlywhenyouhitcontrolc,itmayhavestoppedona
differentlineoradifferentinstructionthantheexample.
Oneofthebestwaystofindbugsinaprogramistofollowtheflow
oftheprogramtoseewhereitisbranchingincorrectly.Tofollow

theflowofthisprogram,keeponenteringstepi(for"step
instruction"),whichwillcausethecomputertoexecuteone
instructionatatime.Ifyoudothisseveraltimes,youroutputwill
looksomethinglikethis:
(gdb)stepi
35cmpl%ebx,%eax
(gdb)stepi
36jlestart_loop
(gdb)stepi
32cmpl$0,%eax
(gdb)stepi
33jeloop_exit
(gdb)stepi
34movldata_items(,%edi,4),%eax
(gdb)stepi
35cmpl%ebx,%eax
(gdb)stepi
36jlestart_loop
(gdb)step
32cmpl$0,%eax

Asyoucantell,ithaslooped.Ingeneral,thisisgood,sincewe
wroteittoloop.However,theproblemisthatitis
neverstopping.
Therefore,tofindoutwhattheproblemis,let'slookatthepoint
inourcodewhereweshouldbeexittingtheloop:
cmpl$0,%eax
jeloop_exit

Basically,itischeckingtoseeif%eaxhitszero.Ifso,itshould
exittheloop.Thereareseveralthingstocheckhere.Firstofall,
youmayhaveleftthispieceoutaltogether.Itisnotuncommonfora
programmertoforgettoincludeawaytoexitaloop.However,this
isnotthecasehere.Second,youshouldmakesurethatloop_exit
actuallyisoutsidetheloop.Ifweputthelabelinthewrongplace,
strangethingswouldhappen.However,again,thisisnotthecase.
Neitherofthosepotentialproblemsaretheculprit.So,thenext
optionisthatperhaps%eaxhasthewrongvalue.Therearetwoways
tocheckthecontentsofregisterinGDB.Thefirstoneisthe
commandinforegister.Thiswilldisplaythecontentsofall
registersinhexadecimal.However,weareonlyinterestedin%eaxat
thispoint.Tojustdisplay%eaxwecandoprint/$eaxtoprintitin
hexadecimal,ordoprint/d$eaxtoprintitindecimal.Noticethat

inGDB,registersareprefixedwithdollarsignsratherthanpercent
signs.Yourscreenshouldhavethisonit:
(gdb)print/d$eax
$1=3
(gdb)

Thismeansthattheresultofyourfirstinquiryis3.Everyinquiry
youmakewillbeassignedanumberprefixedwithadollarsign.Now,
ifyoulookbackintothecode,youwillfindthat3isthefirst
numberinthelistofnumberstosearchthrough.Ifyoustepthrough
theloopafewmoretimes,youwillfindthatineveryloopiteration
%eaxhasthenumber3.Thisisnotwhatshouldbehappening.%eax
shouldgotothenextvalueinthelistineveryiteration.
Okay,nowweknowthat%eaxisbeingloadedwiththesamevalueover
andoveragain.Let'ssearchtoseewhere%eaxisbeingloadedfrom.
Thelineofcodeisthis:
movldata_items(,%edi,4),%eax

So,stepuntilthislineofcodeisreadytoexecute.Now,thiscode
dependsontwovaluesdata_itemsand%edi.data_itemsisasymbol,
andthereforeconstant.It'sagoodideatocheckyoursourcecodeto
makesurethelabelisinfrontoftherightdata,butinourcaseit
is.Therefore,weneedtolookat%edi.So,weneedtoprintitout.
Itwilllooklikethis:
(gdb)print/d$edi
$2=0
(gdb)

Thisindicatesthat%ediissettozero,whichiswhyitkeepson
loadingthefirstelementofthearray.Thisshouldcauseyoutoask
yourselftwoquestionswhatisthepurposeof%edi,andhowshould
itsvaluebechanged?Toanswerthefirstquestion,wejustneedto
lookinthecomments.%ediisholdingthecurrentindexof
data_items.Sinceoursearchisasequentialsearchthroughthelist
ofnumbersindata_items,itwouldmakesensethat%edishouldbe
incrementedwitheveryloopiteration.
Scanningthecode,thereisnocodewhichalters%ediatall.
Therefore,weshouldaddalinetoincrement%ediatthebeginningof
everyloopiteration.Thishappenstobeexactlythelinewetossed
outatthebeginning.Assembling,linking,andrunningtheprogram
againwillshowthatitnowworkscorrectly.
HopefullythisexerciseprovidedsomeinsightintousingGDBtohelp
youfinderrorsinyourprograms.

BreakpointsandOtherGDBFeatures
Theprogramweenteredinthelastsectionhadaninfiniteloop,and
couldbeeasilystoppedusingcontrolc.Otherprogramsmaysimply
abortorfinishwitherrors.Inthesecases,controlcdoesn'thelp,
becausebythetimeyoupresscontrolc,theprogramisalready
finished.Tofixthis,youneedtoset
breakpoints.
Abreakpointisa
placeinthesourcecodethatyouhavemarkedtoindicatetothe
debuggerthatitshouldstoptheprogramwhenithitsthatpoint.
Tosetbreakpointsyouhavetosetthemupbeforeyourunthe
program.Beforeissuingtheruncommand,youcansetupbreakpoints
usingthebreakcommand.Forexample,tobreakonline27,issuethe
commandbreak27.Then,whentheprogramcrossesline27,itwill
stoprunning,andprintoutthecurrentlineandinstruction.Youcan
thenstepthroughtheprogramfromthatpointandexamineregisters
andmemory.Tolookatthelinesandlinenumbersofyourprogram,
youcansimplyusethecommand1.Thiswillprintoutyourprogram
withlinenumbersascreenatatime.
Whendealingwithfunctions,youcanalsobreakonthefunction
names.Forexample,inthefactorialprograminChapter4,wecould
setabreakpointforthefactorialfunctionbytypinginbreak
factorial.Thiswillcausethedebuggertobreakimmediatelyafter
thefunctioncallandthefunctionsetup(itskipsthepushingof
%ebpandthecopyingof%esp).
Whensteppingthroughcode,youoftendon'twanttohavetostep
througheveryinstructionofeveryfunction.Welltestedfunctions
areusuallyawasteoftimetostepthroughexceptonrareoccasion.
Therefore,ifyouusethenexticommandinsteadofthestepicommand,
GDBwillwaituntilcompletionofthefunctionbeforegoingon.
Otherwise,withstepi,GDBwouldstepyouthrougheveryinstruction
withineverycalledfunction.

Warning

OneproblemthatGDBhasiswithhandlinginterrupts.
OftentimesGDBwillmisstheinstructionthat
immediatelyfollowsaninterrupt.Theinstructionis
actuallyexecuted,butGDBdoesn'tstepthroughit.This
shouldnotbeaproblemjustbeawarethatitmay
happen.

GDBQuickReference
Thisquickreferencetableiscopyright2002RobertM.Dondero,Jr.,
andisusedbypermissioninthisbook.Parameterslistedinbrackets
areoptional.
TableF1:CommonGDBDebuggingCommands
Miscellaneous
quit

ExitGDB

help[cmd]

Printdescriptionofdebuggercommandcmd.Without
cmd,printsalistoftopics.

directory
[dir1][dir2]
...

Adddirectoriesdir1,dir2,etc.tothelistof
directoriessearchedforsourcefiles.

RunningtheProgram
run[arg1]
[arg2]...

Runtheprogramwithcommandlinearguments
arg1,arg2,etc.

setargsarg1
[arg2]...

Settheprogram'scommandlineargumentsto
arg1,arg2,etc.

showargs

Printtheprogram'scommandlinearguments.

UsingBreakpoints
infobreakpoints

Printalistofallbreakpointsandtheir
numbers(breakpointnumbersareusedforother
breakpointcommands).

break
linenum

Setabreakpointatlinenumber
linenum.

break
*addr

Setabreakpointatmemoryaddress
addr.

break
fn

Setabreakpointatthebeginningoffunction
fn.

condition
bpnum
expr

Breakatbreakpoint
bpnum
onlyifexpression
expr
isnonzero.

command[
bpnum
]
cmd1
[
cmd2
]...

Executecommands
cmd1,cmd2,
etc.whenever
breakpoint
bpnum
(orthecurrentbreakpoint)is
hit.

Continue

Continueexecutingtheprogram.

Kill

Stopexecutingtheprogram.

delete[
bpnum1
]
[
bpnum2
]...

Deletebreakpoints
bpnuml,bpnum2,
etc.,orall
breakpointsifnonespecified.

clear
*addr

Clearthebreakpointatmemoryaddress
addr.

clear[
fn
]

Clearthebreakpointatfunction
fn
,orthe
currentbreakpoint.

clear
linenum

Clearthebreakpointatlinenumber
linenum.

disable[
bpnum1
]
[
bpnum2
]...

Disablebreakpoints
bpnum1,bpnum2,
etc.,orall
breakpointsifnonespecified.

enable[
bpnum1
]
[
bpnum2
]...

Enablebreakpoints
bpnum1,bpnum2,
etc.,orall
breakpointsifnonespecified.

SteppingthroughtheProgram
next "Stepover"thenextinstruction(doesn't
i
followfunctioncalls).
step "Stepinto"thenextinstruction(follows
i
functioncalls).
fini "Stepout"ofthecurrentfunction.
sh

ExaminingRegistersandMemory
info
registers

Printthecontentsofallregisters.

print/
f
$reg

Printthecontentsofregister
reg
usingformat
f
.The
formatcanbex(hexadecimal),u(unsigneddecimal),o
(octal),a(address),c(character),orf(floating
point).

x/
rsfaddr Printthecontentsofmemoryaddress
addr
usingrepeat
count
r
,size
s,
andformat
f
.Repeatcountdefaultsto
1ifnotspecified.Sizecanbeb(byte),h(halfword),
w(word),org(doubleword).Sizedefaultstowordif
notspecified.Formatisthesameasforprint,with
theadditionsofs(string)andi(instruction).
info
display

Showsanumberedlistofexpressionssetuptodisplay
automaticallyateachbreak.

display/
f Ateachbreak,printthecontentsofregister
reg
using
$reg
format
f
.
display/
s
iAteachbreak,printthecontentsofmemoryaddress
addr
addr
usingsize
s
(sameoptionsasforthexcommand).
display/
ssAteachbreak,printthestringofsize
s
thatbeginsin
addr
memoryaddress
addr.
undisplay Remove
displaynum
fromthedisplaylist.
displaynum
ExaminingtheCallStack
where
Printthecallstack.
backtrace
Printthecallstack.
frame
Printthetopofthecallstack.
up
Movethecontexttowardthebottomofthecallstack.
down
Movethecontexttowardthetopofthecallstack.

Das könnte Ihnen auch gefallen