This FAQ section deals with the GNU assembler. The assembler transforms your assembly source in an ELF object file which contains either 68HC11 or 68HC12 instructions.

How do I assemble a source file?
How can I migrate assembly sources to GNU as?
<< Install

Compiling >>

User Contributed Notes
Robert Goldsmith
03-Jul-2003 21:39
#9
A nice description on how to mix C, assembly and take care of some
issues
---------------------

Well, I have had a lot of support by email directly - so thank you everyone who emails suggestions :) Most of them did not post here to the group as well because they were sending bits of code as attachments (which would just clutter up everyone's inbox) or they were sending me code that is still in development and not released.

Still more of you seem to be interested in my progress as you wish to attempt the same - but, of course, have not received the emails i mentioned above! So, I thought I'd summarise what I now know, or think I know so those who want to can try and those who know better can point out my mistakes :) Sorry to everyone not interested in this as it is a long email but I did have 4 or 5 emails requesting I post this info...

Right, lets start with flow.

If you are wanting total control, you need your own crt0.s file. This is the 'boot' file, by tradition, and needs a few very important bits in it. First, in page0 (I'll expain this in a bit), you need space for gcc to swap in and out temporary data and it's 'virtual' z register so:

    .sect page0
_.tmp:
    .word 0
_.z:
    .word 0
_.frame:
    .word 0

(Don't worry, I will not be showing loads of code, just that in crt0.s)

Also needed in crt0.s is a place to start so:
    .text
    .global _start
;-----------------
; _start is where everything kicks off
;------------------
_start:
; do init style stuff needed before calling the 'main' function - such as setting up a stack pointer :)
; call user main routine
    jsr main

I also put the interrupt / reset vectors in here (in .sect vectors)

Now you have the reset vectors (just like you would in a normal asm file), the page0 setup and a starting point (dont forget to point the reset vector to _start) which does some low level init then calls your 'main' function. From now on, you can just code c like normal :)

My next big problem was variable names - as I am sure you have read in the emails :)

Ok, it seems you need to export them every different way you can think of and then the linker can find them :)

To export a symbol between asm files (and as the first stage in getting them into c), you need to make them global. To do this, use the .global directive:

    .global myLabelToExport

I figure it is sensible to put these at the top of the .s file :)

You don't need to export any local labels - such as subroutines you only need within this file or branch points local to the file. I have started naming any local label such as these with a starting underscore to show the difference. You don't need to specify which labels you are importing (say, from another file), only those you are exporting to other files.

that sorts out the asm - asm label sharing. c files need a bit more. For a c file to use the label, you need to tell the compiler that the linker will sort out the label matching so it should just accept the label is outside the file - by label, I mean variable name or function call. Further, you need to tell the compiler not to bother looking for the function referred to in any c files. To do this, as is normal with c, use the extern keyword.

For each of your asm file .global definitions that you wish to be available in c, you need a line like the following in a header file somewhere:

for a variable,
extern volatile unsigned char PORTA;

This means it is an unsigned char (1 byte), it is likely to change due to external influences (volatile) so don't try to optimise access to it and it is called PORTA. Easy really :)

for functions:
extern void buzzerTOC5isr();

functions need the extern - unlike normal c functions - to stop the c compiler complaining when it can't find the actual function in any of its files.

Not so hard after all :)


Lastly, memory management. You may have noticed the .text and .sect page0 style commands. These refer to either standard (.text, .data, .bss) or non standard memory sections or blocks. You can have control over these by creating a memory.x file and using the version of the linker control script that loads this file. For me, I need to set the linker to:
 -A,m68hc11elfb

notice the b at the end of the architecture - the 'b' file is the one that loads memory.x

memory.x itself is quite easy to understand and contains something like the following (posted so people can make comments on whether they think this is ok!):

MEMORY
{
  page0 (rw) : ORIGIN = 0x0, LENGTH = 0x0100
  ports(rw) : ORIGIN = 0x1000, LENGTH=0x003F
  expansion0(rw) : ORIGIN = 0x4000, LENGTH=0x1000
  expansion1(rw) : ORIGIN = 0x5000, LENGTH=0x1000
  expansion2(rw) : ORIGIN = 0x6000, LENGTH=0x1000
  motorsensor(rw) : ORIGIN = 0x7000, LENGTH=0x1000
  text (rx) : ORIGIN = 0x8000, LENGTH = 0x6000
  vectors(rwx) : ORIGIN = 0xBFC0, LENGTH = 0x0040
  data : ORIGIN = 0xE000, LENGTH = 0x1800

  }

each section has a mode (read, write, exec), a starting point and a length. So, page0 starts at memory address 0 and is 256 bytes long - it is the 'direct' memory space for the hc11.

I hope this is generally useful to everyone ! As you can see, I am not there yet for a fully working project port but, as this email is now long enough, questions come in the next email :)


Robert Goldsmith