control flow - cs.wellesley.edu
Post on 18-Jan-2022
2 Views
Preview:
TRANSCRIPT
Controlflow
ConditioncodesConditionalandunconditionaljumpsLoopsSwitchstatements
1
ConditionalsandControlFlowTwokeypieces
1. Comparisonsandtests:checkconditions2. Transfercontrol:choosenextinstruction
FamiliarCconstructsl if elsel whilel do whilel forl breakl continue
2
Instructionpointer(a.k.a.programcounter)
registerholdsaddressofnextinstructiontoexecute
Conditioncodes (a.k.a.flags)1-bitregistersholdflagssetbylastALUoperation
ZeroFlag result==0
SignFlag result<0
CarryFlag carry-out/unsignedoverflow
OverflowFlag two'scomplementoverflow
%rip
CF
ZF
SF
OF
ProcessorControl-FlowState
1.compare and test: conditionscmpq b,a computes a - b, setsflags,discardsresult
Whichflagsindicatethata < b ?(signed?unsigned?)
testq b,a computes a & b, setsflags,discardsresult
Commonpattern:testq %rax, %rax
WhatdoZF andSF indicate?
3
ex
Aside:saveconditions
4
long gt(int x, int y) {return x > y;
}
cmpq %rdi,%rsi # compare: x – y
setg %al # al = x > y
movzbq %al,%rax # zero rest of %rax
Zero-extendfromByte(8bits)toQuadword (64bits)
setg:setifgreaterstoresbyte:
0x01if~(SF^OF)&~ZF0x00otherwise
%rax %eax %al%ah
2.jump:choosenextinstructionJump/branch todifferentpartofcodebysetting%eip.
6
j__ Condition Descriptionjmp 1 Unconditionalje ZF Equal/Zerojne ~ZF NotEqual/NotZerojs SF Negativejns ~SF Nonnegativejg ~(SF^OF)&~ZF Greater(Signed)jge ~(SF^OF) GreaterorEqual(Signed)jl (SF^OF) Less(Signed)jle (SF^OF)|ZF LessorEqual(Signed)ja ~CF&~ZF Above(unsigned)jb CF Below(unsigned)
Alwaysjump
Jumpiff condition
Jumpforcontrolflow
7
cmpq %rax,%rcxje label………addq %rdx,%raxlabel:
LabelNameforaddressof
followingitem.
Jumpimmediatelyfollowscomparison/test.Together,theymakeadecision:"if%rax =%rcx ,jumptolabel."
Executedonlyif%rax ≠%rcx
ConditionalBranch Example
8
long absdiff(long x,long y) {long result;if (x > y) {
result = x-y;} else {
result = y-x;}return result;
}
LabelsNameforaddressof
followingitem.
Howdidthecompilercreatethis?
absdiff:cmpq %rsi, %rdijle .L7subq %rsi, %rdimovq %rdi, %rax
.L8:retq
.L7:subq %rdi, %rsijmp .L8
Control-FlowGraph
long absdiff(long x, long y){long result;if (x > y) {
result = x-y;} else {
result = y-x;}return result;
}
long result;if (x > y) else
result = x-y; result = y-x;
return result;
IntroducedbyFranAllen,etal.Wonthe2006TuringAwardforherworkoncompilers.
Nodes=BasicBlocks:Straight-linecodealwaysexecutedtogetherinorder.
Edges=ControlFlow:Whichbasicblockexecutesnext(underwhatcondition).
Codeflowchart/directedgraph.
then else
Choosealinearorderofbasicblocks.
long result;if (x > y) else
result = x-y;
result = y-x;
return result;
long result;if (!(x > y))
result = y-x;
result = x-y;
return result;
elseelsethenthen
Choosealinearorderofbasicblocks.
long result;if (!(x > y))
result = x-y;
result = y-x;
return result;
Whymightthecompilerchoosethisbasicblockorderinsteadofanothervalidorder?
Translatebasicblockswithjumps+labels
cmpq %rsi, %rdijle Else
subq %rsi, %rdimovq %rdi, %rax
subq %rdi, %rsimovq %rsi, %raxjmp End
retq
Else:
End:
long result;if (!(x > y))
result = x-y;
result = y-x;
return result;
Whymightthecompilerchoosethisbasicblockorderinsteadofanothervalidorder?
Executeabsdiff
13
%rax
%rdi
%rsi
exRegisters
cmpq %rsi, %rdijle Else
subq %rsi, %rdimovq %rdi, %rax
retq
Else:
End:
subq %rdi, %rsimovq %rsi, %raxjmp End
Note:CSAPPshowstranslationwithgoto
14
long goto_ad(long x,long y){int result;if (x <= y) goto Else;result = x-y;
End:return result;
Else:result = y-x;goto End;
}
long absdiff(long x,long y){int result;if (x > y) {
result = x-y;} else {
result = y-x;}return result;
}
Note:CSAPPshowstranslationwithgoto
15
long goto_ad(long x, long y){long result;if (x <= y) goto Else;result = x-y;
End:return result;
Else:result = y-x;goto End;
}
Closetoassemblycode.
cmpq %rsi, %rdijle Else
subq %rsi, %rdimovq %rdi, %rax
retq
Else:
End:
absdiff:
subq %rdi, %rsimovq %rsi, %raxjmp End
16
http://xkcd.com/292/
Butneverusegoto inyoursourcecode!
compileif-else ex
long wacky(long x, long y){int result;if (x + y > 7) {
result = x;} else {
result = y + 2;}return result;
}
Assumexavailablein%rdi,yavailablein%rsi.
Placeresultin%rax.
EncodingJumps:PC-relativeaddressing
18
l PC-relativeoffsets supportrelocatablecode.l Absolutebranchesdonot(orit'shard).
0x100 cmpq %rax, %rbx 0x10000x102 je 0x70 0x10020x104 … 0x1004… … …0x174 addq %rax, %rbx 0x1074
CompilingLoops
CompilationofotherloopsshouldbestraightforwardInterestingpart:puttheconditionalbranchat toporbottomofloop?
20
while ( sum != 0 ) {<loop body>
}
loopTop: testq %rax, %raxje loopDone
<loop body code>jmp loopTop
loopDone:
Machinecode:C/Javacode:
CCodelong fact_do(long x) {
long result = 1;do {
result = result * x;x = x-1;
} while (x > 1);return result;
}
do while loopexample
21
Keys:• Usebackwardbranchtocontinuelooping• Onlytakebranchwhen“while”conditionholds
long result = 1;
result = result*x;x = x-1;
(x > 1) ?
return result;
YesNo
do while looptranslation
22
Register Variable%rdi%rax
fact_do:movq $1,%rax
.L11:imulq %rdi,%raxdecq %rdicmpq $1,%rdijg .L11
retq
Assembly
Whyputtheloopconditionattheend?
Why?
long result = 1;
result = result*x;x = x-1;
(x > 1) ?
return result;
YesNo
CCodelong fact_while(long x){
long result = 1;while (x > 1) {
result = result * x;x = x-1;
}return result;
}
while looptranslation
23
Why?
long result = 1;
result = result*x;x = x-1;
(x > 1) ?
return result;
long result = 1;
result = result*x;x = x-1;
(x > 1) ?
return result;
ThisorderisusedbyGCCforx86-64
YesNo
YesNo
int fact_while(int x) {int result = 1;while (x > 1) {
result = result * x;x = x - 1;
};return result;
}
movq $1, %raxjmp .L34
.L35:imulq %rdi, %raxdecq %rdi
.L34:cmpq $1, %rdijg .L35
while loopexample
25
int result = 1;
result = result*x;x = x-1;
(x > 1) ?
return result;
YesNo
for (result = 1; p != 0; p = p>>1) {if (p & 0x1) {
result = result * x;}x = x*x;
}
for looptranslation
31
for (Initialize; Test; Update)Body
ForVersion
Initialize;while (Test) {
Body ;Update;
}
WhileVersion
Initialize
BodyUpdate
Test ? YesNo
result = 1;
if (p & 0x1) {result = result*x;
}x = x*x;p = p>>1;
(p != 0) ? YesNo
cmov src,dest if (Test) Destß SrcWhy?Branchpredictioninpipelined/OoO processors.
(Aside)ConditionalMove
35
absdiff:movq %rdi, %rax # xsubq %rsi, %rax # result = x-ymovq %rsi, %rdxsubq %rdi, %rdx # else_val = y-xcmpq %rsi, %rdi # x:ycmovle %rdx, %rax # if <=, result = else_valret
long absdiff(long x, long y) {return x>y ? x-y : y-x;
}
long absdiff(long x, long y) {long result;if (x>y) {
result = x-y;} else {
result = y-x;}
}
ExpensiveComputations
(Aside)BadCasesforConditionalMove
36
val = Test(x) ? Hard1(x) : Hard2(x);
RiskyComputationsval = p ? *p : 0;
Computationswithsideeffectsval = x > 0 ? x*=7 : x+=3;
long switch_eg (unsigned long x, long y, long z) {long w = 1;switch(x) {case 1:
w = y*z;break;
case 2:w = y/z;/* Fall Through */
case 3:w += z;break;
case 5:case 6:
w -= z;break;
default:w = 2;
}return w;
}
switch statements
Fallthroughcases
Missingcases
Multiplecaselabels
Lotstomanage,let'suseajumptable
37
JumpTableStructure
switch(x) {case 1: <some code>
break;case 2: <some code>case 3: <some code>
break;case 5:case 6: <some code>
break;default: <some code>
}
38
65432
JumpTable
CodeBlocks
Memory
Wecanusethejumptablewhenx <=6:
if (x <= 6)target = JTab[x];goto target;
elsegoto default;
Ccode:
10
JumpTable
39
.section .rodata.align 8
.L4:.quad .L8 # x = 0.quad .L3 # x = 1.quad .L5 # x = 2.quad .L9 # x = 3.quad .L8 # x = 4.quad .L7 # x = 5.quad .L7 # x = 6
Jumptableswitch(x) {case 1: // .L56
w = y*z;break;
case 2: // .L57w = y/z;/* Fall Through */
case 3: // .L58w += z;break;
case 5:case 6: // .L60
w -= z;break;
default: // .L61w = 2;
}
“quad”asin41978-era16-bitwords
declaringdata,notinstructions
8-bytememoryalignment
switch statementexample
switch_eg:movq %rdx, %rcxcmpq $6, %rdija .L8jmp *.L4(,%rdi,8)
long switch_eg(long x, long y, long z) {long w = 1;switch(x) {
. . .}return w;
}
40
Jumptable.section .rodata
.align 8.L4:
.quad .L8 # x = 0
.quad .L3 # x = 1
.quad .L5 # x = 2
.quad .L9 # x = 3
.quad .L8 # x = 4
.quad .L7 # x = 5
.quad .L7 # x = 6
Indirectjump
Jumpifabove(likejg,butunsigned)
ex
butthisissigned...
CodeBlocks(x==1)
.L3:movq %rsi, %rax # yimulq %rdx, %rax # y*zret
switch(x) {case 1: // .L3
w = y*z;break;
. . .}return w;
41
Compilerhas"inlined"thereturn.
Register Use(s)
%rdi Argumentx
%rsi Argumenty
%rdx Argumentz
%rax Returnvalue
HandlingFall-Through
long w = 1;switch (x) {. . .case 2: // .L5
w = y/z;/* Fall Through */
case 3: // .L9w += z;break;
. . .}
case 3:w = 1;
case 2:w = y/z;goto merge;
merge:w += z;
42
Compilerhasinlined "w=1"onlywherenecessary.
CodeBlocks(x==2,x==3)
.L5: # Case 2movq %rsi, %rax # y in raxcqto # Div prepidivq %rcx # y/zjmp .L6 # goto merge
.L9: # Case 3movl $1, %eax # w = 1
.L6: # merge:addq %rcx, %rax # w += zret
long w = 1;switch (x) {. . .
case 2: // .L5w = y/z;/* Fall Through */
case 3: // .L9w += z;break;
. . .}
43
Compilerhasinlined "w=1"onlywherenecessary.
Aside: movl isusedbecause1isasmallpositivevaluethatfitsin32bits.Highorderbitsof%rax getsettozeroautomatically.Ittakesonelessbytetoencodeamovl thanamovq.
Register Use(s)
%rdi Argumentx
%rsi Argumenty
%rdx Argumentz
%rax Returnvalue
CodeBlocks(x==5,x==6,default)
.L7: # Case 5,6movl $1, %eax # w = 1subq %rdx, %rax # w -= zret
.L8: # Default:movl $2, %eax # 2ret
long w = 1;switch (x) {
. . .case 5: // .L7case 6: // .L7
w -= z;break;
default: // .L8w = 2;
}
44
Register Use(s)
%rdi Argumentx
%rsi Argumenty
%rdx Argumentz
%rax Returnvalue
switch machinecodeSetup
Label.L8: 0x000000000040052a Label.L4: 0x00000000004005d0
45
00000000004004f6 <switch_eg>:. . .4004fd: 77 2b ja 40052a <switch_eg+0x34>4004ff: ff 24 fd d0 05 40 00 jmpq *0x4005d0(,%rdi,8)
switch_eg:. . .ja .L8jmp *.L4(,%rdi,8)
AssemblyCode
DisassembledObjectCode
InspectjumptableusingGDB.Examinecontentsas7 addressesUsecommand“help x”togetformatdocumentation
(gdb) x/7a 0x00000000004005d00x4005d0: 0x40052a <switch_eg+52> 0x400506 <switch_eg+16>0x4005e0: 0x40050e <switch_eg+24> 0x400518 <switch_eg+34>
0x4005f0: 0x40052a <switch_eg+52> 0x400521 <switch_eg+43>0x400600: 0x400521 <switch_eg+43>
MatchingDisassembledTargets
47
400506: 48 89 f0 mov %rsi,%rax400509: 48 0f af c2 imul %rdx,%rax40050d: c3 retq40050e: 48 89 f0 mov %rsi,%rax400511: 48 99 cqto400513: 48 f7 f9 idiv %rcx400516: eb 05 jmp 40051d <switch_eg+0x27>400518: b8 01 00 00 00 mov $0x1,%eax40051d: 48 01 c8 add %rcx,%rax400520: c3 retq400521: b8 01 00 00 00 mov $0x1,%eax400526: 48 29 d0 sub %rdx,%rax400529: c3 retq40052a: b8 02 00 00 00 mov $0x2,%eax40052f: c3 retq
0x40052a0x4005060x40050e0x4005180x40052a0x4005210x400521
0x4005d0:
Sectionofdisassembledswitch_eg:
Jumptablecontents:
¢ Wouldyouimplementthiswithajumptable?
¢ Probablynot:§ Don’twanta jumptablewith52001entriesforonly4cases(toobig)§ about200KB=200,000bytes§ textofthisswitchstatement=about200bytes
Question
switch(x) {case 0: <some code>
break;case 10: <some code>
break;case 52000: <some code>
break;default: <some code>
break;}
48
ex
top related