X86-64 Assembly Language Part 3: Control (Loops)
Required Reading: section 3.6.7
Control: Condition codes Conditional branches
There are many good reasons to use –S to compile C code to assembly code
• To find out what gcc is doing to your code [we found a compiler bug once]
• To learn different ways of accomplishing things
• To compare the code produced with various options (-g, -O, -Ofast…)
Do NOT turn in machine generated .s files ever
• Those files were generated by a machine, not you (misrepresentation
of the work)
• Such labs will be turned over to the Committee on Academic Misconduct
C Code Goto Version
Count number of 1’s in argument x (“popcount”)
Use conditional branch to either continue looping or to exit loop
long pcount_do
(unsigned long x) {
long result = 0;
result += x & 0x1;
} while (x); return result;
long pcount_goto
(unsigned long x) {
long result = 0;
result += x & 0x1; x >>= 1;
if(x) goto loop; return result;
Goto Version
Argument x
long pcount_goto (unsigned long x) { long result = 0;
result += x & 0x1;
if(x) goto loop;
return result;
movq $0, %rax
movq %rdi, %rdx
andq $1, %rdx
addq %rdx, %rax # result += t
shrq %rdi jne .L2 ret
# if (x) goto loop
# result = 0
# t = x & 0x1
Goto Version
while (Test);
Statement1; Statement2;
… Statementn;
“Jump-to-middle” translation Used with gcc -Og
While version
Goto Version
goto test; loop:
goto loop;
while (Test) Body
Jump to Middle Version
long pcount_goto_jtm (unsigned long x) { long result = 0; goto test;
result += x & 0x1;
if(x) goto loop;
return result;
long pcount_while
(unsigned long x) {
long result = 0;
while (x) {
result += x & 0x1;
x >>= 1; }
return result;
Compare to do-while version of function Initial goto starts loop at test
While version
“Do-while” conversion Used with gcc -O1
Goto Version
while (Test) Body
if (!Test) goto done;
goto loop;
Do-While Version
if (!Test) goto done;
doBody while(Test);
C Code Do-While Version
Compare to do-while version of function Initial conditional guards entrance to loop
long pcount_while
(unsigned long x) {
long result = 0;
while (x) {
result += x & 0x1;
x >>= 1; }
return result;
long pcount_goto_dw
(unsigned long x) {
long result = 0;
if (!x) goto done;
result += x & 0x1; x >>= 1;
if(x) goto loop;
return result;
General Form
for (Init; Test; Update ) Body
#define WSIZE 8*sizeof(long)
long pcount_for
(unsigned long x)
long result = 0;
for (i = 0; i < WSIZE; i++) {
unsigned bit =
(x >> i) & 0x1;
result += bit;
return result;
unsigned bit =
(x >> i) & 0x1;
result += bit;
For Version
for (Init; Test; Update ) Body
While Version
while (Test ) {
long pcount_for_while
(unsigned long x)
long result = 0; i = 0;
while (i < WSIZE) {
unsigned bit =
(x >> i) & 0x1;
result += bit;
return result; }
unsigned bit =
(x >> i) & 0x1;
result += bit;
long pcount_for_goto_dw (unsigned long x) { size_t i;
long result = 0;
if (!(i < WSIZE))!Test
goto done; loop:
unsigned bit =
(x >> i) & 0x1; result += bit;
if (i < WSIZE)
goto loop; done:
return result;
Goto Version
long pcount_for
(unsigned long x)
long result = 0;
for (i = 0; i < WSIZE; i++) {
unsigned bit =
(x >> i) & 0x1;
result += bit;
return result;
Initial test can be optimized away