Table of Contents

Examining Compiler Generated Machine Code

On this page we will explore the process of generating machine code from one or more .c files.

Trivial C Program

The following C program, wk1.c, does nothing:

int main()
{
}

Even so, it produces the following .lss file:

wk1.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000000a2  00000000  00000000  00000054  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .stab         00000378  00000000  00000000  000000f8  2**2
                  CONTENTS, READONLY, DEBUGGING
  2 .stabstr      0000005f  00000000  00000000  00000470  2**0
                  CONTENTS, READONLY, DEBUGGING
  3 .debug_aranges 00000020  00000000  00000000  000004cf  2**0
                  CONTENTS, READONLY, DEBUGGING
  4 .debug_pubnames 0000001b  00000000  00000000  000004ef  2**0
                  CONTENTS, READONLY, DEBUGGING
  5 .debug_info   0000008a  00000000  00000000  0000050a  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_abbrev 00000034  00000000  00000000  00000594  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_line   00000055  00000000  00000000  000005c8  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_frame  00000020  00000000  00000000  00000620  2**2
                  CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 2a 00 	jmp	0x54	; 0x54 <__ctors_end>
   4:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
   8:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
   c:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  10:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  14:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  18:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  1c:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  20:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  24:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  28:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  2c:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  30:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  34:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  38:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  3c:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  40:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  44:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  48:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  4c:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>
  50:	0c 94 47 00 	jmp	0x8e	; 0x8e <__bad_interrupt>

00000054 <__ctors_end>:
  54:	11 24       	eor	r1, r1
  56:	1f be       	out	0x3f, r1	; 63
  58:	cf e5       	ldi	r28, 0x5F	; 95
  5a:	d8 e0       	ldi	r29, 0x08	; 8
  5c:	de bf       	out	0x3e, r29	; 62
  5e:	cd bf       	out	0x3d, r28	; 61

00000060 <__do_copy_data>:
  60:	10 e0       	ldi	r17, 0x00	; 0
  62:	a0 e6       	ldi	r26, 0x60	; 96
  64:	b0 e0       	ldi	r27, 0x00	; 0
  66:	e2 ea       	ldi	r30, 0xA2	; 162
  68:	f0 e0       	ldi	r31, 0x00	; 0
  6a:	02 c0       	rjmp	.+4      	; 0x70 <.do_copy_data_start>

0000006c <.do_copy_data_loop>:
  6c:	05 90       	lpm	r0, Z+
  6e:	0d 92       	st	X+, r0

00000070 <.do_copy_data_start>:
  70:	a0 36       	cpi	r26, 0x60	; 96
  72:	b1 07       	cpc	r27, r17
  74:	d9 f7       	brne	.-10     	; 0x6c <.do_copy_data_loop>

00000076 <__do_clear_bss>:
  76:	10 e0       	ldi	r17, 0x00	; 0
  78:	a0 e6       	ldi	r26, 0x60	; 96
  7a:	b0 e0       	ldi	r27, 0x00	; 0
  7c:	01 c0       	rjmp	.+2      	; 0x80 <.do_clear_bss_start>

0000007e <.do_clear_bss_loop>:
  7e:	1d 92       	st	X+, r1

00000080 <.do_clear_bss_start>:
  80:	a0 36       	cpi	r26, 0x60	; 96
  82:	b1 07       	cpc	r27, r17
  84:	e1 f7       	brne	.-8      	; 0x7e <.do_clear_bss_loop>
  86:	0e 94 49 00 	call	0x92	; 0x92 <main>
  8a:	0c 94 50 00 	jmp	0xa0	; 0xa0 <_exit>

0000008e <__bad_interrupt>:
  8e:	0c 94 00 00 	jmp	0	; 0x0 <__vectors>

00000092 <main>:
  92:	cf 93       	push	r28
  94:	df 93       	push	r29
  96:	cd b7       	in	r28, 0x3d	; 61
  98:	de b7       	in	r29, 0x3e	; 62
  9a:	df 91       	pop	r29
  9c:	cf 91       	pop	r28
  9e:	08 95       	ret

000000a0 <_exit>:
  a0:	ff cf       	rjmp	.-2      	; 0xa0 <_exit>

Vectors

ctors_end

00000054 <__ctors_end>:
  54:	11 24       	eor	r1, r1
  56:	1f be       	out	0x3f, r1	; 63  SREG
  58:	cf e5       	ldi	r28, 0x5F	; 95
  5a:	d8 e0       	ldi	r29, 0x08	; 8
  5c:	de bf       	out	0x3e, r29	; 62  SPH
  5e:	cd bf       	out	0x3d, r28	; 61  SPL

do_copy_data

Initializes X and Z registers for copying data from program memory into data memory.

00000060 <__do_copy_data>:
  60:	10 e0       	ldi	r17, 0x00	; 0
  62:	a0 e6       	ldi	r26, 0x60	; 96
  64:	b0 e0       	ldi	r27, 0x00	; 0
  66:	e2 ea       	ldi	r30, 0xA2	; 162
  68:	f0 e0       	ldi	r31, 0x00	; 0
  6a:	02 c0       	rjmp	.+4      	; 0x70 <.do_copy_data_start>

do_clear_bss

Empty main and Beyond

00000092 <main>:
  92:	cf 93       	push	r28
  94:	df 93       	push	r29
  96:	cd b7       	in	r28, 0x3d	; 61
  98:	de b7       	in	r29, 0x3e	; 62
  9a:	df 91       	pop	r29
  9c:	cf 91       	pop	r28
  9e:	08 95       	ret

000000a0 <_exit>:
  a0:	ff cf       	rjmp	.-2      	; 0xa0 <_exit>

Non-Trivial C Program

#include <avr/io.h>
 
int y[4];
 
int main()
{
  char word[] = "funness";
  int x[3];
  int i = 1;
  PORTB = x[i];
  for(i=0; i<3; ++i)
  {
    x[i] = PINB;
  }
  for(i=0; i<3; ++i)
  {
    PORTB = x[3-i];
  }
  return 0;
}

Below are parts of the listing file generated with no compiler optimization.

Data Copy

00000060 <__do_copy_data>:
  60:	10 e0       	ldi	r17, 0x00	; 0
  62:	a0 e6       	ldi	r26, 0x60	; 96
  64:	b0 e0       	ldi	r27, 0x00	; 0
  66:	ee ea       	ldi	r30, 0xAE	; 174
  68:	f1 e0       	ldi	r31, 0x01	; 1
  6a:	02 c0       	rjmp	.+4      	; 0x70 <.do_copy_data_start>

0000006c <.do_copy_data_loop>:
  6c:	05 90       	lpm	r0, Z+
  6e:	0d 92       	st	X+, r0

00000070 <.do_copy_data_start>:
  70:	a8 36       	cpi	r26, 0x68	; 104
  72:	b1 07       	cpc	r27, r17
  74:	d9 f7       	brne	.-10     	; 0x6c <.do_copy_data_loop>

Clearing Data Area for Uninitialized Global/Static Variables

00000076 <__do_clear_bss>:
  76:	10 e0       	ldi	r17, 0x00	; 0
  78:	a8 e6       	ldi	r26, 0x68	; 104
  7a:	b0 e0       	ldi	r27, 0x00	; 0
  7c:	01 c0       	rjmp	.+2      	; 0x80 <.do_clear_bss_start>

0000007e <.do_clear_bss_loop>:
  7e:	1d 92       	st	X+, r1

00000080 <.do_clear_bss_start>:
  80:	a0 37       	cpi	r26, 0x72	; 114
  82:	b1 07       	cpc	r27, r17
  84:	e1 f7       	brne	.-8      	; 0x7e <.do_clear_bss_loop>
  86:	0e 94 49 00 	call	0x92	; 0x92 <main>
  8a:	0c 94 d6 00 	jmp	0x1ac	; 0x1ac <_exit>

Main

The main function is much more exciting now. Here are few things to keep in mind when view this code:

00000092 <main>:
  92:	cf 93       	push	r28
  94:	df 93       	push	r29
  96:	cd b7       	in	r28, 0x3d	; 61
  98:	de b7       	in	r29, 0x3e	; 62
  9a:	65 97       	sbiw	r28, 0x15	; 21
  9c:	0f b6       	in	r0, 0x3f	; 63
  9e:	f8 94       	cli
  a0:	de bf       	out	0x3e, r29	; 62
  a2:	0f be       	out	0x3f, r0	; 63
  a4:	cd bf       	out	0x3d, r28	; 61
  a6:	ae 01       	movw	r20, r28
  a8:	4d 5f       	subi	r20, 0xFD	; 253
  aa:	5f 4f       	sbci	r21, 0xFF	; 255
  ac:	5a 8b       	std	Y+18, r21	; 0x12
  ae:	49 8b       	std	Y+17, r20	; 0x11
  b0:	80 e6       	ldi	r24, 0x60	; 96
  b2:	90 e0       	ldi	r25, 0x00	; 0
  b4:	9c 8b       	std	Y+20, r25	; 0x14
  b6:	8b 8b       	std	Y+19, r24	; 0x13
  b8:	98 e0       	ldi	r25, 0x08	; 8
  ba:	9d 8b       	std	Y+21, r25	; 0x15
  bc:	eb 89       	ldd	r30, Y+19	; 0x13
  be:	fc 89       	ldd	r31, Y+20	; 0x14
  c0:	00 80       	ld	r0, Z
  c2:	4b 89       	ldd	r20, Y+19	; 0x13
  c4:	5c 89       	ldd	r21, Y+20	; 0x14
  c6:	4f 5f       	subi	r20, 0xFF	; 255
  c8:	5f 4f       	sbci	r21, 0xFF	; 255
  ca:	5c 8b       	std	Y+20, r21	; 0x14
  cc:	4b 8b       	std	Y+19, r20	; 0x13
  ce:	e9 89       	ldd	r30, Y+17	; 0x11
  d0:	fa 89       	ldd	r31, Y+18	; 0x12
  d2:	00 82       	st	Z, r0
  d4:	49 89       	ldd	r20, Y+17	; 0x11
  d6:	5a 89       	ldd	r21, Y+18	; 0x12
  d8:	4f 5f       	subi	r20, 0xFF	; 255
  da:	5f 4f       	sbci	r21, 0xFF	; 255
  dc:	5a 8b       	std	Y+18, r21	; 0x12
  de:	49 8b       	std	Y+17, r20	; 0x11
  e0:	5d 89       	ldd	r21, Y+21	; 0x15
  e2:	51 50       	subi	r21, 0x01	; 1
  e4:	5d 8b       	std	Y+21, r21	; 0x15
  e6:	8d 89       	ldd	r24, Y+21	; 0x15
  e8:	88 23       	and	r24, r24
  ea:	41 f7       	brne	.-48     	; 0xbc <main+0x2a>
  ec:	81 e0       	ldi	r24, 0x01	; 1
  ee:	90 e0       	ldi	r25, 0x00	; 0
  f0:	9a 83       	std	Y+2, r25	; 0x02
  f2:	89 83       	std	Y+1, r24	; 0x01
  f4:	a8 e3       	ldi	r26, 0x38	; 56
  f6:	b0 e0       	ldi	r27, 0x00	; 0
  f8:	89 81       	ldd	r24, Y+1	; 0x01
  fa:	9a 81       	ldd	r25, Y+2	; 0x02
  fc:	9c 01       	movw	r18, r24
  fe:	22 0f       	add	r18, r18
 100:	33 1f       	adc	r19, r19
 102:	ce 01       	movw	r24, r28
 104:	01 96       	adiw	r24, 0x01	; 1
 106:	82 0f       	add	r24, r18
 108:	93 1f       	adc	r25, r19
 10a:	fc 01       	movw	r30, r24
 10c:	3a 96       	adiw	r30, 0x0a	; 10
 10e:	80 81       	ld	r24, Z
 110:	91 81       	ldd	r25, Z+1	; 0x01
 112:	8c 93       	st	X, r24
 114:	1a 82       	std	Y+2, r1	; 0x02
 116:	19 82       	std	Y+1, r1	; 0x01
 118:	16 c0       	rjmp	.+44     	; 0x146 <main+0xb4>
 11a:	29 81       	ldd	r18, Y+1	; 0x01
 11c:	3a 81       	ldd	r19, Y+2	; 0x02
 11e:	e6 e3       	ldi	r30, 0x36	; 54
 120:	f0 e0       	ldi	r31, 0x00	; 0
 122:	80 81       	ld	r24, Z
 124:	48 2f       	mov	r20, r24
 126:	50 e0       	ldi	r21, 0x00	; 0
 128:	22 0f       	add	r18, r18
 12a:	33 1f       	adc	r19, r19
 12c:	ce 01       	movw	r24, r28
 12e:	01 96       	adiw	r24, 0x01	; 1
 130:	82 0f       	add	r24, r18
 132:	93 1f       	adc	r25, r19
 134:	fc 01       	movw	r30, r24
 136:	3a 96       	adiw	r30, 0x0a	; 10
 138:	51 83       	std	Z+1, r21	; 0x01
 13a:	40 83       	st	Z, r20
 13c:	89 81       	ldd	r24, Y+1	; 0x01
 13e:	9a 81       	ldd	r25, Y+2	; 0x02
 140:	01 96       	adiw	r24, 0x01	; 1
 142:	9a 83       	std	Y+2, r25	; 0x02
 144:	89 83       	std	Y+1, r24	; 0x01
 146:	89 81       	ldd	r24, Y+1	; 0x01
 148:	9a 81       	ldd	r25, Y+2	; 0x02
 14a:	83 30       	cpi	r24, 0x03	; 3
 14c:	91 05       	cpc	r25, r1
 14e:	2c f3       	brlt	.-54     	; 0x11a <main+0x88>
 150:	1a 82       	std	Y+2, r1	; 0x02
 152:	19 82       	std	Y+1, r1	; 0x01
 154:	1b c0       	rjmp	.+54     	; 0x18c <main+0xfa>
 156:	a8 e3       	ldi	r26, 0x38	; 56
 158:	b0 e0       	ldi	r27, 0x00	; 0
 15a:	23 e0       	ldi	r18, 0x03	; 3
 15c:	30 e0       	ldi	r19, 0x00	; 0
 15e:	89 81       	ldd	r24, Y+1	; 0x01
 160:	9a 81       	ldd	r25, Y+2	; 0x02
 162:	f9 01       	movw	r30, r18
 164:	e8 1b       	sub	r30, r24
 166:	f9 0b       	sbc	r31, r25
 168:	cf 01       	movw	r24, r30
 16a:	9c 01       	movw	r18, r24
 16c:	22 0f       	add	r18, r18
 16e:	33 1f       	adc	r19, r19
 170:	ce 01       	movw	r24, r28
 172:	01 96       	adiw	r24, 0x01	; 1
 174:	82 0f       	add	r24, r18
 176:	93 1f       	adc	r25, r19
 178:	fc 01       	movw	r30, r24
 17a:	3a 96       	adiw	r30, 0x0a	; 10
 17c:	80 81       	ld	r24, Z
 17e:	91 81       	ldd	r25, Z+1	; 0x01
 180:	8c 93       	st	X, r24
 182:	89 81       	ldd	r24, Y+1	; 0x01
 184:	9a 81       	ldd	r25, Y+2	; 0x02
 186:	01 96       	adiw	r24, 0x01	; 1
 188:	9a 83       	std	Y+2, r25	; 0x02
 18a:	89 83       	std	Y+1, r24	; 0x01
 18c:	89 81       	ldd	r24, Y+1	; 0x01
 18e:	9a 81       	ldd	r25, Y+2	; 0x02
 190:	83 30       	cpi	r24, 0x03	; 3
 192:	91 05       	cpc	r25, r1
 194:	04 f3       	brlt	.-64     	; 0x156 <main+0xc4>
 196:	80 e0       	ldi	r24, 0x00	; 0
 198:	90 e0       	ldi	r25, 0x00	; 0
 19a:	65 96       	adiw	r28, 0x15	; 21
 19c:	0f b6       	in	r0, 0x3f	; 63
 19e:	f8 94       	cli
 1a0:	de bf       	out	0x3e, r29	; 62
 1a2:	0f be       	out	0x3f, r0	; 63
 1a4:	cd bf       	out	0x3d, r28	; 61
 1a6:	df 91       	pop	r29
 1a8:	cf 91       	pop	r28
 1aa:	08 95       	ret

Exercise for Students

Recompile the same program with the highest level of optimization (-0s) and see how things change. Is this what you would expect?