Bruce Cannon wrote: > Thanks Al! > > I still don't get two things: > > 1. In you last comment about CALLing a label without '#', do you mean that > DO_THIS is then understood to be a label for a number which is an address > to a memory location which in turn contains the address of the subroutine? > > And also: > > 2. Why do we need to write > > jmp DoThis In this case the JMP destination is an offset from the current PC, a single word operabd is used. Hence the net effect of the JMP instruction is MOV DoThis(PC),PC However that isn't strictly true, since the PC has been incremented, and, for compactness, DoThis is actually stored in the operand as a word offset, ie half the actual byte offset. Then the real effect is as follows:- MOV DoThis(PC),PC+2 If you try and decode this from the operand you must calculate the follwing:- PC = PCold + 2 + OFFSEt * 2 Where the value OFFSET is stored in the last 12 bits of the operand. > > but > > call #DoThis The CALL instruction here is using the absolute addressing mode, whereby The address of DoThis is stored in the operand. In fact CALL DoThis is also valid, but would be used for accessing a table of functions perhaps, when the address stored in the operand would be the contents of the address DoThis(PC+2) SLAUE10B Appendix B page 19 shows all the different addresssing mode results for the CALL instruction. There you go, all done, and no need to buy a book ;@} Cheers Al
Info on assembler syntax
Started by ●September 13, 2003
Reply by ●September 16, 20032003-09-16
Reply by ●September 16, 20032003-09-16
> >A good question - it's an inconsistency in the syntax - if I
had
designed it,
> >I would have made call the same as jmp, and
used something like
> >
> > call @fptr
> >
> >for indirect function calls.
> >...
>
> IMHO, I think it's a mistake. This means you cannot have PC relative
calls.
I don't think that's true. According to the Users' Guide
(SLAU049C),
you can get a PC-relative call with `call LABEL'. This works
correctly with the GNU assembler; do other assemblers disallow it?
Noah
Reply by ●September 16, 20032003-09-16
On Tue, 16 Sep 2003 17:59:37 -0000, Noah wrote:
>> >A good question - it's an
inconsistency in the syntax - if I had
>designed it,
>> >I would have made call the same as jmp, and used something like
>> >
>> > call @fptr
>> >
>> >for indirect function calls.
>> >...
>>
>> IMHO, I think it's a mistake. This means you cannot have PC
relative
>calls.
>
>I don't think that's true. According to the Users' Guide
(SLAU049C),
>you can get a PC-relative call with `call LABEL'. This works
>correctly with the GNU assembler; do other assemblers disallow it?
There isn't a single instruction on the MSP430 which yields a PC
relative call behavior. I think it was a sad oversight on their
part (or Horst Diewald's part.)
It takes 7 cycles, 4 instruction words, and a spare register for
computation in order to make a PC-relative function call. It's
possible that GNU assembler hides these details, but I'm curious
just how they would handle selecting the spare register, if so.
Chapter 9 of the MSP430 Application Report Book discusses how to
code PC-relative calls, this way:
MOV PC, Rn ; Address SC+2 > Rn
ADD #SUBR$, Rn ; Add offset (SUBR (SC+2))
CALL Rn ; SC+2+SUBR(SC+2)) = SUBR
As you can see, this uses 4 words, 7 cycles, and scratches a
register.
I believe there would have been nothing lost and everything
gained if TI's designer(s) had backed off by one level of
indirection in the case of the CALL instruction.
Jon
Reply by ●September 17, 20032003-09-17
--- In msp430@msp4..., Jonathan Kirwan <jkirwan@e...> wrote:
> It takes 7 cycles, 4 instruction words, and a
spare register for
> computation in order to make a PC-relative function call. It's
> possible that GNU assembler hides these details, but I'm curious
> just how they would handle selecting the spare register, if so.
You're quite right. And the GNU assembler doesn't hide any details.
I was just confused about the semantics of `call LABEL'.
Noah
Reply by ●September 17, 20032003-09-17
nOT BEING ONE TO BE CONTROVERSIAL OR ANYTHING ;@}. But I don't see
what
all the fuss is about, frankly I've never missed it. The current
implementation of CALL LABEL produces a call to the address at the
contents of address LABEL, neat! easy to undertsand an dvery useful.
two instances, one where a machine might require field upgrades, or
where the same machine might have multiple personalities depending on
who the client is. In this case LABEL might be in data flash, so by
simply compiling with different subroutine names/addresses at this
location we have a universal program with split personalities. Or a
system that can be upgraded, leaving a comms core behind that always
re-enters the new version of the program with CALL NEWPROG. This gets
around a lot of the constraints you often ghave to meet with field
upgrading software. You often end up having to fix a lot of entry and
exit points. This method re-enters run time code through a single
address, whose contents are re-programmable, and exits to upgrade mode
using a simple RET to the protected (hopefully) software in the upgrade
procedures.
Even more useful than that perhaps. If now LABEL is a RAM address we
have a very simple way of executing task lists, priority scheduling etc.
I can't think why I might HAVE to use PC relative addressing, when there
might be other options. In fact it is something I've rarely used for any
instructions on any micro.
The anomolous operation isn't in fact with the way CALL works, it works
the same way that MOV LABEL,r4 works. It is JMP LABEL that appears to
have the wrong syntax, in fact all of the jump instructions only have PC
relative addressing, totally contrary to the syntax for all other
instructions. I bemoan the loss of other addressing modes for jumps
rather than the omission of a dubious PC relative call. I mean JMP
#LABEL is how it appears to work right now, but JMP (LABEL) (the default
syntax for other isntrcution sis indirect addresssing) would be useful,
as would JMP Rn, JMP @Rn etc without having to jump ;^) through hoops to
achieve the same effect, as in ADD LABEL,PC, or ADD &LABEL,PC, or ADD
#LABEL,PC, or ADD @R5+,PC. These are PC relative jumps, in effect, with
out the range limit.
Perhaps I'm just warped and twisted, or maybe it's because I never had
to suffer the PDP11 ;@}
Al
Jonathan Kirwan wrote:
> On Tue, 16 Sep 2003 17:59:37 -0000, Noah wrote:
>
>
>>>>A good question - it's an inconsistency in the syntax - if
I had
>>
>>designed it,
>>
>>>>I would have made call the same as jmp, and used something like
>>>>
>>>> call @fptr
>>>>
>>>>for indirect function calls.
>>>>...
>>>
>>>IMHO, I think it's a mistake. This means you cannot have PC
relative
>>
>>calls.
>>
>>I don't think that's true. According to the Users' Guide
(SLAU049C),
>>you can get a PC-relative call with `call LABEL'. This works
>>correctly with the GNU assembler; do other assemblers disallow it?
>
>
> There isn't a single instruction on the MSP430 which yields a PC
> relative call behavior. I think it was a sad oversight on their
> part (or Horst Diewald's part.)
>
> It takes 7 cycles, 4 instruction words, and a spare register for
> computation in order to make a PC-relative function call. It's
> possible that GNU assembler hides these details, but I'm curious
> just how they would handle selecting the spare register, if so.
>
> Chapter 9 of the MSP430 Application Report Book discusses how to
> code PC-relative calls, this way:
>
> MOV PC, Rn ; Address SC+2 > Rn
> ADD #SUBR$, Rn ; Add offset (SUBR (SC+2))
> CALL Rn ; SC+2+SUBR(SC+2)) = SUBR
>
> As you can see, this uses 4 words, 7 cycles, and scratches a
> register.
>
> I believe there would have been nothing lost and everything
> gained if TI's designer(s) had backed off by one level of
> indirection in the case of the CALL instruction.
>
> Jon
>
>
> .
>
>
>
> ">http://docs.yahoo.com/info/terms/
>
>
>
Reply by ●September 17, 20032003-09-17
On Wed, 17 Sep 2003 17:06:41 +0930, Al wrote: >nOT BEING ONE TO BE CONTROVERSIAL OR ANYTHING ;@}. But I don't see what >all the fuss is about, frankly I've never missed it. The current >implementation of CALL LABEL produces a call to the address at the >contents of address LABEL, neat! easy to undertsand an dvery useful. Oh, Al. Don't you remember the days, toggling in the code where ever you could fit it, your calluses rubbing a little sore from the toggling? And if its not position independent and you started off wrong by one, you get to toggle it all in again? And, of course, it's easier to memorize a block of binary code than to have to keep the nasty little fields in your head as you hand toggle it in. Hehe. >two instances, one where a machine might require field upgrades, or >where the same machine might have multiple personalities depending on >who the client is. In this case LABEL might be in data flash, so by >simply compiling with different subroutine names/addresses at this >location we have a universal program with split personalities. Or a >system that can be upgraded, leaving a comms core behind that always >re-enters the new version of the program with CALL NEWPROG. This gets >around a lot of the constraints you often ghave to meet with field >upgrading software. You often end up having to fix a lot of entry and >exit points. This method re-enters run time code through a single >address, whose contents are re-programmable, and exits to upgrade mode >using a simple RET to the protected (hopefully) software in the upgrade >procedures. > >Even more useful than that perhaps. If now LABEL is a RAM address we >have a very simple way of executing task lists, priority scheduling etc. > >I can't think why I might HAVE to use PC relative addressing, when there >might be other options. In fact it is something I've rarely used for any >instructions on any micro. But there is a use for PIC (position independent code) or two, perhaps. Add-in extension routines may be downloaded from RS-232 and placed in the next available slot, and the assembler won't know where that is. They access the target O/S via absolute addressing, but access their own subroutines via PIC. I'm sure I could cobble up some other reasons, too. You are just too used to compile-and-burn mode. ;) >The anomolous operation isn't in fact with the way CALL works, it works >the same way that MOV LABEL,r4 works. I completely understand that, Al. It basically means that they didn't think beyond what they were already doing, long enough to realize a quick 'mind shift' would have made a useful address mode out of a useless one. >It is JMP LABEL that appears to >have the wrong syntax, in fact all of the jump instructions only have PC >relative addressing, totally contrary to the syntax for all other >instructions. I bemoan the loss of other addressing modes for jumps >rather than the omission of a dubious PC relative call. I mean JMP >#LABEL is how it appears to work right now, but JMP (LABEL) (the default >syntax for other isntrcution sis indirect addresssing) would be useful, >as would JMP Rn, JMP @Rn etc without having to jump ;^) through hoops to >achieve the same effect, as in ADD LABEL,PC, or ADD &LABEL,PC, or ADD >#LABEL,PC, or ADD @R5+,PC. These are PC relative jumps, in effect, with >out the range limit. Too wrapped up in the assembler stuff, Al. I'm thinking machine code and you are thinking assembler, here. >Perhaps I'm just warped and twisted, or maybe it's because I never had >to suffer the PDP11 ;@} hehe. You wouldn't consider it suffering, Al. I guarantee you that with a couple of adjustments on the MSP430 architecture by little ole me and you'd be even more pleased with the result. You'd never look back on any facet of it. (And I wouldn't use a single additional inverter or transmission gate to get there.) :) Jon
Reply by ●September 17, 20032003-09-17
Jonathan Kirwan wrote: > On Wed, 17 Sep 2003 17:06:41 +0930, Al wrote: > > >>nOT BEING ONE TO BE CONTROVERSIAL OR ANYTHING ;@}. But I don't see what >>all the fuss is about, frankly I've never missed it. The current >>implementation of CALL LABEL produces a call to the address at the >>contents of address LABEL, neat! easy to undertsand an dvery useful. > > > Oh, Al. Don't you remember the days, toggling in the code where > ever you could fit it, your calluses rubbing a little sore from > the toggling? And if its not position independent and you > started off wrong by one, you get to toggle it all in again? > And, of course, it's easier to memorize a block of binary code > than to have to keep the nasty little fields in your head as you > hand toggle it in. > > Hehe. I don't know about that. All my early stuff was hand keyed, but very early on the Army paid for about 500 xeroxed sheets of programming papaer. I basically designed a format that let me easily calculate the binaries for each instruction. Again, perhaps my early designs were too crude, but, although the address was set to autoincrement after each entry I also had address increment and decrement buttons (incidentally the mechanism that taught me the hard way about debouncing), so it was easy to correct a mistake. Of course you had to spot it, but hey, debugging was fun. You could also read back the memory contents from 0000, That was my A#1 debug tool!! later, when I moved to mainframes there were banks of piano key toggle switches for program and data entry, but I never even contemplated meorising other than the very few main operands, the rest was just a case of knowing the bit-fields, which was the bit I found easy. > > >>two instances, one where a machine might require field upgrades, or >>where the same machine might have multiple personalities depending on >>who the client is. In this case LABEL might be in data flash, so by >>simply compiling with different subroutine names/addresses at this >>location we have a universal program with split personalities. Or a >>system that can be upgraded, leaving a comms core behind that always >>re-enters the new version of the program with CALL NEWPROG. This gets >>around a lot of the constraints you often ghave to meet with field >>upgrading software. You often end up having to fix a lot of entry and >>exit points. This method re-enters run time code through a single >>address, whose contents are re-programmable, and exits to upgrade mode >>using a simple RET to the protected (hopefully) software in the upgrade >>procedures. >> >>Even more useful than that perhaps. If now LABEL is a RAM address we >>have a very simple way of executing task lists, priority scheduling etc. >> >>I can't think why I might HAVE to use PC relative addressing, when there >>might be other options. In fact it is something I've rarely used for any >>instructions on any micro. > > > But there is a use for PIC (position independent code) or two, > perhaps. Add-in extension routines may be downloaded from > RS-232 and placed in the next available slot, and the assembler > won't know where that is. They access the target O/S via > absolute addressing, but access their own subroutines via PIC. > I'm sure I could cobble up some other reasons, too. > > You are just too used to compile-and-burn mode. ;) I don't work that way necessarily, My code doesn't have holes in it except explicit holes designed for bolt in routines. Since the address of these is jknown it's simply enough to set an ORG and compile. I rarely have to upgrade in bits at a time. Most upgrades I do are either trivial, or major overhauls. > > >>The anomolous operation isn't in fact with the way CALL works, it works >>the same way that MOV LABEL,r4 works. > > > I completely understand that, Al. It basically means that they > didn't think beyond what they were already doing, long enough to > realize a quick 'mind shift' would have made a useful address > mode out of a useless one. But I don't find it useless, far from it, I use it more than I have ever used a PC relative call. > > >>It is JMP LABEL that appears to >>have the wrong syntax, in fact all of the jump instructions only have PC >>relative addressing, totally contrary to the syntax for all other >>instructions. I bemoan the loss of other addressing modes for jumps >>rather than the omission of a dubious PC relative call. I mean JMP >>#LABEL is how it appears to work right now, but JMP (LABEL) (the default >>syntax for other isntrcution sis indirect addresssing) would be useful, >>as would JMP Rn, JMP @Rn etc without having to jump ;^) through hoops to >>achieve the same effect, as in ADD LABEL,PC, or ADD &LABEL,PC, or ADD >>#LABEL,PC, or ADD @R5+,PC. These are PC relative jumps, in effect, with >>out the range limit. > > > Too wrapped up in the assembler stuff, Al. I'm thinking machine > code and you are thinking assembler, here. Really the same thing at the end of it, and it is at the machine code level that the micro ended up flawed, and at the assembler level that compensation must be made. It seems that the designers were either overwhelmed by the desire for a large jump range, or underwhelmed by too much schnapps. The basic JMP and condition codes require only 6 bits, the remaining 10 bits have all been assigned as WORD OFFSET, that really shows how befuddled they might have been. How deviant, Now the assemblers task is even quirkier, and it almost precludes the use of the MSPs conventional syntax, since the value fields there are 'natural', that is the value generated by the assembler is the absolute value implied by the source code, MOV #1234H sees the value 1234H in the second word of the operand, MOV 1234H sees the MOV indirect opcode appear in the first word of the operand, and the offset to the address 1234H appear in the second word. Only the jumps differ in this respect, and I think it was a kludgy design to avoid a short jmp, and to give jmp a longer range, therefore I am suggesting that the designers required extra, and perhaps dedicated jmp processing hardware. I did start tracking the instruction set decode mechanism some months back (I was laid up and had nothing better to do) and IIRC I came to the conclusion then that the designers had kludged the jump, but don't remember where I went after that. Had they maintained the the conventional format of the instruction set they woudl have ended up with 8 variants of jump, with an offset of just 256 bytes, not convenient when using word addresses, since -128 /+127 sort of becomes restrictive, in reality a range of -64 to +62 instructions, with +127 being handled as a special case. It seems that rather than use a 2 word operand, and thus, presumably increase the number of clock cycles a jump required, they chose the klunky method we now know and love. On balance the two word operand jump would have been more flexible. In this case you could have taken several paths, perhaps steal 1 more bit to indicate a very short jump, as is extremely common in loops, with the address in the remaining 7 bits, or a very long jump using a second word. But then we don't need that, the BR emulated instruction can do that. The concern may simply have been to improve overall execution speeds, but in my experience JMP is mostly used to travel very short distances, and, certainly the places where shaving 2 instruction cycles off execution would nearly alwsy fit this case. So throw away the knlunky jump and revert IT rather than make another special case out of CALL. >>Perhaps I'm just warped and twisted, or maybe it's because I never had >>to suffer the PDP11 ;@} > > > hehe. You wouldn't consider it suffering, Al. I guarantee you > that with a couple of adjustments on the MSP430 architecture by > little ole me and you'd be even more pleased with the result. > You'd never look back on any facet of it. (And I wouldn't use a > single additional inverter or transmission gate to get there.) I had some experience with various MODCOMPs, which I was told were PDP based, didn't like tham 1 bit, but then us knuckle draggers are prone to be pedants. Cheers Al
Reply by ●September 17, 20032003-09-17
Jonathan Kirwan <jkirwan@jkir...> writes:
> Chapter 9 of the MSP430 Application Report Book
discusses how to
> code PC-relative calls, this way:
>
> MOV PC, Rn ; Address SC+2 > Rn
> ADD #SUBR$, Rn ; Add offset (SUBR (SC+2))
> CALL Rn ; SC+2+SUBR(SC+2)) = SUBR
>
> As you can see, this uses 4 words, 7 cycles, and scratches a
> register.
There is an alternative way. If you perform the call like the
following:
PUSH PC # 2 bytes
ADD.W #foo-($+4), PC # 4 bytes
And the return:
ADD.W #0x4, 0(SP) # 4 bytes
RET
Then you will get a slightly better result. At first sight it looks
like this is more expensive, but in real life it isn't. Why? Well,
because most applications will tend to have a lot more call points
than returns. In this case we will gain two bytes on each call point,
which makes up for the four bytes we lose at each return. In
addition, we doesn't have to worry about allocating the extra register
Rn that the TI code requires.
This, by the way, is what the position independent code model in the
IAR compiler uses.
-- Anders
Disclaimer: Opinions expressed in this posting are strictly my own and
not necessarily those of my employer.