home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Interfaces / PInterfaces / DisAsmLookup.p < prev    next >
Encoding:
Text File  |  1994-07-27  |  22.7 KB  |  488 lines  |  [TEXT/MPS ]

  1. {
  2.     File:        DisAsmLookup.p
  3.  
  4.      Copyright:    © 1984-1994 by Apple Computer, Inc.
  5.                  All rights reserved.
  6.  
  7.      Version:    Universal Interfaces 2.0a1  ETO #15, MPW prerelease. July 22, 1994
  8.  
  9.      Bugs?:        If you find a problem with this file, send the file and version
  10.                  information (from above) and the problem description to:
  11.  
  12.                      Internet:    apple.bugs@applelink.apple.com
  13.                      AppleLink:    APPLE.BUGS
  14.  
  15. }
  16.  
  17. {$IFC UNDEFINED UsingIncludes}
  18. {$SETC UsingIncludes := 0}
  19. {$ENDC}
  20.  
  21. {$IFC NOT UsingIncludes}
  22.     UNIT DisAsmLookup;
  23.     INTERFACE
  24. {$ENDC}
  25.  
  26. {$IFC UNDEFINED __USINGDISASMLOOKUP__}
  27. {$SETC __USINGDISASMLOOKUP__ := 1}
  28.  
  29. {$I+}
  30. {$SETC DisAsmLookupIncludes := UsingIncludes}
  31. {$SETC UsingIncludes := 1}
  32. {$IFC UNDEFINED __TYPES__}
  33. {$I Types.p}
  34. {$ENDC}
  35. {$SETC UsingIncludes := DisAsmLookupIncludes}
  36.  
  37.  
  38. TYPE
  39.     LookupRegs    = (_A0_, _A1_, _A2_, _A3_, _A4_, _A5_, _A6_, _A7_,
  40.                                  _PC_, _ABS_, _TRAP_, _IMM_);
  41.  
  42. (*----------------------------------------------------------------------*)
  43.  
  44. PROCEDURE Disassembler(        DstAdjust:  LongInt;             {addr correction}
  45.                         VAR BytesUsed:  Integer;             {bytes used up  }
  46.                             FirstByte:  UNIV Ptr;            {starting byte  }
  47.                         VAR Opcode:        UNIV Str255;        {mnemonic       }
  48.                         VAR Operand:     UNIV Str255;        {operand        }
  49.                         VAR Comment:     UNIV Str255;        {comment        }
  50.                             LookupProc: UNIV Ptr);            {search proc    }
  51.     (*
  52.      Disassembler is a Pascal routine to be called to disassemble a sequence
  53.      of bytes.  All MC68xxx, MC68881, and MC68851 instructions are supported.
  54.      The sequence of bytes to be disassembled are pointed to by FirstByte.
  55.      BytesUsed bytes starting at FirstByte are consumed by the disassembly,
  56.      and the Opcode, Operand, and Comment strings returned as NULL TERMINATED
  57.      Pascal strings (for easier manipulation with C). The caller is then free
  58.      to format or use the output strings any way appropriate to the
  59.      application.
  60.      
  61.      Depending on the opcode and effective address(s) (EA's) to be
  62.      disassembled, the Opcode, Operand, and Comment strings contain the
  63.      following information:
  64.      
  65.      Case                     Opcode    Operand    Comment
  66.      =======================================================================
  67.      Non PC-relative EA's     op.sz     EA's             ; 'c…' (for immediates)
  68.      PC-relative EA's         op.sz     EA's       ; address
  69.      Toolbox traps            DC.W      $AXXX      ; TB XXXX
  70.      OS traps                 DC.W      $AXXX      ; OS XXXX
  71.      Invalid bytes            DC.W      $XXXX      ; ????
  72.      =======================================================================
  73.      
  74.      For valid disassembly of processor instructions the appropriate MC68XXX
  75.      opcode mnemonic is generated for the Opcode string along with a size
  76.      attribute when required.  The source and destination EA's are generated
  77.      as the Operand along with a possible comment. Comments start with a ';'.
  78.      Traps use a DC.W assembler directive as the Opcode with the trap word
  79.      as the Operand and a comment indicating whether the trap is a toolbox or
  80.      OS trap and what the trap number is.  As described later the caller can
  81.      generate symbolic substitutions into EA's and provide names for traps.
  82.     
  83.      Invalid instructions cause the string 'DC.W' to be returned in the
  84.      Opcode string. Operand is '$XXXX' (the invalid word) with a comment of
  85.      '; ????'.  BytesUsed is 2.  This is similar to the trap call case except
  86.      for the comment.
  87.     
  88.      Note, the Operand EA's is syntatically similar to but NOT COMPATIBLE
  89.      with the MPW assembler!    This is because the Disassembler generates
  90.      byte hex constants as "$XX" and word hex constants as "$XXXX".  Negative
  91.      values (e.g., $FF or $FFFF) produced by the Disassembler are treated as
  92.      long word values by the MPW assembler.  Thus it is assumed that
  93.      Disassembler output will NOT be used as MPW assembler input.  If that is
  94.      the goal, then the caller must convert strings of the form $XX or $XXXX
  95.      in the Operand string to their decimal equivalent.  The routine
  96.      ModifyOperand is provided in this unit to aid with the conversion
  97.      process.
  98.     
  99.      Since a PC-relative comment is an address, the only address that the
  100.      Disassembler knows about is the address of the code pointed to by
  101.      FirstByte.  Generally, that may be a buffer that has no relation to
  102.      "reality", i.e., the actual code loaded into the buffer.  Therefore,
  103.      to allow the address comment to be mapped back to some actual address
  104.      the caller may specify an adjustment factor, specified by DstAdjust,
  105.      that is ADDED to the value that normally would be placed in the
  106.      comment.
  107.     
  108.      Operand effective address strings are generated as a function of the 
  109.      effective address mode and a special case is made for A-trap opcode
  110.      strings. In places where a possible symbolic reference could be
  111.      substituted for an address (or a portion of an address), the Disassembler
  112.      can call a user specified routine to do the substitution (using the
  113.      LookupProc parameter described later).  The following table summarizes
  114.      the generated effective addresses and where symbolic substitutions (S)
  115.      can be made:
  116.      
  117.      Mode    Generated Effective Address  Effective Address with Substitution
  118.      ========================================================================
  119.          0     Dn                           Dn
  120.          1     An                           An
  121.          2     (An)                         (An)
  122.          3     (An)+                        (An)+
  123.          4     -(An)                        -(An)
  124.          5     ∂(An)                        S(An) or just S (if An=A5, ∂≥0)
  125.         6n     ∂(An,Xn.Size*Scale)          S(An,Xn.Size*Scale)
  126.         6n     (BD,An,Xn.Size*Scale)        (S,An,Xn.Size*Scale)
  127.         6n     ([BD,An],Xm.Size*Scale,OD)   ([S,An],Xm.Size*Scale,OD)
  128.         6n     ([BD,An,Xn.Size*Scale],OD)   ([S,An,Xn.Size*Scale],OD)
  129.         70     ∂                            S
  130.         71     ∂                            S
  131.         72     *±∂                          S
  132.         73     *±∂(Xn.Size*Scale)           S(Xn.Size*Scale)
  133.         73     (*±∂,Xn.Size*Scale)          (S,Xn.Size*Scale)
  134.         73     ([*±∂],Xm.Size*Scale,OD)     ([S],Xm.Size*Scale,OD)
  135.         73     ([*±∂,Xn.Size*Scale],OD)     ([S,Xn.Size*Scale],OD)
  136.         74     #data                        S (#data made comment)
  137.      A-traps $AXXX                        S (as opcode, AXXX made comment)
  138.      ========================================================================
  139.  
  140.      For A-traps, the substitution can be performed to substitute for the DC.W
  141.      opcode string.  If the substitution is made then the Disassembler will
  142.      generate ,Sys and/or ,Immed flags as operands for Toolbox traps and
  143.      ,AutoPop for OS traps when the bits in the trap word indicates these
  144.      settings.
  145.      
  146.                      |         Generated          |            Substituted
  147.                      | Opcode  Operand  Comment   | Opcode  Operand        Comment
  148.      ========================================================================
  149.      Toolbox | DC.W    $AXXX    ; TB XXXX | S       [,Sys][,Immed] ; AXXX
  150.      OS      | DC.W    $AXXX    ; OS XXXX | S       [,AutoPop]     ; AXXX
  151.      ========================================================================
  152.  
  153.      All displacements (∂, BD, OD) are hexadecimal values shown as a byte
  154.      ($XX), word ($XXXX), or long ($XXXXXXXX) as appropriate.  The *Scale is
  155.      suppressed if 1. The Size is W or L.  Note that effective address
  156.      substitutions can only be made for "∂(An)", "BD,An", and "*±∂" cases.
  157.     
  158.      For all the effective address modes 5, 6n, 7n, and for A-traps, a
  159.      coroutine (a procedure) whose address is specified by the LookupProc
  160.      parameter is called by the Disassembler (if LookupProc is not NIL) to
  161.      do the substitution (or A-trap comment) with a string returned by the
  162.      proc.  It is assumed that the proc pointed to by LookupProc is a level 1
  163.      Pascal proc declared as follows:
  164.  
  165.      PROCEDURE Lookup(    PC:      UNIV Ptr;        {Addr of extension/trap word}
  166.                         BaseReg: LookupRegs;    {Base register/lookup mode  }
  167.                         Opnd:    UNIV LongInt;    {Trap word, PC addr, disp.  }
  168.                         VAR S:   Str255);         {Returned substitution      }
  169.  
  170.      or in C,
  171.      
  172.      pascal void LookUp(Ptr         PC,      /* Addr of extension/trap word */
  173.                         LookupRegs  BaseReg, /* Base register/lookup mode   */
  174.                         long        Opnd,    /* Trap word, PC addr, disp.   */
  175.                         char        *S);     /* Returned substitution       */
  176.     
  177.      PC      = Pointer to instruction extension word or A-trap word in the
  178.                          buffer pointed to by the Disassembler's FirstByte parameter.
  179.  
  180.      BaseReg = This determines the meaning of the Opnd value and supplies
  181.                          the base register for the "∂(An)", "BD,An", and "*±∂" cases.
  182.                          BaseReg may contain any one of the following values:
  183.                         
  184.                          _A0_    =  0 ==> A0
  185.                          _A1_    =  1 ==> A1
  186.                          _A2_    =  2 ==> A2
  187.                          _A3_    =  3 ==> A3
  188.                          _A4_    =  4 ==> A4
  189.                          _A5_    =  5 ==> A5
  190.                          _A6_    =  6 ==> A6
  191.                          _A7_    =  7 ==> A7
  192.                          _PC_    =  8 ==> PC-relative (special case)
  193.                          _ABS_   =  9 ==> Abs addr    (special case)
  194.                          _TRAP_  = 10 ==> Trap word   (special case)
  195.                          _IMM_     = 11 ==> Immediate   (special case)
  196.                          
  197.                          For absolute addressing (modes 70 and 71), BaseReg contains
  198.                          _ABS_.  For A-traps, BaseReg would contain _TRAP_.  For
  199.                          immediate data (mode 74), BaseReg would contain _IMM_.
  200.      
  201.      Opnd    = The contents of this LongInt is determined by the BaseReg
  202.                          parameter just described.
  203.  
  204.                          For BaseReg = _IMM_ (immediate data):
  205.                                  Opnd contains the (extended) 32-bit immediate data specified
  206.                                  by the instruction.
  207.  
  208.                          For BaseReg = _TRAP_ (A-traps):
  209.                                  Opnd is the entire trap word. The high order 16 bits of
  210.                                  Opnd are zero.
  211.  
  212.                          For BaseReg = _ABS_  (absolute effective address):
  213.                                  Opnd contains the (extended) 32-bit address specifed by
  214.                                  the instruction's effective address.  Such addresses would
  215.                                  generally be used to reference low memory globals on a
  216.                                  Macintosh.
  217.  
  218.                          For BaseReg = _PC_  (PC-relative effective address):
  219.                                  Opnd contains the 32-bit address represented by "*±∂"
  220.                                  adjusted by the Disassembler's DstAdjust parameter.
  221.                                  
  222.                          For BaseReg = _An_  (effective address with a base register):
  223.                                  Opnd contains the (sign-extended) 32-bit (base)
  224.                                  displacement from the instruction's effective address.
  225.                                  
  226.                                  In the Macintosh environment, a BaseReg specifying A5
  227.                                  implies either global data references or Jump Table
  228.                                  references. Positive Opnd values with an A5 BaseReg thus
  229.                                  mean Jump Table references, while a negative offset would
  230.                                  mean a global data reference.  Base registers of A6 or A7
  231.                                  would usually mean local data.
  232.     
  233.      S       = Pascal string returned from Lookup containing the effective
  234.                          address substitution string or a trap name for A-traps.  S is
  235.                          set to null PRIOR to calling Lookup.  If it is still null on
  236.                          return, the string is not used.  If not null, then for A-traps,
  237.                          the returned string is used as the opcode string. In all other
  238.                          cases the string is substituted as shown in the above table.
  239.     
  240.      Depending on the application, the caller has three choices on how to
  241.      use the Disassembler and an associated Lookup proc:
  242.     
  243.      (1). The caller can call just the Disassembler and provide his own Lookup
  244.                 proc. In that case the calling conventions discussed above must be
  245.                 followed.
  246.     
  247.      (2). The caller can provide NIL for the LookupProc parameter, in which
  248.                 case, NO Lookup proc will be called.
  249.                 
  250.      (3). The caller can call first InitLookup (described below, a proc
  251.                 provided with this unit) and pass the address of this unit's
  252.                 standard Lookup proc when Disassembler is called.    In this case all
  253.                 the control logic to determine the kind of substitution to be done
  254.                 is provided for the caller and all that need to be provided by the
  255.                 user are routines to look up any or all of the following:
  256.                 
  257.                 • PC-relative references
  258.                 • Jump Table references
  259.                 • Absolute address references
  260.                 • Trap names
  261.                 • Immediate data names
  262.                 • References with offsets from base registers                                            *)
  263.                 
  264.  
  265. PROCEDURE InitLookup(PCRelProc, JTOffProc, TrapProc, AbsAddrProc, IdProc, ImmDataProc: UNIV Ptr);
  266.     {Prepare for use of this unit's Lookup proc.  When Disassembler is called
  267.      and the address of this unit's Lookup proc is specified, then for immediate
  268.      data, PC-relative, Jump Table references, A-traps, absolute addresses, and
  269.      offsets from a base register, the associated level 1 Pascal proc
  270.      specified here is called (if not NIL -- all six addresses are preset to
  271.      NIL).  The calls assume the following declarations for these procs (see
  272.      Lookup, below for further details):
  273.                                                      
  274.      PROCEDURE PCRelProc(Address: UNIV LongInt; 
  275.                                         VAR S:      UNIV Str255);
  276.  
  277.      PROCEDURE JTOffProc(A5JTOffset: UNIV Integer;
  278.                                         VAR S:      UNIV Str255);
  279.  
  280.      PROCEDURE TrapNameProc(TrapWord: UNIV Integer;
  281.                                         VAR S:      UNIV Str255);
  282.                                                      
  283.      PROCEDURE AbsAddrProc(AbsAddr: UNIV LongInt;
  284.                                         VAR S:      UNIV Str255);
  285.  
  286.      PROCEDURE IdProc(BaseReg: LookupRegs;
  287.                                         Offset:   UNIV LongInt;
  288.                                         VAR S:      UNIV Str255);
  289.                                                      
  290.      PROCEDURE ImmDataProc(ImmData: UNIV LongInt;
  291.                                         VAR S:      UNIV Str255);
  292.  
  293.      Note: InitLookup contains initialized data which requires initializing
  294.                  at load time (this is of concern only to users with assembler
  295.                  main programs.}
  296.     
  297.  
  298.  PROCEDURE Lookup(        PC:      UNIV Ptr;    {Addr of extension/trap word}
  299.                         BaseReg: LookupRegs;    {Base register/lookup mode  }
  300.                         Opnd:    UNIV LongInt;    {Trap word, PC addr, disp.  }
  301.                     VAR    S:       Str255);         {Returned substitution      }
  302.     {This is a standard Lookup proc available to the caller for calls to the
  303.      Disassembler.    If the caller elects to use this proc, then InitLookup
  304.      MUST be called prior to any calls to the Disassembler.  All the logic
  305.      to determine the type of lookup is done by this proc.  For PC-relative,
  306.      Jump Table references, A-traps, absolute addresses, and offsets from a
  307.      base register, the associated level 1 Pascal proc specified in the
  308.      InitLookup call (if not NIL) is called.
  309.     
  310.      This scheme simplifies the Lookup mechanism by allowing the caller
  311.      to deal with just the problems related to the application.}
  312.  
  313.  
  314. PROCEDURE LookupTrapName(TrapWord:    UNIV Integer;
  315.                             VAR S:    UNIV Str255);
  316.     {This is a procedure provided to allow conversion of a trap instruction
  317.      (in TrapWord) to its corresponding trap name (in S).  It is provided
  318.      primarily for use with the Disassembler and its address may be passed to
  319.      InitLookup above for use by this unit's Lookup routine.  Alternatively,
  320.      there is nothing prohibiting the caller from using it directly for other
  321.      purposes or by some other Lookup proc.
  322.      
  323.      Note: The tables in this proc make the size of this proc about 9500
  324.                  bytes.  The trap names are fully spelled out in upper and lower
  325.                  case.}
  326.  
  327. PROCEDURE ModifyOperand(VAR Operand: UNIV Str255);
  328.     {Scan an operand string, i.e., the null terminated Pascal string returned
  329.      by the Disassembler (null MUST be present here) and modify negative hex
  330.      values to negated positive value.  For example, $FFFF(A5) would be
  331.      modified to -$0001(A5).  The operand to be processed is    passed as the
  332.      function's parameter which is edited "in place" and returned to the
  333.      caller.
  334.  
  335.      This routine is essentially a pattern matcher and attempts to only
  336.      modify 2, 4, and 8 digit hex strings in the operand that "might" be
  337.      offsets from a base register.  If the matching tests are passed, the
  338.      same number of original digits are output (because that indicates a
  339.      value's size -- byte, word, or long).
  340.  
  341.      For a hex string to be modified, the following tests must be passed:
  342.  
  343.      • There must have been exactly 2, 4, or 8 digits.
  344.  
  345.          Only hex strings $XX, $XXXX, and $XXXXXXXX are possible candidates
  346.          because that is the only way the Disassembler generates offsets.
  347.  
  348.      • Hex string must be delimited by a "(" or a ",".
  349.  
  350.          The "(" allows offsets for $XXXX(An,...) and $XX(An,Xn) addressing
  351.          modes.  The comma allows for the MC68020 addressing forms.
  352.  
  353.      • The "$X..." must NOT be preceded by a "±".
  354.  
  355.          This eliminates the possibility of modifying the offset of a
  356.          PC-relative addressing mode always generated in the form "*±$XXXX".
  357.      
  358.      • The "$X..." must NOT be preceded by a "#".
  359.      
  360.          This eliminates modifying immediate data.
  361.  
  362.      • Value must be negative.
  363.  
  364.          Negative values are the only values we modify.  A value $FFFF is
  365.          modified to -$0001.}
  366.  
  367. FUNCTION validMacsBugSymbol(symStart, limit: UNIV Ptr;
  368.                             symbol: StringPtr): StringPtr; C;
  369.     {Check that the bytes pointed to by symStart represents a valid MacsBug
  370.      symbol.  The symbol must be fully contained in the bytes starting at
  371.      symStart, up to, but not including, the byte pointed to by the limit
  372.      parameter.
  373.      
  374.      If a valid symbol is NOT found, then NIL is returned as the function's
  375.      result.  However, if a valid symbol is found, it is copied to symbol (if
  376.      it is not NIL) as a null terminated Pascal string, and return a pointer
  377.      to where we think the FOLLOWING module begins. In the "old style" cases
  378.      (see below) this will always be 8 or 16 bytes after the input symStart.
  379.      For new style Apple Pascal and C cases this will depend on the symbol
  380.      length, existence of a pad byte, and size of the constant (literal) area.
  381.      In all cases, trailing blanks are removed from the symbol.
  382.      
  383.      A valid MacsBug symbol consists of the characters '_', '%', spaces,
  384.      digits, and upper/lower case letters in a format determined by the first
  385.      two bytes of the symbol as follows:
  386.      
  387.         1st byte  | 2nd byte  |  Byte  |
  388.             Range   |  Range    | Length | Comments
  389.      =======================================================================
  390.         $20 - $7F | $20 - $7F |    8   | "Old style" MacsBug symbol format
  391.         $A0 - $7F | $20 - $7F |    8   | "Old style" MacsBug symbol format
  392.      -----------------------------------------------------------------------
  393.         $20 - $7F | $80 - $FF |   16   | "Old style" MacApp symbol ab==>b.a
  394.         $A0 - $7F | $80 - $FF |   16   | "Old style" MacApp symbol ab==>b.a
  395.      -----------------------------------------------------------------------
  396.         $80       | $01 - $FF |    n   | n = 2nd byte           (Apple symbol)
  397.         $81 - $9F | $00 - $FF |    m   | m = BAnd(1st byte,$7F) (Apple symbol)
  398.      =======================================================================
  399.      
  400.      The formats are determined by whether bit 7 is set in the first and
  401.      second bytes.  This bit will removed when we find it or'ed into the first
  402.      and/or second valid symbol characters.
  403.      
  404.      The first two formats in the above table are the basic "old style" (pre-
  405.      existing) MacsBug formats. The first byte may or may not have bit 7 set
  406.      the second byte is a valid symbol character.  The first byte (with bit 7
  407.      removed) and the next 7 bytes are assumed to comprise the symbol.
  408.      
  409.      The second pair of formats are also "old style" formats, but used for
  410.      MacApp symbols.  Bit 7 set in the second character indicates these
  411.      formats.  The symbol is assumed to be 16 bytes with the second 8 bytes
  412.      preceding the first 8 bytes in the generated symbol.  For example,
  413.      12345678abcdefgh represents the symbol abcdefgh.12345678.
  414.      
  415.      The last pair of formats are reserved by Apple and generated by the MPW
  416.      Pascal and C compilers.  In these cases the value of the first byte is
  417.      always between $80 and $9F, or with bit 7 removed, between $00 and $1F.
  418.      For $00, the second byte is the length of the symbol with that many bytes
  419.      following the second byte (thus a max length of 255). Values $01 to $1F
  420.      represent the length itself.  A pad byte may follow these variable length
  421.      cases if the symbol does not end on a word boundary.  Following the
  422.      symbol and the possible pad byte is a word containing the size of the
  423.      constants (literals) generated by the compiler.
  424.      
  425.      Note that if symStart actually does point to a valid MacsBug symbol,
  426.      then you may use showMacsBugSymbol to convert the MacsBug symbol bytes to
  427.      a string that could be used as a DC.B operand for disassembly purposes.
  428.      This string explicitly shows the MacsBug symbol encodings.}
  429.  
  430. FUNCTION endOfModule(address, limit: UNIV Ptr; symbol: StringPtr;
  431.                                          VAR nextModule: UNIV Ptr): StringPtr; C;
  432.     {Check to see if the specified memory address, contains a RTS, JMP (A0) or
  433.      RTD #n instruction immediately followed by a valid MacsBug symbol.  These
  434.      sequences are the only ones which can determine an end of module when
  435.      MacsBug symbols are present.  During the check, the instruction and its
  436.      following MacsBug symbol must be fully contained in the bytes starting at
  437.      the specified address parameter, up to, but not including, the byte
  438.      pointed to by the limit parameter.
  439.     
  440.      If the end of module is NOT found, then NIL is returned as the
  441.      function's result.  However, if a end of module is found, the MacsBug
  442.      symbol is returned in symbol (if it is not NIL) as a null terminated
  443.      Pascal string (with trailing blanks removed), and the functions returns
  444.      the pointer to the start of the MacsBug symbol (i.e., address+2 for RTS
  445.      or JMP (A0) and address+4 for RTD #n).  This address may then be used as
  446.      in input parameter to showMacsBugSymbol to convert the MacsBug symbol to
  447.      a Disassembler operand string.
  448.      
  449.      Also returned in nextModule is where we think the FOLLOWING module
  450.      begins. In the "old style" cases (see validMacsBugSymbol) this will
  451.      always be 8 or 16 bytes after the input address.  For new style the
  452.      Apple Pascal and C cases this will depend on the symbol length, existence
  453.      of a pad byte, and size of the constant (literal) area.  See 
  454.      validMacsBugSymbol for a description of valid MacsBug symbol formats.}
  455.     
  456. FUNCTION showMacsBugSymbol(symStart, limit: UNIV Ptr; operand: StringPtr;
  457.                                                      VAR bytesUsed: Integer): StringPtr; C;
  458.     {Format a MacsBug symbol as a operand of a DC.B directive.  The first one
  459.      or two bytes of the symbol are generated as $80+'c' if they have there
  460.      high high bits set.  All other characters are shown as characters in a
  461.      string constant.  The pad byte, if present, is one is also shown as $00.
  462.      
  463.      When called, showMacsBugSymbol assumes that symStart is pointing at a
  464.      valid MacsBug symbol as validated by the validMacsBugSymbol or
  465.      endOfModule routines. As with validMacsBugSymbol, the symbol must be
  466.      fully contained in the bytes starting at symStart up to, but not
  467.      including, the byte pointed to by the limit parameter.
  468.      
  469.      The string is returned in the 'operand' parameter as a null terminated
  470.      Pascal string.  The function also returns a pointer to this string as its
  471.      return value (NIL is returned only if the byte pointed to by the limit
  472.      parameter is reached prior to processing the entire symbol -- which
  473.      should not happen if properly validated).  The number of bytes used for
  474.      the symbol is returned in bytesUsed.  Due to the way MacsBug symbols are
  475.      encoded, bytesUsed may not necessarily be the same as the length of the
  476.      operand string.
  477.      
  478.      A valid MacsBug symbol consists of the characters '_', '%', spaces,
  479.      digits, and upper/lower case letters in a format determined by the first
  480.      two bytes of the symbol as described in the validMacsBugSymbol routine.}
  481.  
  482. {$ENDC}    { __USINGDISASMLOOKUP__ }
  483.  
  484. {$IFC NOT UsingIncludes}
  485.     END.
  486. {$ENDC}
  487.  
  488.