Thread: 68000 assembler (building one that is)

  1. #1
    Registered User
    Join Date
    Dec 2003
    Posts
    16

    Unhappy 68000 assembler (building one that is)

    Hello, im buoilding a basic (if you could call it that), 68000 assembler. Im so far successfully able to assemble a MOVE instruction based on the guidlines found in any 68000 manual

    The main problem i have at the moment is implementing the ASSEMBLY of branching labels (and labels as operands) into the assembler part of my program.

    The way my program works is that it assembles an instruction, say the MOVE instruction thus:

    Code:
    MOVE       $7999,D1     =     32387999  (assembled instruction)
    With 68000 instructions having variable sizes, this instruction would take up 4 bytes in memory. This would then be placed in my simulated memory, (im doin this by creating what ive called a memory structure):

    Code:
    typedef struct Memory{
    
      
       char MNUM[XX]            = MOVE      
       char Op1[XX]             = $7999
       char Op1[XX]             = D1
       .
       .
       .
       .
       .
       char final_assembled[XX] = 32387999
       Size_of_final_assembled  = 4 bytes 		// Worked out by a simple
    						// strlen along the way
       int start_mem	    = 0x0000002A	// the amount of space the
       int finish_mem           = 0x0000002E	// instruction takes up
    
       struct Memory_Node *nextNode;		// next node in memory starting a 0x0000002E
    
    } Memory_Node;
    Memory would be seen as a series of structures each linking to the next logical area to the next with a giving instruciton in the correct place of each node.

    Braching instructions (like any othe 68k assembly instruction) also have varying sizes.

    These sizes are worked out by taking the destination address (in memory) of the branch away from the source address (in memory) of the branch (then having an extra 2 taken aaway.) Below shows this:

    Code:
    ########################################
    0000002E 32387999     TEST:     MOVE      $7999,D1
    00000032 32387999               MOVE      $7999,D1      ' DEST       COME FROM    = RESULT (WORD)
    00000036 60F6                   BRA       TEST	        ' 0000002E - 00000036 - 2 = F6 (from 60F6)
    ########################################
    MEMORY   ASSEMBLED    LABEL     NMUM      OPERANDS      COMENT
    ########################################
    This would be ok to implement in the program, the initial idea would be to skip the assembling phase and have the program try and find the destination of the branch in memory, from here the above sum (0000002E - 00000036 - 2 = F6) could be calculated and then the branch instruciton could be assembled properly (with the final_assembled[XX] now having the correct value inside it).

    This creates a huge problem though when trying to implement it this way when the following conditions are met in the form below:

    Code:
    ########################################
        4  00000014 323900009999 WISH:     MOVE      $9999,D1
        5  0000001A 3401                   MOVE      D1,D2
        6  0000001C 323C0000               MOVE      #0000,D1
        7  00000020 60000016               BRA       NICE
        8  00000024 3238FFFF               MOVE      $FFFFFFFF,D1
        9  00000028 60EA                   BRA       WISH
       10  0000002A 32387999               MOVE      $7999,D1
       11  0000002E 32387999     TEST:     MOVE      $7999,D1
       12  00000032 32387999               MOVE      $7999,D1
       13  00000036 60F6                   BRA       TEST
       14  00000038 323C0000     NICE:     MOVE      #0000,D1
    ########################################
     line  MEMORY   ASSEMBLED    LABEL     NMUM      OPERANDS      
    ########################################
    As you can see, the BRA on line 7 takes up more space in memory than the BRA in line 13.

    The above illustrates a classic catch 22 situation where none of the BRA instructions can be correctly assembled due to other branch instructions being the way of the other. (Basically I cant determin how much memory each would take up due to my not being able to figure out the size of each branching instruction).

    This is my main problem, and right now im completely stuck because of it.

    HELP!!!!!!!!!!

    From Garry
    Last edited by Nutcasey; 01-20-2004 at 01:46 PM.

  2. #2
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164

    Re: 68000 assembler (building one that is)

    Originally posted by Nutcasey
    Code:
    ########################################
        4  00000014 323900009999 WISH:     MOVE      $9999,D1
        5  0000001A 3401                   MOVE      D1,D2
        6  0000001C 323C0000               MOVE      #0000,D1
        7  00000020 60000016               BRA       NICE
        8  00000024 3238FFFF               MOVE      $FFFFFFFF,D1
        9  00000028 60EA                   BRA       WISH
       10  0000002A 32387999               MOVE      $7999,D1
       11  0000002E 32387999     TEST:     MOVE      $7999,D1
       12  00000032 32387999               MOVE      $7999,D1
       13  00000036 60F6                   BRA       TEST
       14  00000038 323C0000     NICE:     MOVE      #0000,D1
    ########################################
     line  MEMORY   ASSEMBLED    LABEL     NMUM      OPERANDS      
    ########################################
    As you can see, the BRA on line 7 takes up more space in memory than the BRA in line 13.

    The above illustrates a classic catch 22 situation where none of the BRA instructions can be correctly assembled due to other branch instructions being the way of the other. (Basically I cant determin how much memory each would take up due to my not being able to figure out the size of each branching instruction).

    This is my main problem, and right now im completely stuck because of it.
    I don't remember 68000 well, but in the other assemblers I used there were two forms, branch and long branch. The branch would be limited to 256 bytes forward & back, and the long would take care of the rest.

    The way you have it implemented, how do you tell the address size for any branch?

    In your example, how do you know the
    BRA NICE is a 3 byte destination and
    BRA TEST is a 1 byte destination? What is it that distinguishes this branch between 60F6, 60F632 and 60F6323C?
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  3. #3
    Registered User
    Join Date
    Dec 2003
    Posts
    16
    Here is the Explination of a branch instruction as taken from the 68000 manual.

    BRA Branch Always
    (M68000 Family)

    Operation: PC + dn ->PC

    Assembler
    Syntax: BRA < label >

    Attributes: Size = (Byte, Word, Long*)
    *(MC68020, MC68030, MC68040 only)

    Description: Program execution continues at location (PC) + displacement. The program counter contains the address of the instruction word of the BRA instruction plus two. The displacement is a twos complement integer that represents the relative distance in bytes from the current program counter to the destination program counter. If the 8-bit displacement field in the instruction word is zero, a 16-bit displacement (the word immediately following the instruction) is used. If the 8-bit displacement field in the instruction word is all ones ($FF), the 32-bit displacement (long word immediately following the instruction) is used.

    Condition Codes:
    Not affected.

    Instruction Format:
    Code:
    ---------------------------------------------------
    |15 14 13 12 11 10 09 08 | 07 06 05 04 03 02 01 00|
    |0  1  1  0  0  0  0  0  | 8-BIT DISPLACEMENT     |
    --------------------------------------------------|
    |16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00  |
    |32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF  |
    ---------------------------------------------------
    Instruction Fields:
    8-Bit Displacement field—Twos complement integer specifying the number of bytes between the branch instruction and the next instruction to be executed.

    16-Bit Displacement field—Used for a larger displacement when the 8-bit displacement is equal to $00.

    32-Bit Displacement field—Used for a larger displacement when the 8-bit displacement is equal to $FF.

    NOTE
    A branch to the immediately following instruction automatically
    uses the 16-bit displacement format because the 8-bit
    displacement field contains $00 (zero offset).

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The way that Intel gets around this problem is exactly what WaltP said.

    In x86 assembler you have several types of JMPs you can do.

    A short jump is one in which you jump within -127 to +128 bytes of the current CS:EIP.

    A near jump is one in which you jump into your current segment. -32768 to +32767 from your current CS:EIP.

    A far jump is one in which you are jumping/branching into a different segment. Pretty much anywhere from your current CS:EIP.


    Short jumps are the most efficient
    You cannot code this:

    JZ FARLABEL

    Because this will jump short if 0 or if ZF=1 (zero flag). You cannot jump short to a farlabel. So the coding is such that the actual opcode has the size of the jump coded into it.

    The proper way to do this would be:

    Code:
      JNZ BEYOND:
      JMP FARLABEL:
    BEYOND:

    The J(x) instructions will jump short and near and the JMP's will jump short, near, near indirect, intersegment - 4 or 6 byte displacement, to call gate's, and task-state segment's.

    J(X) instructions
    Code:
    IF condition
    THEN
      EIP <- EIP +SignExtend(rel8/16/32)
      IF OperandSize=16
        THEN EIP <- EIP AND 0000FFFFh
      FI
    FI


    The JMP instruction algo is 3 pages long so I'll not put it here.

    A simple fix is to only allow short jumps in your assembler. That is those falling within -127 to +128 bytes of your current EIP or equivalent. This is very limiting, but it's simple to code.

  5. #5
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Originally posted by Nutcasey
    Here is the Explination of a branch instruction as taken from the 68000 manual.
    ...
    Instruction Fields:
    8-Bit Displacement field—Twos complement integer specifying the number of bytes between the branch instruction and the next instruction to be executed.

    16-Bit Displacement field—Used for a larger displacement when the 8-bit displacement is equal to $00.

    32-Bit Displacement field—Used for a larger displacement when the 8-bit displacement is equal to $FF.

    NOTE
    A branch to the immediately following instruction automatically
    uses the 16-bit displacement format because the 8-bit
    displacement field contains $00 (zero offset).
    Ahhh, that makes sense in a convoluted way. So, Nutcasey, you will have to probably make an initial setting of 32 bit addresses then fine tune the displacement as you do the second link pass. The only place you'd have potential trouble is right at the boundaries. In the rare case your branch is on the cusp, there's probably not a real problem using 16 bits for a 254 byte jump.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  6. #6
    Registered User
    Join Date
    Dec 2003
    Posts
    16
    I'm building this as part of a simple simualtor for my university project, as such i have very little time.

    You were both right by the way, you can specifiy a short branch in the form of "BRA.S" as to keep the assembled instruction under 4 bytes. (of course this limits you to branching to only a limited amount distance in memory but this is sufficient enough for my requirements!)

    This will solve the problem for me so thank you very much for your help gentlemen!

    ps is there are BRA. X available where X would == a 16-bit 2's comp offset?
    Last edited by Nutcasey; 01-20-2004 at 06:33 PM.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    In other words BRA.X could theoretically jump -32767 to +32768 bytes from the current CS:EIP?

  8. #8
    Registered User
    Join Date
    Dec 2003
    Posts
    16
    Yeah, i found on the 68000 that BRA.L forces the branch to a particular size, just what i needed so il use that throughout the program.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 0
    Last Post: 06-08-2009, 05:33 PM
  2. Building an assembler in C O_o
    By Evenstevens in forum C Programming
    Replies: 7
    Last Post: 04-29-2009, 02:54 PM
  3. Assembler
    By GaPe in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 02-03-2003, 01:01 PM
  4. Converting Assembler Operators to Binary
    By sean in forum C Programming
    Replies: 10
    Last Post: 06-06-2002, 01:47 PM
  5. MAINFRAME Assembler.
    By sean in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 12-05-2001, 05:32 PM