Confused over PIN behavior.

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

 

Hi,  I am finding side-effects to PIN values that confuse me.  I'm avr noob with c/c++ sw background.

 

Set-up:

atmega328b in arduino body,  En-reset clipped.

AS7 attached to ICE attached to Arduino ISP

using DebugWire

 

I am trying to get PORTB and PORTD into a zero'd out state at application init.  I'd like DDRx, PORTx, and PINx to be all 0'd.

 

 

I have an InitPorts function, called first thing from main(). 

 

On function entry, AS7 debugging shows the following, Note that PINB is not entirely 0'd

 

So, I try to do the following:

 

 

1)  DDRB = 0xFF;    // enable output on all pins,  and also set all values on PORTB to 0

result:

-- cool, does what I expected, also clears PINB.  But bc I want to start with pins config'd for Input by default, I do...

 

2) DDRB = 0;

result:

-- not what i expected.  cleared direction, yeah, but now some Pins are non-zero.

 

 

As noted, I'm noobing.   Are the pins floating?  Is the Debugger reliable?  If I really want to have this initial state, do I need external pull down resistors on the pins? 

 

Thanks. O

 

 

 

 

 

 

This topic has a solution.
Last Edited: Tue. May 19, 2020 - 08:12 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

oflatley wrote:
Are the pins floating
This.

 

With DDRxn at '0', the pin is an input.  If PORTxn is also '0', the pull-up is disabled, so the pin floats.  Then PINxn will reflect the instantaneous state of the pin, subject to whatever voltage is decides to take on from the environment.

 

If you want them to be inputs, but hold a '0' state absent external drive, you'll need a weak pull-down resistor.  Unfortunately the atmega328p (not the atmega328b, which doesn't exist... did you mean the atmega328pb?) doesn't have internal pull-downs, only internal pull-ups.  So if you really need a pull-down you'll have to wire one up externally.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

oflatley wrote:
I'd like DDRx, PORTx, and PINx to be all 0'd.
Just to note that is exactly what you get when power is applied to the AVR in the first place. 

 

As Joey says this makes all pins high-Z (floating) inputs, no pull-ups which means that "PIN" is indeterminate if the external electronics has not been designed to hold it in some designed state.

Last Edited: Tue. May 19, 2020 - 08:07 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you @joey and clawson

 

I put a scope on the pins and convinced myself that the debugger was correct, which is a point of sanity.    So, yeah, it's pretty obvious to me now what happens when you set an undriven pin into input mode -- what the docs call 3-state.  I slapped a resistor on the pin to ground, and yeah, that reinforced my learning. 

 

I am working to fit a new piece into an existing motorcycle -- actually to replace the OEM dash (which serves as k-line master) .  I snooped the protocol and know what I want to do -- it's just some of the start up logic was non-obvious to my inner-noob.  I'll get it though -- it's 'fun' and 'educational'.  

 

 

 

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

And yeah, I meant 328p -- this started as an arduino project. Then I wanted total control and transparency.

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

clawson wrote:

oflatley wrote:
I'd like DDRx, PORTx, and PINx to be all 0'd.
Just to note that is exactly what you get when power is applied to the AVR in the first place.

 

But a lot happens between power-on and main(), no?  There's some lower-level code stub which calls main(), yeah?

 

Are you guaranteed any state at the the entry to main? Is so, what?  Link to docs?

 

Thanks

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

>Just to note that is exactly what you get when power is applied to the AVR in the first place.

 

Except for PINx, which is unknown. I'm sure that was just a slip of the keyboard including PINx.

 

 

>Are you guaranteed any state at the the entry to main

 

The registers have a reset value. If you lookup the PINx register in the datasheet, you will find an x as the reset value (unknown), which makes sense as PINx is an input and its state is unknown (both the actual pin and the PINx register, which should be the same). You are making it a known state with the pulldown. DDRx and PORTX are known states at reset because they do not depend on anything external.

 

Most peripheral registers have a known reset state (any reset), a few (or very few) have an unknown state like PINx and the reset flags register. They then take on the property of inertia, and remain in the same state until acted on by an external force- writing a value to its register, internal hardware causing a change, etc. This also means from reset to main, unless some force acted on the register, it is still at its reset value when you get to main.

 

So as Cliff pointed out, PORTx and DDRx are 0 after reset (reset value), so if you want them 0, there is nothing to do. Most startup code before main (not produced by you) will not be setting peripheral registers, so you can count on registers being in reset state when you get to your code. There may be rare exceptions, but will mostly also require you to be involved (watchdog things, reset flags, that type of thing).

 

 

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

oflatley wrote:

But a lot happens between power-on and main(), no?  There's some lower-level code stub which calls main(), yeah?

 

Are you guaranteed any state at the the entry to main? Is so, what?  Link to docs?

Nothing touches any GPIO pin registers (DDR,PORT,PIN).

 

Depending upon how big your .bss and .data sections are, typical delay between the release from reset and entry to main is only a dozen or so cycles.  At 8 MHz, that's only a couple of microseconds.  Compared to the startup time from power-up to the release of reset (>65 ms), it is negligible.  Even if you've lots of .bss or .data, it can't be more than about 18k cycles, or about 2.5 ms @ 8 MHz.

 

If you need a known state during reset, then external pulling resistors are required.  All GPIO pins are tri-stated while in reset.  Nothing you can do about that.

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

oflatley wrote:

But a lot happens between power-on and main(), no?  There's some lower-level code stub which calls main(), yeah?

 

Are you guaranteed any state at the the entry to main? Is so, what?  Link to docs?

This will depend on your C compiler. There is a thing called the "C Run Time" ("CRT") that is built into each program that a compiler makes. It takes execution all the way from power on to the entry point of main() doing whatever is necessary to deliver the Cstandard/Kerninghan+Ritchie defined environment you might expect to have at the start of main().

 

The main(oof!) implication of that is that any initialised globals will already be holding the defined initial value by the time you enter main and any global/static that is not given a specific initial value is guaranteed to hold 0 (unless you are using a particularly strange TI compiler I once used!).

 

But that is all the CRT really has to do. It touches very little of the CPU specific electronics. Now in some chips (ARM with DRAM springs to mind) there are some very specific hardware operations that have to occur before you could set up initial variables. You have to be sure the DRAM will even hold what you write to it and for that you may need to initialise a DRAM refresh controller before you even start to copy/wipe variable contents. So I guess that is a case where CRT does a little more.

 

In the avr-gcc compiler specifically then if you build the very simplest program possible...

#include <avr/io.h>

int main(void) {
	// nothing to see here
}

then the bit supplied by the C compiler consists of:

00000000 <__vectors>:
   0:	09 c0       	rjmp	.+18     	; 0x14 <__ctors_end>
   2:	0e c0       	rjmp	.+28     	; 0x20 <__bad_interrupt>
   4:	0d c0       	rjmp	.+26     	; 0x20 <__bad_interrupt>
   6:	0c c0       	rjmp	.+24     	; 0x20 <__bad_interrupt>
   8:	0b c0       	rjmp	.+22     	; 0x20 <__bad_interrupt>
   a:	0a c0       	rjmp	.+20     	; 0x20 <__bad_interrupt>
   c:	09 c0       	rjmp	.+18     	; 0x20 <__bad_interrupt>
   e:	08 c0       	rjmp	.+16     	; 0x20 <__bad_interrupt>
  10:	07 c0       	rjmp	.+14     	; 0x20 <__bad_interrupt>
  12:	06 c0       	rjmp	.+12     	; 0x20 <__bad_interrupt>

00000014 <__ctors_end>:
  14:	11 24       	eor	r1, r1
  16:	1f be       	out	0x3f, r1	; 63
  18:	cf e9       	ldi	r28, 0x9F	; 159
  1a:	cd bf       	out	0x3d, r28	; 61
  1c:	02 d0       	rcall	.+4      	; 0x22 <main>
  1e:	04 c0       	rjmp	.+8      	; 0x28 <_exit>

00000020 <__bad_interrupt>:
  20:	ef cf       	rjmp	.-34     	; 0x0 <__vectors>

00000022 <main>:
#include <avr/io.h>

int main(void) {
	// nothing to see here
  22:	80 e0       	ldi	r24, 0x00	; 0
  24:	90 e0       	ldi	r25, 0x00	; 0
  26:	08 95       	ret

00000028 <_exit>:
  28:	f8 94       	cli

0000002a <__stop_program>:
  2a:	ff cf       	rjmp	.-2      	; 0x2a <__stop_program>

I highlighted the only bit you wrote. The rest you see here is the complete "CRT". At location 00000 there is a jump to skip over the interrupt vector table. While it's empty ("dead" links) the compiler always provides a complete vector table unless you tell it not to. That occupies 2: to 12:. Following this is the start of the real CRT. It clears the SREG register of the CPU. The main reason for this is to clear the I bit to ensure interrupts start out disabled. That happens in:

  14:	11 24       	eor	r1, r1
  16:	1f be       	out	0x3f, r1	; 63

There is a secondary reason for this. To make code more efficient it turns out the compiler often needs 0x00 to be able to use it for all sorts of things (this becomes evident in larger C programs) so the compiler has a design choice in that it tries to always ensure there is 0x00 in R1 so if it ever needs the value 0x00 it can just do a MOV from R1 instead of needing a CLR/LDI to prepare a register. So it not only clears SREG (IO location 0x3F) but at the same time it's now arranged for R1 to be pre-loaded with 0x00.

 

The next thing the CRT does is:

  18:	cf e9       	ldi	r28, 0x9F	; 159
  1a:	cd bf       	out	0x3d, r28	; 61

Now to guarantee my example had a very small interrupt vector table (just a handful of RJMPs) I chose to build for the ATtiny13 which has one of the lowest interrupt vector counts among all the AVRs but because it's a Tiny with less than 256 bytes of RAM this means the Stack Pointer can be kept in one byte so this code is loading 0x9F (address of the last byte of RAM) into R28 then writing that to the SPL register - the single stack pointer register used in this chip. C does this for all AVRs, even those that are known to preload SPL (and maybe also SPH) with the address of RAMEND automatically - it's kind of "belts and braces" to be sure the SP is set to the end of RAM.

 

Then the CRT does:

  1c:	02 d0       	rcall	.+4      	; 0x22 <main>

So that is it, complete job done. All the CRT stuff is now finished so all that remains is to call main() and now your C code can take over.

 

So that is it, what the CRT does (in avr-gcc) is:

 

1) jump over IVT

2) provide a bunch of JMPs to make the IVT

3) Clear R1 for future use

4) then use that to set SREG to be sure that I is not active

5) then load the value of RAMEND into some register(s)

6) and write that to the SPL/(SPH) locations

7) call main()

 

You may have spotted a handful of extra code there. I said it provides an interrupt vector table (IVT) and that consists of a bunch of JMPs but those jumps have to have somewhere to jump to. So the CRT also provides:

00000020 <__bad_interrupt>:
  20:	ef cf       	rjmp	.-34     	; 0x0 <__vectors>

So it provides a destination for the interrupt jumps so that in the absence of anything else they will at least do something predictable. What that something is is a jump to location 0. That will actually "reseet" the code but at least it may be a recognisable action (to highlight to the user that they made a mistake if they ever enable an interrupt vector without providing an ISR() to handle it.

 

Oh and finally the entry to main() is a CALL not a JMP. That means it can RETurn back (as my short example does) so there has to be something after the CALL main to catch this. What that is consists of a jump to something called "exit:" followed by "stop_program:"  and what they do in combination is to turn off interrupts (clear the I flag in SREG) and then sit in an infinite RJMP loop.

 

If I build a slight more complex program for a slightly larger AVR (ATmega328P: more interrputs and more RAM (so SP is bigger than 8 bits)) then the code looks like this:

#include <avr/io.h>

int foo = 12345;
char buff[10];

int main(void) {
	// nothing to see here
}

then now I get:

00000000 <__vectors>:
   0:	33 c0       	rjmp	.+102    	; 0x68 <__ctors_end>
   2:	00 00       	nop
   4:	4c c0       	rjmp	.+152    	; 0x9e <__bad_interrupt>
   6:	00 00       	nop
   8:	4a c0       	rjmp	.+148    	; 0x9e <__bad_interrupt>
   a:	00 00       	nop
   c:	48 c0       	rjmp	.+144    	; 0x9e <__bad_interrupt>
   e:	00 00       	nop
  10:	46 c0       	rjmp	.+140    	; 0x9e <__bad_interrupt>
  12:	00 00       	nop
  14:	44 c0       	rjmp	.+136    	; 0x9e <__bad_interrupt>
  16:	00 00       	nop
  18:	42 c0       	rjmp	.+132    	; 0x9e <__bad_interrupt>
  1a:	00 00       	nop
  1c:	40 c0       	rjmp	.+128    	; 0x9e <__bad_interrupt>
  1e:	00 00       	nop
  20:	3e c0       	rjmp	.+124    	; 0x9e <__bad_interrupt>
  22:	00 00       	nop
  24:	3c c0       	rjmp	.+120    	; 0x9e <__bad_interrupt>
  26:	00 00       	nop
  28:	3a c0       	rjmp	.+116    	; 0x9e <__bad_interrupt>
  2a:	00 00       	nop
  2c:	38 c0       	rjmp	.+112    	; 0x9e <__bad_interrupt>
  2e:	00 00       	nop
  30:	36 c0       	rjmp	.+108    	; 0x9e <__bad_interrupt>
  32:	00 00       	nop
  34:	34 c0       	rjmp	.+104    	; 0x9e <__bad_interrupt>
  36:	00 00       	nop
  38:	32 c0       	rjmp	.+100    	; 0x9e <__bad_interrupt>
  3a:	00 00       	nop
  3c:	30 c0       	rjmp	.+96     	; 0x9e <__bad_interrupt>
  3e:	00 00       	nop
  40:	2e c0       	rjmp	.+92     	; 0x9e <__bad_interrupt>
  42:	00 00       	nop
  44:	2c c0       	rjmp	.+88     	; 0x9e <__bad_interrupt>
  46:	00 00       	nop
  48:	2a c0       	rjmp	.+84     	; 0x9e <__bad_interrupt>
  4a:	00 00       	nop
  4c:	28 c0       	rjmp	.+80     	; 0x9e <__bad_interrupt>
  4e:	00 00       	nop
  50:	26 c0       	rjmp	.+76     	; 0x9e <__bad_interrupt>
  52:	00 00       	nop
  54:	24 c0       	rjmp	.+72     	; 0x9e <__bad_interrupt>
  56:	00 00       	nop
  58:	22 c0       	rjmp	.+68     	; 0x9e <__bad_interrupt>
  5a:	00 00       	nop
  5c:	20 c0       	rjmp	.+64     	; 0x9e <__bad_interrupt>
  5e:	00 00       	nop
  60:	1e c0       	rjmp	.+60     	; 0x9e <__bad_interrupt>
  62:	00 00       	nop
  64:	1c c0       	rjmp	.+56     	; 0x9e <__bad_interrupt>
	...

00000068 <__ctors_end>:
  68:	11 24       	eor	r1, r1
  6a:	1f be       	out	0x3f, r1	; 63
  6c:	cf ef       	ldi	r28, 0xFF	; 255
  6e:	d8 e0       	ldi	r29, 0x08	; 8
  70:	de bf       	out	0x3e, r29	; 62
  72:	cd bf       	out	0x3d, r28	; 61

00000074 <__do_copy_data>:
  74:	11 e0       	ldi	r17, 0x01	; 1
  76:	a0 e0       	ldi	r26, 0x00	; 0
  78:	b1 e0       	ldi	r27, 0x01	; 1
  7a:	ea ea       	ldi	r30, 0xAA	; 170
  7c:	f0 e0       	ldi	r31, 0x00	; 0
  7e:	02 c0       	rjmp	.+4      	; 0x84 <__do_copy_data+0x10>
  80:	05 90       	lpm	r0, Z+
  82:	0d 92       	st	X+, r0
  84:	a2 30       	cpi	r26, 0x02	; 2
  86:	b1 07       	cpc	r27, r17
  88:	d9 f7       	brne	.-10     	; 0x80 <__do_copy_data+0xc>

0000008a <__do_clear_bss>:
  8a:	21 e0       	ldi	r18, 0x01	; 1
  8c:	a2 e0       	ldi	r26, 0x02	; 2
  8e:	b1 e0       	ldi	r27, 0x01	; 1
  90:	01 c0       	rjmp	.+2      	; 0x94 <.do_clear_bss_start>

00000092 <.do_clear_bss_loop>:
  92:	1d 92       	st	X+, r1

00000094 <.do_clear_bss_start>:
  94:	ac 30       	cpi	r26, 0x0C	; 12
  96:	b2 07       	cpc	r27, r18
  98:	e1 f7       	brne	.-8      	; 0x92 <.do_clear_bss_loop>
  9a:	02 d0       	rcall	.+4      	; 0xa0 <main>
  9c:	04 c0       	rjmp	.+8      	; 0xa6 <_exit>

0000009e <__bad_interrupt>:
  9e:	b0 cf       	rjmp	.-160    	; 0x0 <__vectors>

000000a0 <main>:
int foo = 12345;
char buff[10];

int main(void) {
	// nothing to see here
  a0:	80 e0       	ldi	r24, 0x00	; 0
  a2:	90 e0       	ldi	r25, 0x00	; 0
  a4:	08 95       	ret

000000a6 <_exit>:
  a6:	f8 94       	cli

000000a8 <__stop_program>:
  a8:	ff cf       	rjmp	.-2      	; 0xa8 <__stop_program>

The stack setting now loads SPL and SPH with the value 0x08FF.

 

Some new code __do_copy_data has appeared to copy initial variable values from flash to RAM. That will write the 12345 value to my "foo" variable in RAM.

 

Also added is some __do_clear_bss code that will wipe my (uninitialised globals) globals. So that is going to write 0x00 to the ten bytes of my buff[] variable.

 

But all this is the "entire story". The hardware peripherals of the AVR are not touched in avr-gcc's version of the CRT. It doesn't enable/disable UARTs, it does not touch DDR/PORT/PIN registers to do anything on IO, it doesn't start timers or anything else along those line.

 

One thing you might find in the CRT of some other AVR C compilers are things like disabling the Watchdog Timer as soon as possible - that so that if it has just done a WDT reset and comes back to the start, even if the CRT spends time doing stuff (like data and bcsss loops) that the WDT won't "fire" again before it can reach main(). The avr-gcc CRT does not have code for this though it does have mechanisms (.init0 .. .init9) for users to insert "early" code if there is anything they think they need (in fact copy_data/clear_bss happen in .init4 so by placing things in .init0 .. .init3 it can be pre-empted).

 

EDIT: just to point out that in some systems (and Arduino is the classic example!) there may be a "bootloader" that runs at power on, that may do things like starting timers and enabling UARTs. The hope is that by the time it decides to jump into your "application" it will have put everything back to where it was at power on. But if not you need to take that up with the authors of the bootloader involved (a "good" bootloader will often end by forcing a watchdog reset that does put almost everything back to power on defaults before it jumps to the application)

Last Edited: Wed. May 20, 2020 - 02:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Very nice explanation!!

 

I wonder why they do a slightly obscure :

eor	r1, r1

rather than simply say clr r1  ?

 

Apparently they end up using the same resulting opcode, but saying clr would be more effective for the reader

I assume it's just an example of another way to skin the cat, unless another theory is proposed. 

 

edit: mention same opcode either way, but decode dein't check for clr case   

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. May 21, 2020 - 12:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is CLR R1. Just look at the opcode manual and the actual hex codes for each. This particular disassembler chooses to disassemble it as EOR.

 

Edit Top 6 bits 0010 01 etc.

 

I suppose that when a disassembler finds what looks like EOR but both rrrrr and ddddd are the same it could show CLR rrrrr but avr-objdump doesn't do that.

Last Edited: Wed. May 20, 2020 - 09:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

clawson wrote:
It is CLR R1.

Thank you, Cliff.  I was really starting to worry about the implications of the latest grand pronouncement.  Why didn't >>I<< think about decoding the instruction set a bit?  Why didn't >>I<< investigate the

...and the listing of the duplicates?  What about a chart of he numerical values of the op codes, and the "holes" for future instructions?  Shouldn't someone concerned with low-level stuff see if he could stand on the shoulders of the giants?

 

[edit]  Perhaps the wrong toolchain is being used...

                 
                 __RESET:
000041 94f8      	CLI
000042 27ee      	CLR  R30
000043 bbec      	OUT  EECR,R30
 ...

 

 

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.

Last Edited: Wed. May 20, 2020 - 09:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't have the first idea what you are rambling on about?!

 

avrcandies asked why EOR not CLR and I explained. Was there something technically wrong in that explanation?

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

  vrcandies asked why EOR not CLR and I explained. Was there something technically wrong in that explanation?

It was fine and superb.

 

I'd just prefer that if possible they show clr r23  since you smoothly read that as clearing r23.  When you see EOR r23, r23 you have to go, oh....what is that.....oh that's clearing r23.

I forgot the AVR has the funny muti way disassembly.  I certainly find it unappetizing for anyone or a compiler to write eor r18, r18  instead of clr r18

 

So , indeed they fake the clr at all times using eor xx, xx, but I'd prefer them to also reverse the fake!

 

If I say apple = 10   vs  apple =  (2*8+1)*(4-6) + 4*11  , I prefer the first.

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. May 21, 2020 - 12:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Was there something technically wrong in that explanation?

Of course not.  Read my post again, and I'll lay it out.

 

-- I have begun pointing out when the emperor has no clothes, in particular to off-shoot pronouncements by this member.

-- As you pointed out, it is the same.  As I tried to point out, if a member is that concerned about such detail, then I'd expect a little homework before the grand pronouncement.  Apparently no-one else agrees with that.

-- Then I went the step further, implying areas for future investigation before the next grand pronouncement.  As I recall, you were part of the "charting".

 

-- Now, in defense we learn that "they show clr ...".  The royal They?  Anyway, that defense, or further attack, totally ignored the "perhaps the wrong toolchain is being used", and example of such.  [Gee, I thought that with an open-source toolchain the purists could adjust it as desired]

 

You want the blunt summary:  Those that have the knowledge know that there are many many "same opcodes".  If you don't have the knowledge, fine.  And I ain't criticizing that.  What I am poking fun at is the hokey defenses. 

 

[edit] N.b. I don't really remember the source of the first offensive EOR post, but it doesn't matter.  A disassembler listing doesn't/can't know the context of which op code selection would not offend avrcandies.

 

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.

Last Edited: Thu. May 21, 2020 - 01:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No I didn't look up opcodes and had no reason to whatsoever, it was a simple observation:

 

If the opcodes are completely different, wouldn't one best select clr r23 instead of eor r23, r23 for the highest readability?  If not, they could

If the opcodes are completely the same, wouldn't one decode as clr r23 instead of eor r23, r23 for the highest readability?  If not, they could

 

There was no ulterior motive, though some may prefer to call the blood hounds.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

 and I'll lay it out.

Oh I see, this is all about some petty feud and making schoolyard jibes at one another. I'll leave you too your childish behaviour then. Have fun, though I'm sure it will eventually get stale.

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

clawson wrote:

oflatley wrote:

But a lot happens between power-on and main(), no?  There's some lower-level code stub which calls main(), yeah?

 

Are you guaranteed any state at the the entry to main? Is so, what?  Link to docs?

This will depend on your C compiler. There is a thing called the "C Run Time" ("CRT") that is built into each program that a compiler makes. It takes execution all the way from power on to the entry point of main() doing whatever is necessary to deliver the Cstandard/Kerninghan+Ritchie defined environment you might expect to have at the start of main().

 

@clawson -- Yeah, moons ago I remember stepping through the CRT the Borland compiler would generate for my student C programs.   The concepts are familiar:  but I very much appreciate you taking the time to lay that out.   It makes sense.

 

I do enjoy assembler -- I went down a weird 2-year long path when Borland released it's object oriented TASM.  I'll be interested in learning the patterns gcc uses for registers as I step through code.   Thanks again

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

I do enjoy assembler -- I went down a weird 2-year long path 

Assembler lets you fine tune things to make/ensure best use of processor tricks.  The runtime library sometimes uses assembly, since improvements to it can have a larger cascading effect, so you can get a lot of bang for the hassle of fiddling with asm.   

I remember using the Borland Turbo assembler way back when to handcraft some sprite graphics routines...after our tweaking they ran about 100x faster than the originals.  Back then we were impressed if we could rotate some scenes containing simple 3d objects & watch it repaint almost in real time.  

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!