📄 disassembler.c
字号:
/* ---------------------------------------------------------------------------- * disassembler.c * this module contains an 8051 disassembler * * Copyright 2003/2004 * * This code was originally written by David Sullins <djs@naspa.net> * with contributes from Peter Peres. They published their code under * the terms of the GPL so we use huge parts with their kindly permission. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * ----------------------------------------------------------------------------*/#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <stdio.h>#include <ctype.h>#include <string.h>#include "isp-at89.h"/* local prototypes */void pass1(struct MemoryMap *MemMap, struct MemChunk *Chunk, int addr);unsigned short int DPTR = 0; /* This is for tracking DPTR */const char mnemonic[256][20] = {/* 0 */ "NOP", "AJMP %s\n", "LJMP %s\n", "RR A", "INC A", "INC %s", "INC @R0", "INC @R1", "INC R0", "INC R1", "INC R2", "INC R3", "INC R4", "INC R5", "INC R6", "INC R7",/* 1 */ "JBC %s, %s", "ACALL %s", "LCALL %s", "RRC A", "DEC A", "DEC %s", "DEC @R0", "DEC @R1", "DEC R0", "DEC R1", "DEC R2", "DEC R3", "DEC R4", "DEC R5", "DEC R6", "DEC R7",/* 2 */ "JB %s, %s", "AJMP %s\n", "RET\n", "RL A", "ADD A, #%s", "ADD A, %s", "ADD A, @R0", "ADD A, @R1", "ADD A, R0", "ADD A, R1", "ADD A, R2", "ADD A, R3", "ADD A, R4", "ADD A, R5", "ADD A, R6", "ADD A, R7",/* 3 */ "JNB %s, %s", "ACALL %s", "RETI\n", "RLC A", "ADDC A, #%s", "ADDC A, %s", "ADDC A, @R0", "ADDC A, @R1", "ADDC A, R0", "ADDC A, R1", "ADDC A, R2", "ADDC A, R3", "ADDC A, R4", "ADDC A, R5", "ADDC A, R6", "ADDC A, R7",/* 4 */ "JC %s", "AJMP %s\n", "ORL %s, A", "ORL %s, #%s", "ORL A, #%s", "ORL A, %s", "ORL A, @R0", "ORL A, @R1", "ORL A, R0", "ORL A, R1", "ORL A, R2", "ORL A, R3", "ORL A, R4", "ORL A, R5", "ORL A, R6", "ORL A, R7",/* 5 */ "JNC %s", "ACALL %s", "ANL %s, A", "ANL %s, #%s", "ANL A, #%s", "ANL A, %s", "ANL A, @R0", "ANL A, @R1", "ANL A, R0", "ANL A, R1", "ANL A, R2", "ANL A, R3", "ANL A, R4", "ANL A, R5", "ANL A, R6", "ANL A, R7",/* 6 */ "JZ %s", "AJMP %s\n", "XRL %s, A", "XRL %s, #%s", "XRL A, #%s", "XRL A, %s", "XRL A, @R0", "XRL A, @R1", "XRL A, R0", "XRL A, R1", "XRL A, R2", "XRL A, R3", "XRL A, R4", "XRL A, R5", "XRL A, R6", "XRL A, R7",/* 7 */ "JNZ %s", "ACALL %s", "ORL C, %s", "JMP @A+DPTR\n", "MOV A, #%s", "MOV %s, #%s", "MOV @R0, #%s", "MOV @R1, #%s", "MOV R0, #%s", "MOV R1, #%s", "MOV R2, #%s", "MOV R3, #%s", "MOV R4, #%s", "MOV R5, #%s", "MOV R6, #%s", "MOV R7, #%s",/* 8 */ "SJMP %s\n", "AJMP %s\n", "ANL C, %s", "MOVC A, @A+PC", "DIV AB", "MOV %s, %s", "MOV %s, @R0", "MOV %s, @R1", "MOV %s, R0", "MOV %s, R1", "MOV %s, R2", "MOV %s, R3", "MOV %s, R4", "MOV %s, R5", "MOV %s, R6", "MOV %s, R7",/* 9 */ "MOV DPTR, #%s", "ACALL %s", "MOV %s, C", "MOVC A, @A+DPTR", "SUBB A, #%s", "SUBB A, %s", "SUBB A, @R0", "SUBB A, @R1", "SUBB A, R0", "SUBB A, R1", "SUBB A, R2", "SUBB A, R3", "SUBB A, R4", "SUBB A, R5", "SUBB A, R6", "SUBB A, R7",/* A */ "ORL C, /%s", "AJMP %s\n", "MOV C, %s", "INC DPTR", "MUL AB", "", /* undefined opcode */ "MOV @R0, %s", "MOV @R1, %s", "MOV R0, %s", "MOV R1, %s", "MOV R2, %s", "MOV R3, %s", "MOV R4, %s", "MOV R5, %s", "MOV R6, %s", "MOV R7, %s",/* B */ "ANL C, /%s", "ACALL %s", "CPL %s", "CPL C", "CJNE A, #%s, %s", "CJNE A, %s, %s", "CJNE @R0, #%s, %s", "CJNE @R1, #%s, %s", "CJNE R0, #%s, %s", "CJNE R1, #%s, %s", "CJNE R2, #%s, %s", "CJNE R3, #%s, %s", "CJNE R4, #%s, %s", "CJNE R5, #%s, %s", "CJNE R6, #%s, %s", "CJNE R7, #%s, %s",/* C */ "PUSH %s", "AJMP %s\n", "CLR %s", "CLR C", "SWAP A", "XCH A, %s", "XCH A, @R0", "XCH A, @R1", "XCH A, R0", "XCH A, R1", "XCH A, R2", "XCH A, R3", "XCH A, R4", "XCH A, R5", "XCH A, R6", "XCH A, R7",/* D */ "POP %s", "ACALL %s", "SETB %s", "SETB C", "DA A", "DJNZ %s, %s", "XCHD A, @R0", "XCHD A, @R1", "DJNZ R0, %s", "DJNZ R1, %s", "DJNZ R2, %s", "DJNZ R3, %s", "DJNZ R4, %s", "DJNZ R5, %s", "DJNZ R6, %s", "DJNZ R7, %s",/* E */ "MOVX A, @DPTR", "AJMP %s\n", "MOVX A, @R0", "MOVX A, @R1", "CLR A", "MOV A, %s", "MOV A, @R0", "MOV A, @R1", "MOV A, R0", "MOV A, R1", "MOV A, R2", "MOV A, R3", "MOV A, R4", "MOV A, R5", "MOV A, R6", "MOV A, R7",/* F */ "MOVX @DPTR, A", "ACALL %s", "MOVX @R0, A", "MOVX @R1, A", "CPL A", "MOV %s, A", "MOV @R0, A", "MOV @R1, A", "MOV R0, A", "MOV R1, A", "MOV R2, A", "MOV R3, A", "MOV R4, A", "MOV R5, A", "MOV R6, A", "MOV R7, A"};/* op_format table * * 0 = illegal opcode * 1 = no operands * 2 = one immediate operand * 3 = one direct operand * 4 = one bit-addressed operand * 5 = one relative address operand * 6 = one absolute address operand * 7 = two-byte immediate operand * 8 = two operands: direct, immediate * 9 = two operands: direct, direct * 10 = two operands: immediate, relative address * 11 = two operands: direct, relative address * 12 = two operands: bit address, relative address * 13 = two-byte long address operand */const char op_format[256] = { 1, 6, 13, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0 */ 12, 6, 13, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */ 12, 6, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 2 */ 12, 6, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 3 */ 5, 6, 3, 8, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4 */ 5, 6, 3, 8, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 5 */ 5, 6, 3, 8, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */ 5, 6, 4, 1, 2, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 7 */ 5, 6, 4, 1, 1, 9, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 8 */ 7, 6, 4, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9 */ 4, 6, 4, 1, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* A */ 4, 6, 4, 1, 10, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, /* B */ 3, 6, 4, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C */ 3, 6, 4, 1, 1, 11, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, /* D */ 1, 6, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E */ 1, 6, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* F */};const char sfbitname[128][7] = {/* 80 */ "P0.0", "P0.1", "P0.2", "P0.3", "P0.4", "P0.5", "P0.6", "P0.7",/* 88 */ "IT0", "IE0", "IT1", "IE1", "TR0", "TF0", "TR1", "TF1",/* 90 */ "P1.0", "P1.1", "P1.2", "P1.3", "P1.4", "P1.5", "P1.6", "P1.7",/* 98 */ "RI", "TI", "RB8", "TB8", "REN", "SM2", "SM1", "SM0",/* A0 */ "P2.0", "P2.1", "P2.2", "P2.3", "P2.4", "P2.5", "P2.6", "P2.7",/* A8 */ "EX0", "ET0", "EX1", "ET1", "ES", "0ADh", "0AEh", "EA",/* B0 */ "P3.0", "P3.1", "P3.2", "P3.3", "P3.4", "P3.5", "P3.6", "P3.7",/* B8 */ "PX0", "PT0", "PX1", "PT1", "PS", "0BDh", "0BEh", "0BFh",/* C0 */ "0C0h", "0C1h", "0C2h", "0C3h", "0C4h", "0C5h", "0C6h", "0C7h",/* C8 */ "CP_RL2", "C_T2", "TR2", "EXEN2", "TCLK", "RCLK", "EXF2", "TF2",/* D0 */ "P", "0D1h", "OV", "RS0", "RS1", "F0", "AC", "CY",/* D8 */ "0D8h", "0D9h", "0DAh", "0DBh", "0DCh", "0DDh", "0DEh", "0DFh",/* E0 */ "ACC.0", "ACC.1", "ACC.2", "ACC.3", "ACC.4", "ACC.5", "ACC.6", "ACC.7",/* E8 */ "0E8h", "0E9h", "0EAh", "0EBh", "0ECh", "0EDh", "0EEh", "0EFh",/* F0 */ "B.0", "B.1", "B.2", "B.3", "B.4", "B.5", "B.6", "B.7",/* F8 */ "0F8h", "0F9h", "0FAh", "0FBh", "0FCh", "0FDh", "0FEh", "0FFh"};const char sfrname[128][7] = {/* 80 */ "P0", "SP", "DP0L", "DP0H", "DP1L", "DP1H", "SPDR", "PCON",/* 88 */ "TCON", "TMOD", "TL0", "TL1", "TH0", "TH1", "8Eh", "8Fh",/* 90 */ "P1", "91h", "92h", "93h", "94h", "95h", "WMCON", "97h",/* 98 */ "SCON", "SBUF", "9Ah", "9Bh", "9Ch", "9Dh", "9Eh", "9Fh",/* A0 */ "P2", "0A1h", "0A2h", "0A3h", "0A4h", "0A5h", "0A6h", "0A7h",/* A8 */ "IE", "0A9h", "SPSR", "0ABh", "0ACh", "0ADh", "0AEh", "0AFh",/* B0 */ "P3", "0B1h", "0B2h", "0B3h", "0B4h", "0B5h", "0B6h", "0B7h",/* B8 */ "IP", "0B9h", "0BAh", "0BBh", "0BCh", "0BDh", "0BEh", "0BFh",/* C0 */ "0C0h", "0C1h", "0C2h", "0C3h", "0C4h", "0C5h", "0C6h", "0C7h",/* C8 */ "T2CON", "T2MOD", "RCAP2L", "TL2", "TH2", "0CDh", "0CEh", "0CFh",/* D0 */ "PSW", "0D1h", "0D2h", "0D3h", "0D4h", "SPCR", "0D6h", "0D7h",/* D8 */ "0D8h", "0D9h", "0DAh", "0DBh", "0DCh", "0DDh", "0DEh", "0DFh",/* E0 */ "ACC", "0E1h", "0E2h", "0E3h", "0E4h", "0E5h", "0E6h", "0E7h",/* E8 */ "0E8h", "0E9h", "0EAh", "0EBh", "0ECh", "0EDh", "0EEh", "0EFh",/* F0 */ "B", "0F1h", "0F2h", "0F3h", "0F4h", "0F5h", "0F6h", "0F7h",/* F8 */ "0F8h", "0F9h", "0FAh", "0FBh", "0FCh", "0FDh", "0FEh", "0FFh"};/* This are simplified calls to getDatabyte() which need less arguments as the * original function. This macros could be used either in pass1 or in pass 2 but * check for correct parameters. */#define getNextByte(pass) (getDatabyte(MemMap, Chunk, (pass), memPtr++))#define getByte(adr) (getDatabyte(MemMap, Chunk, 2, (adr)))/* This function reads the next byte from memory. It checks if addr is in range and * looks the data up the the Chunk addr belongs to. * If addr is out of range and illegal opcode is returned to cancel operation. This * can only be an temporarely solution and has bee put to the todo list. * If called during pass 1 this function mark given addresses in the MemMap as code * bytes which will be printed out as mnemonics later. */unsigned chargetDatabyte(struct MemoryMap *MemMap, struct MemChunk *Chunk, int pass, int addr){ if (pass == 1) { MemMap->flags[addr] |= ADR_CODE; /* set code marker */ MemMap->flags[addr] &= ~ADR_ENTRY; /* clear possible entry marker */ MemMap->flags[addr] &= ~ADR_DLABEL; /* clear possible data label marker */ } Chunk = memchunk_Find(Chunk, addr); if (Chunk) return Chunk->data[addr - Chunk->header.address]; return 0xa5; /* illegal opcode to cancel operation */}/* This family of funktions mark one or more addresses as possible code entries. * Pass 1 is initiated on every possible code entry so that also code isles such as * interrupt routines with no connection to the rest of the code will hopefully be * disassembled. This should also be used to handle JMP A,#DPTR in full. */voidaddCodeEntry(struct MemoryMap *MemMap, int addr){ if (addr < MemMap->mapsize) /* do only, if addr is in range */ if ((MemMap->flags[addr] & ADR_USED) == 0) /* and contains something */ MemMap->flags[addr] |= ADR_ENTRY; /* then set code entry marker */}voidaddCodeEntryRange(struct MemoryMap *MemMap, int addr, int count){ int n; for (n=0; n < count; n++) addCodeEntry(MemMap, addr++);}/* This function forces adding entry points. No check regarding * address in use is done. It is for real (hard) entry points only. */voidaddCodeEntryList(struct MemoryMap *MemMap, int *list, int count){ int n; for (n=0; n < count; n++) if (list[n] < MemMap->mapsize) MemMap->flags[list[n]] |= ADR_ENTRY;}voidaddLabel(struct MemoryMap *MemMap, int addr, int type){ int label; label = (type == CODE) ? ADR_CLABEL : ADR_DLABEL; if (addr < MemMap->mapsize) /* address in range ? */ if ((MemMap->flags[addr] & label) == 0) MemMap->flags[addr] |= label;}/* This function calculates the name of a label attached to a specific memory * address. To do this it counts all used labels in this programm from the * beginning until it comes to the given address. The result of this operation * is transformed to a label string which will be returned. If the address is out * of range the resulting string contain the original address. */const char *getLabelName(struct MemoryMap *MemMap, int addr, int type){ static char label[10]; int count = 0, n, flag; if (type == CODE) { flag = ADR_CLABEL; label[0] = 'L'; } else { flag = ADR_DLABEL; label[0] = 'D'; } if (addr < MemMap->mapsize && MemMap->flags[addr] & flag) { /* address is in range and carries an appropriate label */ for (count++, n=0; n < addr; n++) if (MemMap->flags[n] & flag) count++; /* count past labels */ sprintf(&label[1], "%04d", count); } else sprintf(label, "%04Xh", addr); return label;}/* Pretty format a hexadecimal number in a string. */const char *formatHexValue(unsigned char num){ static char name[5]; snprintf(name, 5, "%02Xh", num); return name;}/* Convert a direct memory value to a SFR name if appropriate. * Otherwise output the formatted number. */const char *decodeSFR(unsigned char sfr){ if (sfr & 0x80) return sfrname[sfr & 0x7f]; else return formatHexValue(sfr);}/* Convert a bit memory value to a SF bit name if appropriate. * Otherwise output the formatted number. */const char *decodeSFBit(unsigned char sfbit){ if (sfbit & 0x80) return sfbitname[sfbit & 0x7f]; else return formatHexValue(sfbit);}/* This Function calculates the target address from an direct addressing * command using an 16 bit absolute address. The return value is an * absolute 16 bit address. */intdecodeLongAddr(struct MemoryMap *MemMap, int pass, unsigned char op1, unsigned char op2){ int addr; addr = ((((int)op1)<<8) | op2); /* calculate address */ /* if in pass 1 check if this address has already been labelled */ if (pass == 1) addLabel(MemMap, addr, CODE); return addr;}/* This Function calculates the target address from an indirect addressing * command using an 11 bit address relative to the program counter. * The return value is an absolute 16 bit address. */intdecodeAbsAddr(struct MemoryMap *MemMap, int pass, unsigned char opcode, unsigned char operand, int memPtr){ int addr; /* calculate address */ addr = ((memPtr & 0xf800) | (((int)opcode & 0xe0)<<3) | operand); /* if in pass 1 check if this address has already been labelled */ if (pass == 1) addLabel(MemMap, addr, CODE); return addr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -