Sorry for the noob question...but I need help!

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Sorry for the noob question...but I need help!

5,284 Views
Four80EastFan
Contributor I
I'm new to this assembly language stuff and I'm very confused at the moment. I'm taking a course and we're learning with the HCS12. Can someone help me with this piece of code please? Here is the assembly source for "mystery":
 
mystery:
        pshb
        ldaa #0
loop:   tstb
        beq mystend
        decb
        pshx
        abx
        pshb
        ldab 0,x
        cmpb #79
        bne notO
        inca
notO:   pulb
        pulx
        jmp loop
mystend:
        pulb
        rts
What does this subroutine do? A step-by-step explanation would be verrrrry helpful. Thanks.
Labels (1)
0 Kudos
Reply
15 Replies

2,975 Views
Four80EastFan
Contributor I
How do i find the square root of a number without using scratch registers or memory?...only the stack


Message Edited by Four80EastFan on 2008-09-25 09:40 PM
0 Kudos
Reply

2,975 Views
bigmac
Specialist III
Hello,
 
You do not say what sort of number you wish to process.  The following function is capable of handling a 16-bit integer value, and returning the square root to the nearest integer.  It uses the Newton algorithm.
 
word sqrt( word val)
{
   word temp, x = 4096;
 
   do {
      temp = x;
      x = (val/x + x + 1)/2;
   } while (x != temp);
   return x;
}
 
Regards,
Mac
 
 
0 Kudos
Reply

2,975 Views
kef
Specialist I
0 Kudos
Reply

2,975 Views
Four80EastFan
Contributor I
Wawowiwa. Verrry nice. I get it all now (the basics at least). I can follow everything.  It's really interesting using the step function and seeing what's going on in the stack etc. That's how I fixed my code. Here's my WORKING subroutine...I'm so proud.
 
MUL150: nop
 
        psha
        pshy
        ins
        pulx
        pshb
        ldd #0
       
loop:
 
       dex   
       addd -1,sp
       cpx #0        
       beq other       
       jmp loop        
       
other: 
       rts
 
One question though. Right when the program enters the subroutine some random values are put onto the stack ($0FFF = 15 and $0FFE = E0). Where did these come from??
0 Kudos
Reply

2,975 Views
kef
Specialist I
Random value comes from not initialized Y register.
For everyone puzzled what the hell first four lines are doing :smileyhappy:, it looks like they were supposed to transfer multiplier from A to X register. Intead of zero-padding, upper half of X gets filled with the bits from lower half of not initialized Y.
 
        psha    ;  A at 0,sp
        pshy    ; Y at 0,sp;   A at 2,sp
        ins       ; removing upper half of Y from stack,  Yl at 0,sp,  A at 1,sp
        pulx     ; X = Yl:A
 
        pshb   ; B at 0,sp
        ldd #0
       
loop:
 
       dex   
       addd -1,sp   ; ughh, never use negative sp offsets! Everything what's
                 ; below SP will be overwritten by running interrupt handlers.
                 ; Negative SP offsets are almost never used, except soething like task switcher from
                 ; preemptive RTOS.
                 ; With interrupts enabled and working, upper half of the sum will be random!
       cpx #0        
       beq other       
       jmp loop        
       
other: 
       rts
 
0 Kudos
Reply

2,975 Views
CompilerGuru
NXP Employee
NXP Employee
Cool,
however it appears to me that it does contain 2 bugs :smileysad:.
First, if I count right, it pushes 3 bytes on the stack, but reads (with the INS) 4 bytes from the stack,
therefore I guess the RTS at the end does not return to the caller :smileysad:.
Second, (actually it might even be the same issue) using
> addd -1,sp
is almost always incorrect, basically everything below 0,SP is in the non allocated area of the stack. In a real app, an interrupt might overwrite -1,SP and down at any time, so using unallocated stack generates hard to fix bugs.

Tips:
- Not completely sure what the code at the starts tries to do. Use  TFR to transfer one register into another (TFR D,X moves D into X).
- The snippet:
       dex   
       addd ???,sp
       cpx #0        
       beq other       
       jmp loop      
 other:

  Can be optimized with the DBNE instruction.
       addd ???,sp
       DBNE X,loop      

- Don't forget the multiply by 0 case
- Add with LEAY (or LEAX), the advantage is that you don't need to add from the stack.
E.g.
LEAY D,Y
adds D and Y and stores the result in Y.

Daniel
0 Kudos
Reply

2,975 Views
Four80EastFan
Contributor I
I know there's a lot of crap in there because I still need to expand my "vocabulary". For example, the reason I did pshy at the beginning was so that I would get  zero in mem. locations prior to A so that when I pull that value from the stack (pulx -> 16 bits), A has a zero in front of it. I tried leaving the previous mem. location empty but when i pulx, x is loaded with some wierd value. I know there are definitely ways to clean my code up and make it shorter. I will keep working at this stuff. This subroutine works though...ACCA<- 37 and ACCB<- 59 gives me 887(hex). I still have to take the zero case into account though...                   Kef,  D, X and Y were intialized to zero in the main program.


Message Edited by Four80EastFan on 2008-09-24 06:11 AM
0 Kudos
Reply

2,975 Views
kef
Specialist I
Some tricks
 
Ways to push 0-byte to the stack:
 
  CLRA
  PSHA
 
  CLR   1,-SP
 
  MOVB  #0, -SP
 
 
Also instead of zero padding 8bits A to 16bits X, you could use add with carry
 
   ADDB  0,SP
   ADCA  #0
 
0 Kudos
Reply

2,975 Views
Four80EastFan
Contributor I
I've made a few changes and it still doesn't work.
 
        stab $0a01      ; store contents of ACCB to memory
        
        
        
        loop:   
       deca                   
       addb $0a01
       cmpa #0               
       beq other       
       jmp loop       
       
       other: 
       rts
 
Is acc. B too small to hold the sum? Should I store the sum in an IR? Also, what's the difference between having a # before the label and nothing before the label? 
0 Kudos
Reply

2,975 Views
kef
Specialist I
Yes, your code can't work with products > 255.
What is IR?
 
CMPA  #0   compares reg A against zero
CMPA  0     compares reg A against byte at address 0
 
It doesn't work because you add B's more than necessary. Consider A=1. First value at $a01 and the sum in B are equal. Then you decrement A to 0, add value at $a01 to B (that's already 2*B). Then compare A against 0 and exit.
 
After you fix this, you should consider the case when A=0.
0 Kudos
Reply

2,975 Views
Four80EastFan
Contributor I
Thanks kef. I will make the necessary changes. I'll try storing the result in an index register (IR).
0 Kudos
Reply

2,975 Views
Four80EastFan
Contributor I
I knew it was 16-bit, I just couldn't find the right forum...
 
Anyways, forget my previous question. Here's a new one:
 
I want to multiply two numbers in ACCA and ACCB without doing it explicitly. For example, instead of 8x9, I would do 8+8+...9 times. Here's is my failed attempt at this. This is a subroutine btw, the accumulators already have values.
 
 
staa $0a00      ; store contents of ACCA to memory
        stab $0a01      ; store contents of ACCB to memory
        ldaa #0         ; load 0 into ACCA
       
       
        loop:  
        addd $0a01      ; add the contents of this mem. location to ACCD
        adda counter    ; ACCA <- ACCA + 1
       cmpa $0a00      ; compare contents of ACCA to number in this mem. location
       beq other       ; branch if the two numbers in the above step are equal
       jmp loop        ; jump to the beginning of the loop
        other: 
       rts             ; return to caller
      
 
        counter: dw !1  ; initialize counter   
    
Please help.
0 Kudos
Reply

2,975 Views
CompilerGuru
NXP Employee
NXP Employee
I guess the main problem is that addd is writing to A & B, in order to just add 8 bits to B, use addb.
Also as A already contains the value initially, it adds once to much to A.
Also consider checking for B being 0.

Once you get it working (and not sooner...) there are a couple of optimizations possible.
Consider counting A down to 0 with a DBNE. Also consider adding the result up in X or Y with a LEAX, B,X.
For incrementing A by 1, you could use ADDA #1 or INCA.

Daniel


0 Kudos
Reply

2,975 Views
bigmac
Specialist III
Hello, and welcome.
 
Firstly, since the HCS12 is a 16-bit MCU, you have actually posted this in the incorrect forum, especially for an assembly language question.  I suspect one of the moderators will eventually transfer this to a more appropriate forum.
 
Now I would assume that the code you have presented is a course exercise that you are expected to complete, to demonstrate that you have an understanding of the subject in question.  If I were to immediately provide the answers you requested, without you first making your own attempt to understand what is happening, I don't think that you would have learnt very much.  Please correct me if this is not the situation.
 
To understand a sub-routine written in assembly code, it is necessary to understand what each instruction does, and what it is meant to do in the context of the sub-routine structure.  This means that comments need to be added for most lines of code, about what you think is happening.  I think you should attempt to do this, and is probably what your course tutor is expecting.
 
You also need to be aware of (or surmise) the entry and exit conditions for the sub-routine, and also document these as comments.  For the present example, it would appear that the entry values for AccB and X registers are significant to the sub-routine - what might each value represent?  On exit, the AccA value would appear significant.
 
Looking at the basic structure, you obviously have a code loop, so that the same instructions may execute multiple times.  Therefore, the loop exit arrangement needs to be understood.  Finally, what might the value 79 decimal represent?
 
What I have just described are the actions and considerations that most assembly programmers would need to observe - there are few shortcuts.  So I suggest that you have a go yourself, and post your commented code if you think you still have some problems.  I assume that you already have full documentation for the various assembly instructions.
 
Regards,
Mac
 
0 Kudos
Reply

2,975 Views
peg
Senior Contributor IV
Hi,

Yep! seems you are quite new at this. The S12 is a 16-bit microcontroller and you have posted this in the 8-bit forum.

0 Kudos
Reply