small program with assembly 68k

Discussion in 'Programmer's Corner' started by blank, Apr 26, 2008.

  1. blank

    Thread Starter Member

    Apr 26, 2008

    i've just started learning assembly and i need some help..

    i've got an excersive which says to:

    A. store the numbers FF,FE,FD blah blah blah.. to memory positions from $400600-$4006FF.

    ORG $400400
    MOVE.B #$FF,D0
    LEA $400600,A0
    MOVE.W #256,D1
    LOOP MOVE.B D0,(A0)+
    SUBQ.B #1,D1


    B. to move all those numbers to memory positions $400700-$4007FF conversely. The content of memory position $4006FF to $400700, $4006FE to $400701 etc etc...

    LEA $400700,A1
    LOOP2 MOVE.B -(A0),(A1)+
    ADDI.B #1,D1
    END $400400

    is this code correct?

    another thing i noticed.. i run my code today in another system and when i trace it comes up with MOVE.W #$0100,D1 instead of #256,D1 (256 is the number of the entries of my numbers -FF to 00- that will be saved in the memory positions.
    why does this happen?

    again im newb in assembly so excuse any beginners mistakes i might be doing.
  2. Mark44

    Well-Known Member

    Nov 26, 2007
    I haven't done any M68000 assembly, but I've done a lot of x86 assembly coding, and know enough M68000 assembly to understand what you're trying to do here.
    Just before the start of the loop, you're setting the program origin, putting FF into register D0, loading the address 400600 into A0, and loading the loop count into D1.

    In the body of the loop you move the byte in D0 (FF) to the address pointed to by A0, and then increment the address in A0 by one byte. Then you decrement your loop counter and branch to the LOOP label.

    I don't see anywhere that you are decrementing the byte in D0, so it appears that what you'll be getting is FF, FF, FF, ... instead of what you want, which is FF, FE, FD, ... 3, 2, 1, 0.

    Your loop should look something like this:
    Code ( (Unknown Language)):
    2. LOOP  MOVE.B   D0,(A0)+
    3.       SUBQ.B   #1,D1
    4.       SUBQ.B   #1,D0   ;; decrement the byte in D0
    5.       BNE      LOOP

    I don't think it is. I think your decrement/increment things might be out of whack in your loop. Also, your loop counter should be be reinitialized and should count down to zero, not up.

    I'm going to assume that the code above runs immediately after the previous code has finished executing so that A0 contains $4006FF.

    The first instruction in the loop will decrement the address in A0 by one byte (since it's a MOVE byte instruction) to $4006FE, move the byte at that address to $400700, and increment the address in A1 by a byte to $400701. In other words, it will be moving 1, not 0, to memory location $400700.

    If you use post decrement/increment, reinitialize your loop counter, and count down, I think that will do what you want. Here's the revised code:

    Code ( (Unknown Language)):
    2.        LEA    $400700,A1
    3.        MOVE.B #256, D1      ;; initialize loop counter again
    4. LOOP2  MOVE.B (A0)-,(A1)+
    5.        SUBQ.B #1,D1          ;; decrement loop counter
    6.        BNE    LOOP2
    7.        END    $400400

    They are actually the same, but in different bases. The $ prefix indicates a number in hexadecimal, or base 16. 100 (base 16) == 256 (base 10).

    Let me know if this works for you.
  3. blank

    Thread Starter Member

    Apr 26, 2008
    thanks for the tips Mark. Will check it.
    The excersice continues. Now its study time.. I'll come back later if i'll stuck anywhere.
    Thanks again. :)
  4. blank

    Thread Starter Member

    Apr 26, 2008
    thats the correct code i think

    Code ( (Unknown Language)):
    3.            ORG         $400400
    4.            LEA          $400600,A0
    5.            MOVE.W   #256,D0
    6.            MOVE.W   #$FF,D1
    7. LOOP    MOVE.B    D1,(A0)+
    8.            SUBQ.B    #1,D0
    9.            SUBQ.B    #1,D1
    10.            BNE         LOOP
    11.            CLR.L       D0
    12.            CLR.L       D1    
    13.            MOVE.W   #256,D0
    14.            MOVE.W   #$00,D1
    15.            LEA         $400700,A1
    16. LOOP2  MOVE.B    D1,(A1)+
    17.            SUBQ.B   #1,D0
    18.            ADDI.B    #1,D1
    19.            BNE        LOOP2
    20.            END       $400400  
  5. Mark44

    Well-Known Member

    Nov 26, 2007
    I see a mistake I made: trying to load #256 (or #$100) into a byte. The largest byte is 255. I should have used MOVE.W, not MOVE.B.

    Regarding the code you show in your last post, I don't think your second loop is going to do what you want, which is to put $FF in location $400700, $FE in $400701, and so on. Instead of this instruction:
    Code ( (Unknown Language)):
    1.      ADDI.B  #1,D1
    I think you want this:
    Code ( (Unknown Language)):
    1.      SUBQ.B  #1,D1
    If you make that change, I think your code will do what is required for the exercise. I should note that there are at least two ways to code the second loop:
    1. Copy the bytes that were placed in memory by the first loop (my approach).
    2. Recalculate each byte, and copy its value (your approach).
    Either way is fine.

    A comment about comments...
    Assembly code is arcane enough that many assembly programmers put a comment on almost every line. That way, a reader can see what you intended to do, even if your code doesn't work correctly. Debugging is easier when your comments show what you're trying to do.

    Off the top of my head, your code would be improved if you had comments that:
    1. State the purpose of each register used (e.g., D0 holds your loop counter, D1 holds the current value of the byte you're going to copy).
    2. State what a loop is supposed to do.
    3. State why you're doing a particular action.

    I'm sure there are more, but these are all that I can think of relative to your program.

    Anyway, I hope this helps. You're doing some fun stuff (IMO:)). From the programmer's perspective, the M68000 processor was lots easier to program than its Intel counterpart, the 80386. The Motorola chip had more registers available, pretty much any register could be used for any purpose (unlike the Intel chips), the instruction set was cleaner, and so on.

  6. blank

    Thread Starter Member

    Apr 26, 2008
    Hey Mark, you're totaly right about the comments, I just didnt have the time to write them.

    When I run your version and trace the code, after the first loop D1 was starting from FF and not from 00 like the exercise asks. Then I tried MD (Memory Dump), it started from 00 but it was strangely registered twice (the number 00) to memory positions $400700 and $400701. I dont know why.. then continued with number 02 to $400702. Anyway its not wrong, it just needs some adjustments i guess.

    What i did in the second version i posted:

    _______CLR.L__D0___;;clear D0
    _______CLR.L__D1___;;clear D1
    _______MOVE.W_#256,D0___;;put to D0 the number of the repeats
    _______MOVE.W_#$00,D1___;; put to D1 the number 00
    _______LEA____$400700,A1___;;load $400700 to A1
    LOOP2__MOVE.B_D1,(A1)+___;;move the byte of D1 to A1 and raise the content of A1 by 2
    _______SUBQ.B_#1,D0___;decrement D0 by 1 byte
    _______ADDI.B_#1,D1___;increment D1 by 1 byte
    _______BNE____LOOP2___; till the repeats finish (256)

    i think the comments will help you understand why i used ADDI instead of SUBQ. Thats a complete diff method than the first one, i needed to increment D1 in order to get to FF from 00. (MOVE.W #$00,D1)

    Thanks alot for all the help man, i really appreciate it.
  7. Mark44

    Well-Known Member

    Nov 26, 2007
    As I mentioned before, your loop and mine look different, but they're doing the same thing, which is to put 0 in 400700, 1 in 400701, 2 in 400702, ... , FF in 4007FF. I'm moving the values that the first loop placed in memory; FF in 400600, FE in 400601, FD in 400602, ..., 0 in 4006FF.

    So what my version of the second loop was doing was to:
    Move the byte (0) from 4006FF to 400700,
    Move the byte (1) from 4006FE to 400701,
    Move the byte (2) from 4006FE to 400702,
    Move the byte (FF) from 400600 to 4007FF.

    Your version does this:
    Put 0 in 400700.
    Increment the byte to 1, and put it in 400701.
    Increment the byte to 2, and put it in 400702.
    Increment the byte to FF, and put it in 4007FF.

    To do the moves the way I did them, I needed to count down through the source memory, and up through the destination memory.

    This is the approach that you started with, but you were predecrementing your source address and postincrementing your destination address, which would have caused off-by-one errors. The following code comes from your first post.
    Code ( (Unknown Language)):
    1. LOOP2 MOVE.B -(A0),(A1)+
    In case you're not clear about this pre- and post-increment/decrement business, it has to do with when the increment/decrement operation occurs. A pre-decrement/increment in a MOVE operation means that the address is decremented/incremented before the MOVE happens. Similarly, a post-decrement/increment means that the MOVE happens first, and then the address is decremented/incremented.

    Here's my code again, which is based on your first attempt. I changed the instruction just before the loop from MOVE.B to MOVE.W for the reason mentioned earlier.

    Again, both versions satisfy the exercise requirements, so neither one is better than the other, but seeing how someone else approaches a problem can sometimes give you additional insights.
    Code ( (Unknown Language)):
    2.        ;; I'm assuming that A0 = $4006FF after the first loop is done
    3.        LEA    $400700,A1      ;; A1 = start of destination addresses
    4.        MOVE.W #256, D1      ;; initialize loop counter again
    5. LOOP2  MOVE.B (A0)-,(A1)+
    6.        SUBQ.B #1,D1          ;; decrement loop counter
    7.        BNE    LOOP2
    8.        END    $400400

    BTW, one of your comments is wrong.

    You have this at the beginning of LOOP2:
    Code ( (Unknown Language)):
    2. LOOP2__MOVE.B_D1,(A1)+___;;move the byte of D1 to A1 and raise the content of A1 by 2
    Since the MOVE is a byte, the destination address will be incremented by 1, not 2.