Checking assembly listing, why call main ?

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am checking the assembly listing of my C program and I noticed that there is a call to main. Why doesn't the compiler just do a jump to main?

This looks like a waste of stack...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can think of two things:

For safety. Every once in a while there is a person that returns from main, and that currently leads into an infinite loop. It used to cause code to restart, but people got confused when code ran infinitely even though they thought the code is run once only.

And because that is the way it is always done, main is a function like everything else. You can have initialization functions that get executed before main as well. Perhaps you can have your own termination routines that get executed after main as well, like going into a bootloader or something.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually, the compiler does not call main; it's written in the startup code from avr-libc.

You could use your own startup code alongside with -nostartfiles.

Even in the current setup the code might be executed multiple times: after main when _exit is called, there is a CLI and a infinit loop. So if the WDT is on it will reset the machine and restart the application.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
__attribute__((OS_main)) int main (void) {

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

__attribute__((OS_main)) int main (void) {

That won't change it because main still gets called from startup code in section .init9.

OS_main will reduce the prologue/epilogue overhead inside main but it has no effect on the caller of main.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a question here. Is there any functions which can be defined and will be called in the startup code by the GCC itself before main is called.
I guess i have seen a function called __low_level_init() in some other compiler which when defined by user ,will be called before main in the startup code.

-Krishna Balan S

-------------------------------------------------------------------------

"Heroes are ordinary people with extraordinary commitment"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

krishnabalan wrote:
Is there any functions which can be defined and will be called in the startup code by the GCC itself before main is called.
http://www.nongnu.org/avr-libc/user-manual/mem_sections.html
Paragraph "The .initN Sections"

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

OS_main will reduce the prologue/epilogue overhead inside main but it has no effect on the caller of main.

But it quells all the push/pops - surely that's what OP wants? Here's an example. First without OS_main:

/*__attribute__((OS_main))*/ int main (void) {
  ca:	2f 92       	push	r2
  cc:	3f 92       	push	r3
  ce:	4f 92       	push	r4
  d0:	5f 92       	push	r5
  d2:	6f 92       	push	r6
  d4:	7f 92       	push	r7
  d6:	8f 92       	push	r8
  d8:	9f 92       	push	r9
  da:	bf 92       	push	r11
  dc:	cf 92       	push	r12
  de:	df 92       	push	r13
  e0:	ef 92       	push	r14
  e2:	ff 92       	push	r15
  e4:	0f 93       	push	r16
  e6:	1f 93       	push	r17
  e8:	cf 93       	push	r28
  ea:	df 93       	push	r29

#ifdef __AVR_ATmega168__
	UBRR0L = 51; // 9600 @ 8MHz
	UCSR0B = (1<<TXEN0); // only using it as output debug channel
#else
	UBRRL = 51; // 9600 @ 8MHz
  ec:	83 e3       	ldi	r24, 0x33	; 51
  ee:	89 b9       	out	0x09, r24	; 9

then with:

__attribute__((OS_main)) int main (void) {
000000ca 
: #ifdef __AVR_ATmega168__ UBRR0L = 51; // 9600 @ 8MHz UCSR0B = (1<<TXEN0); // only using it as output debug channel #else UBRRL = 51; // 9600 @ 8MHz ca: 83 e3 ldi r24, 0x33 ; 51 cc: 89 b9 out 0x09, r24 ; 9

The actual CALL/RET pales into insignificance against this.

(OP is trying to make a "tight" bootloader)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

krishnabalan wrote:
Is there any functions which can be defined and will be called in the startup code by the GCC itself before main is called.
You can put a finction into an init-Section like so:
// !!! Do never call this function         !!!
// !!! The Linker knows what to do with it !!!
void __attribute__ ((naked, section (".init8")))
init_before_main (void) 
{
   // code
}

You will have to get familiar with init-Sections and the restrictions on the code you put there.

A second way is using a constructor:

void __attribute__ ((constructor))
run_prior_to_main (void) 
{
   // code
}

FYI, I attached a C-file to setup stdio so that I can use plain vanilla C on AVR, e.g. run code like

#include 

int main()
{
    printf ("Hallo Welt!\n");

    return 0;
}

on AVR. (Cum granum salis; if a WDT is on you will have to do a bit more to regurarly feet it (ISR) and implement your own exit()). But all goes fine without bothering the main C file(s).

clawson wrote:
SprinterSB wrote:
OS_main will reduce the prologue/epilogue overhead inside main but it has no effect on the caller of main.
But it quells all the push/pops - surely that's what OP wants? [...] The actual CALL/RET pales into insignificance against this.
You'r definitely better in reading from crystal balls I think ;-)

Can you (ar anybody else) imagine a situation where adding OS_main to main would be malicious?

If yes, what would be such a situation? I don't know rtems, Ada or Objective-C.

If no, it might be profitable to do that magic in the compiler already if optimization is on alongside with a switch to turn it off.

Attachment(s): 

avrfreaks does not support Opera. Profile inactive.

Last Edited: Tue. Aug 2, 2011 - 07:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Can you (ar anybody else) imagine a situation where adding OS_main to main would be malicious?

When the program calls main() recursively? (this is the argument proffered every time someone asks why main() is CALL'd not JMP'd). Now if anyone has ever actually seen a program where main() is used recursively I'll eat my hat!
Quote:
If no, tt might be profitable to do that magic in the compiler already if optimization is on alongside with a switch to turn it off.

As such that'd be brilliant. Also if there were some way to not throw a warning when main() was declared void without forcing the use of -free-standing that'd be equally great as these two things are a rod that avr-gcc is often beaten with by other (dedicated AVR) compiler users.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

... a rod that avr-gcc is often beaten with by other (dedicated AVR) compiler users.

:twisted:
https://www.avrfreaks.net/index.p...
https://www.avrfreaks.net/index.p...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thought a bit more about it and came to the conclusion that adding OS_foo attribute automatically (even if it can be disabled by option) is a bad idea.

For example an embedded OS could provide it's own startup code and you simply link your program against the OS' libs with -nostartfiles thd they call main as a task. Bang.

So if one don't use features to tweak code, no one should complain about a wasted byte here or there. The only thing that' to be blamed is GCC's documentation because it doesn't tell a word about OS_foo (PR49824).

As for warnings with void main() jsut read the diagnostic

main.c:1:6: warning: return type of 'main' is not 'int' [-Wmain]

and you'll find -Wno-main.

int main does not hurt at all as you have an infinite loop at it's end or call a function attributed noreturn and the code behind that is dead, anyway.

When I started with avr-gcc I wasted hours to get rid of these two bytes... Don't waste your time on this ridiculous two bytes that won't show up with a proper program, anyway. It's just the usual boah-I-discovered-the-compiler-doing-suboptimal-code-and-that-makes-me-feel-so-smart-thing.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Don't waste your time on this ridiculous two bytes that won't show up with a proper program, anyway.

If indeed the intent is to make a small bootloader, then I have no problems with micro-tweaking. A few words here, a few words there, ...

But indeed, if doing the detailed work then tweak the startup file(s) to your needs.

[A trivia question, semi-OT: If doing the bootloader, must one have main()? Or can it be myboot()?

Another semi-related: If one is doing the tight bootloader and there are a handful of warnings and the developer understands what is being complained about and wants to live with them, then what's the big deal? I suppose one could be part of a "no warnings allowed" shop...]

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

[A trivia question, semi-OT: If doing the bootloader, must one have main()? Or can it be myboot()?


Default CRT calls main()/main: but with -nostartfiles there is no CRT and the first linked file is located at .org 0 so the "entry" can be called whatever you like (just like Atmel assembler)

And yes, as long as one understands that warnings are benign they can be ignored.