Incrementing a variable in assembly

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

Incrementing a variable in assembly

跳至解决方案
6,712 次查看
meiermat
Contributor I

As a short background, I've only been using CodeWarrior 10.1 for a few days, and I'm still getting used to the quirks.

 

My problem is that I can't seem to increment a global variable.  I have a 1Hz timer interrupt set up.  I know it works, because I can add code to toggle an I/O pin and watch it on a scope, and I can set breakpoints in the code that do trigger during a debugging session.  However, the variable never increments.  I can load the variable into the accumulator, increment that, and then store it back, and that works fine.  To add further frustration, this EXCACT code sometimes builds fine, and sometimes gives me a warning at the INC instruction, A13003, that the value is being truncated.  That's odd to me, since it's only an 8-bit variable.

 

Any help is greatly appreciated.  I know this is a pretty remedial issue, and to be honest, I'm a bit embarassed that I haven't figured it out.  I attached the entire code.  The segment in question is the interrupt ISR for Timer 1 (TPM1_OVF_ISR).  The processor is the MC9S08DZ60.  I started the project using the BareBoard Project wizard.  Sorry I didn't just include it in the body; I couldn't get it to paste and be legible.

 

Thanks in advance,

 

Matt

标签 (1)
0 项奖励
回复
1 解答
5,223 次查看
rocco
Senior Contributor II

Hi Matt,

 

So it looks like your INC instruction was incrementing location $00 (an I/O port) instead of location $100. Glad you found it.

 

What we are doing differently is that I am writing relocatable assembly language, whereas you are writing absolute assembly language. So you are using ORGs and I am using SECTIONS. I only mentioned it so that you would know that I wasn't that familiar with absolute assembly.

 

You should just use "ORG Z_RAMStart", as you said. That appears to me to be the correct way for absolute assembly. Your understanding of page-zero being from $00 to $FF is correct. But I don't think you need the concept of page 1 or any other page. There is page-zero, and then there is everything else. That is all the silicon cares about.

 

The main advantage of relocatable assembly language is that you can make use of object-libraries. But there is more work involved, especially for the linker.

 

But to answer some of your "section" questions:

I use three "default" section statements a lot: BSCT (for page-zero data), DSCT (for non-page-zero data) and PSCT (for program instructions). I also create other sections, but 80% of my code is in those three.

 

When you declare a SECTION, you could explicitly make it refer to page-zero with the "short" keyword:

 

TableSct:  section   short

 

As for interrupt vectors, I've created a section called ".vect". Here is the code in the .asm file:

 

;;**********************************    ** Interrupt Vectors **    **********************************;;.vect: section  ;MC9S08gb60 Hardware Interrupt Vectors xdef vectors;;vectors: fdb IICnextPage ;Real-Time Interrupt vector  (Lowest Priority) fdb ICCservice ;IIC interrupt vector fdb Nope  ;ATD convertor interrupt vector fdb Nope  ;Keyboard interrupt vector fdb Nope  ;SCI2 Transmitter interrupt vector fdb Nope  ;SCI2 Receiver interrupt vector fdb Nope  ;SCI2 Error interrupt vector fdb Response ;SCI1 Transmitter interrupt vector fdb Command  ;SCI1 Receiver interrupt vector fdb CommErr  ;SCI1 Error interrupt vector fdb Nope  ;SPI interrupt vector fdb Overflow2 ;Timer 2 Overflow interrupt vector fdb Nope  ;Timer 2 Channel 4 interrupt vector fdb Nope  ;Timer 2 Channel 3 interrupt vector fdb ClinTrig ;Timer 2 Channel 2 interrupt vector fdb Temp1in  ;Timer 2 Channel 1 interrupt vector fdb Temp2in  ;Timer 2 Channel 0 interrupt vector fdb Overflow1 ;Timer 1 Overflow interrupt vector fdb Nope  ;Timer 1 Channel 2 interrupt vector fdb Nope  ;Timer 1 Channel 1 interrupt vector fdb Nope  ;Timer 1 Channel 0 interrupt vector fdb ICGintr  ;Internal Clock Generator interrupt vector fdb LVDintr  ;Low Voltage Detect interrupt vector fdb DSPintr  ;IRQ pin interrupt vector from DSP fdb Nope  ;Software interrupt vector fdb Boot  ;Reset vector    (Highest Priority)

 

And the it is placed at the appropriate addresses by the linker with these lines in the .prm file:

 

SEGMENTS   .   .   . Vectors = READ_ONLY 0xFFcc TO 0xFFff;   .   .   .ENDPLACEMENT   .   .   . .vect  INTO Vectors;   .   .   .END

 

在原帖中查看解决方案

0 项奖励
回复
8 回复数
5,223 次查看
rocco
Senior Contributor II

Hi Matt,

 

Welcome to the forum.

 

The code looks fine to me, but bugs often do. I think it may be a "build" problem.

 

I almost never use ORG statements (I use SECTION), so I assume the assembler knows that COUNTER is in page-zero from the value of "RAMstart". When using SECTION, the section would be explicitly defined as page-zero.

 

The INC instruction only works on variables in page-zero. The "Truncated" message that you are receiving is referring to the address of COUNTER, not the value of COUNTER. So that  message means that the assembler is assuming that COUNTER is not in page-zero.

 

But it is just a warning, so the code is created anyway. But if COUNTER is not in page-zero, then some address in page-zero is being incremented instead of COUNTER. That location would have the same low eight bits in its address. Your Load-Inc-Store approach works because it uses extended addressing and therefore is not limited to page-zero.

 

Take a look at the .map file, and maybe it will tell you what's wrong.

0 项奖励
回复
5,223 次查看
meiermat
Contributor I

You're right about the variable loction.  Its absolute address in RAM is $0100 (the definition of RAMStart).  I never bothered to check what RAMStart was when I started the project.  I just assumed it would be placed at the beginning of RAM.

 

As far as I understand, ORG defines an absolute section, while SECTION is relocateable.  However, that brings up a few other questions.

 

First can you elaborate on this:

 

"I almost never use ORG statements (I use SECTION), so I assume the assembler knows that COUNTER is in page-zero from the value of "RAMstart". When using SECTION, the section would be explicitly defined as page-zero."

 

Are you saying that you sould declare SECTION RAMStart?  Or simply SECTION, and then move on?  What guarantees that the section is explicitly defined as page-zero?  Am I misguided in thinking that page-zero is all addresses from $0000 to $00FF, page one is $0100 through $01FF, and so-on?

 

Would it suffice to use ORG Z_RAMStart instead, or maybe another constant address in the first page of memory?

 

If I set up my IVT as a SECTION instead of ORG, then how do I go about locating it at the proper address?

 

I've always used ORG to guarantee that my code goes into its proper location, like when I'm programming IVTs.  What is the disadvantage?

 

Thanks again,

 

Matt

0 项奖励
回复
5,224 次查看
rocco
Senior Contributor II

Hi Matt,

 

So it looks like your INC instruction was incrementing location $00 (an I/O port) instead of location $100. Glad you found it.

 

What we are doing differently is that I am writing relocatable assembly language, whereas you are writing absolute assembly language. So you are using ORGs and I am using SECTIONS. I only mentioned it so that you would know that I wasn't that familiar with absolute assembly.

 

You should just use "ORG Z_RAMStart", as you said. That appears to me to be the correct way for absolute assembly. Your understanding of page-zero being from $00 to $FF is correct. But I don't think you need the concept of page 1 or any other page. There is page-zero, and then there is everything else. That is all the silicon cares about.

 

The main advantage of relocatable assembly language is that you can make use of object-libraries. But there is more work involved, especially for the linker.

 

But to answer some of your "section" questions:

I use three "default" section statements a lot: BSCT (for page-zero data), DSCT (for non-page-zero data) and PSCT (for program instructions). I also create other sections, but 80% of my code is in those three.

 

When you declare a SECTION, you could explicitly make it refer to page-zero with the "short" keyword:

 

TableSct:  section   short

 

As for interrupt vectors, I've created a section called ".vect". Here is the code in the .asm file:

 

;;**********************************    ** Interrupt Vectors **    **********************************;;.vect: section  ;MC9S08gb60 Hardware Interrupt Vectors xdef vectors;;vectors: fdb IICnextPage ;Real-Time Interrupt vector  (Lowest Priority) fdb ICCservice ;IIC interrupt vector fdb Nope  ;ATD convertor interrupt vector fdb Nope  ;Keyboard interrupt vector fdb Nope  ;SCI2 Transmitter interrupt vector fdb Nope  ;SCI2 Receiver interrupt vector fdb Nope  ;SCI2 Error interrupt vector fdb Response ;SCI1 Transmitter interrupt vector fdb Command  ;SCI1 Receiver interrupt vector fdb CommErr  ;SCI1 Error interrupt vector fdb Nope  ;SPI interrupt vector fdb Overflow2 ;Timer 2 Overflow interrupt vector fdb Nope  ;Timer 2 Channel 4 interrupt vector fdb Nope  ;Timer 2 Channel 3 interrupt vector fdb ClinTrig ;Timer 2 Channel 2 interrupt vector fdb Temp1in  ;Timer 2 Channel 1 interrupt vector fdb Temp2in  ;Timer 2 Channel 0 interrupt vector fdb Overflow1 ;Timer 1 Overflow interrupt vector fdb Nope  ;Timer 1 Channel 2 interrupt vector fdb Nope  ;Timer 1 Channel 1 interrupt vector fdb Nope  ;Timer 1 Channel 0 interrupt vector fdb ICGintr  ;Internal Clock Generator interrupt vector fdb LVDintr  ;Low Voltage Detect interrupt vector fdb DSPintr  ;IRQ pin interrupt vector from DSP fdb Nope  ;Software interrupt vector fdb Boot  ;Reset vector    (Highest Priority)

 

And the it is placed at the appropriate addresses by the linker with these lines in the .prm file:

 

SEGMENTS   .   .   . Vectors = READ_ONLY 0xFFcc TO 0xFFff;   .   .   .ENDPLACEMENT   .   .   . .vect  INTO Vectors;   .   .   .END

 

0 项奖励
回复
5,223 次查看
meiermat
Contributor I

Rocco,

 

That explains everything perfectly.  The addition to the .prm file is the part I needed, for locating the SECTIONs of code in their proper places.

 

Incidentally, where might I find the .prm file?  I ran a simple search in Windows, and it doesn't show up in my project folder, or workspace.

 

It's not entirely necessary, I suppose.  Again, thanks for the assistance

 

Matt

0 项奖励
回复
5,223 次查看
bigmac
Specialist III

Hello Matt,

 

For CW 6.3 at least, the project.prm file may be found within the PRM folder of the project.  However, if using the new project wizard to create your assembly code project, and you specify absolute assembly, the unneeded file will not be incorporated,

 

For an absolute assembly project, it is also possible to run the CW assembler as a stand-alone program, without involving the IDE (and linker), nor even the need for a CW project structure.  Simply drag the .asm file name to the AHC08.EXE assembler window.  I do not know if this still applies to the later version of CW.

 

As you are probably already aware, a relocatable assembly project may contain multiple .asm files.  However, the absolute assembly project may contain only a single .asm file.  Any include files must use a different file name extension.  I tend to use the extension .inc where the include does not generate any code (equates, macro definitions, etc), and .a08 where the include generates code (sub-routines, RAM variables, etc).

 

While it is a personal choice, for the vector table I would use the directive DC.W in lieu of FDB.  To me, it then becomes immediately obvious that following the directive are 16-bit value(s).  For 8-bit values, the directive would be DC.B.  The use of the suffix is consistent with many other directives, e.g. DS.W would allow space for a 16-bit variable in RAM.

 

Regards,

Mac

 

0 项奖励
回复
5,223 次查看
rocco
Senior Contributor II

Well, it seems like Mac and I think a lot alike.

 


bigmac wrote:

. . .  I tend to use the extension .inc where the include does not generate any code (equates, macro definitions, etc), and .a08 where the include generates code (sub-routines, RAM variables, etc).


And I use .sa8 for HC08 assembly, .sa5 for HC05 assembly, and .sa1 for 68701 assembly (source-file, assembler, processor). Those last two aren't used much anymore, except when I'm hunting for an algorithm from my earlier days.

 

I also use .inc for definition files that are common to multiple projects or MCUs, much like .h files in C.

 


bigmac wrote:

While it is a personal choice, for the vector table I would use the directive DC.W in lieu of FDB.


And I agree here as well. FDB is what was available in the early '80s, when my first vector table was written, before the now-common DC.w syntax was available. You can see a lot of 80s left-over code, like the asterisks around comment blocks. I just never updated it, and my cut&paste mentality has perpetuated it.

 

I have only ever written a program from scratch once.

0 项奖励
回复
5,223 次查看
meiermat
Contributor I

Many thanks to both of you.  I was in need of a good primer for some of that stuff.

 

I guess I know where the .prm file is, since I've only used absolute assembly.  Maybe I'm a control freak.

 

Again, thanks for the tips.

 

Matt

0 项奖励
回复
5,223 次查看
rocco
Senior Contributor II

Hi Matt,

 

We don't use Codewarrior, except for the its Assembler, Linker, Librarian and Debugger (which is the meat of it), so I don't know where you would find the .prm file in your project. We had found that the project structure of CodeWarrior would not allow us to do hierarchical projects, which are most of our jobs. The Eclipse-based version may be more flexible, but we already have our own structure.

 

The .prm file is required by the linker. I believe that you don't need the linker if you are writing in absolute assembly language. All the necessary information to create your absolute object file is already in the .asm file, so the assembler can create it directly. I can't say for sure, as I have only ever used relocatable assembly language.

0 项奖励
回复