Some more Debugger factoring

This commit is contained in:
Jeff Parsons 2016-09-14 21:11:57 -07:00
commit e5c5a8e6be
17 changed files with 1124 additions and 1539 deletions

View file

@ -37,6 +37,7 @@ if (DEBUGGER) {
var usr = require("../../shared/lib/usrlib");
var web = require("../../shared/lib/weblib");
var Component = require("../../shared/lib/component");
var Debugger = require("../../shared/lib/debugger");
var PC6502 = require("./defines");
var Messages = require("./messages");
var Memory = require("./memory");
@ -68,7 +69,7 @@ var DbgAddr6502;
* Debugger6502(parmsDbg)
*
* @constructor
* @extends Component
* @extends Debugger
* @param {Object} parmsDbg
*
* The Debugger6502 component supports the following optional (parmsDbg) properties:
@ -89,17 +90,6 @@ function Debugger6502(parmsDbg)
this.style = Debugger6502.STYLE_8080;
/*
* These keep track of instruction activity, but only when tracing or when Debugger checks
* have been enabled (eg, one or more breakpoints have been set).
*
* They are zeroed by the reset() notification handler. cInstructions is advanced by
* stepCPU() and checkInstruction() calls. nCycles is updated by every stepCPU() or stop()
* call and simply represents the number of cycles performed by the last run of instructions.
*/
this.nCycles = 0;
this.cOpcodes = this.cOpcodesStart = 0;
/*
* Most commands that require an address call parseAddr(), which defaults to dbgAddrNextCode
* or dbgAddrNextData when no address has been given. doDump() and doUnassemble(), in turn,
@ -110,18 +100,6 @@ function Debugger6502(parmsDbg)
*/
this.dbgAddrNextCode = this.newAddr();
this.dbgAddrNextData = this.newAddr();
/*
* This maintains command history. New commands are inserted at index 0 of the array.
* When Enter is pressed on an empty input buffer, we default to the command at aPrevCmds[0].
*/
this.iPrevCmd = -1;
this.aPrevCmds = [];
/*
* fAssemble is true when "assemble mode" is active, false when not.
*/
this.fAssemble = false;
this.dbgAddrAssemble = this.newAddr();
/*
@ -138,21 +116,6 @@ function Debugger6502(parmsDbg)
*/
this.aSymbolTable = [];
/*
* aVariables is an object with properties that grows as setVariable() assigns more variables;
* each property corresponds to one variable, where the property name is the variable name (ie,
* a string beginning with a letter or underscore, followed by zero or more additional letters,
* digits, or underscores) and the property value is the variable's numeric value. See doVar()
* and setVariable() for details.
*
* Note that parseValue(), through its reliance on str.parseInt(), assumes a default base of 16
* if no base is explicitly indicated (eg, a trailing decimal period), and if you define variable
* names containing exclusively hex alpha characters (a-f), those variables will take precedence
* over the corresponding hex values. In other words, if you define variables "a" and "b", you
* will no longer be able to simply type "a" or "b" to specify the decimal values 10 or 11.
*/
this.aVariables = {};
/*
* clearBreakpoints() initializes the breakpoints lists: aBreakExec is a list of addresses
* to halt on whenever attempting to execute an instruction at the corresponding address,
@ -214,7 +177,7 @@ function Debugger6502(parmsDbg)
if (DEBUGGER) {
Component.subclass(Debugger6502);
Component.subclass(Debugger6502, Debugger);
/*
* NOTE: Every Debugger property from here to the first prototype function definition (initBus()) is a
@ -2652,379 +2615,6 @@ if (DEBUGGER) {
return s;
};
Debugger6502.aBinOpPrecedence = {
'||': 0, // logical OR
'&&': 1, // logical AND
'|': 2, // bitwise OR
'^': 3, // bitwise XOR
'&': 4, // bitwise AND
'!=': 5, // inequality
'==': 5, // equality
'>=': 6, // greater than or equal to
'>': 6, // greater than
'<=': 6, // less than or equal to
'<': 6, // less than
'>>>': 7, // unsigned bitwise right shift
'>>': 7, // bitwise right shift
'<<': 7, // bitwise left shift
'-': 8, // subtraction
'+': 8, // addition
'%': 9, // remainder
'/': 9, // division
'*': 9 // multiplication
};
/**
* evalExpression(aVals, aOps, cOps)
*
* In Node, if you set a variable to 0x80000001; ie:
*
* foo=0x80000001|0
*
* and then calculate foo*foo using "(foo*foo).toString(2)", the result is:
*
* '11111111111111111111111111111100000000000000000000000000000000'
*
* which is slightly incorrect because it has overflowed JavaScript's floating-point precision.
*
* 0x80000001 in decimal is -2147483647, so the product is 4611686014132420609, which is 0x3FFFFFFF00000001.
*
* @this {Debugger6502}
* @param {Array.<number>} aVals
* @param {Array.<string>} aOps
* @param {number} [cOps] (default is all)
* @return {boolean} true if successful, false if error
*/
Debugger6502.prototype.evalExpression = function(aVals, aOps, cOps)
{
cOps = cOps || -1;
while (cOps-- && aOps.length) {
var chOp = aOps.pop();
if (aVals.length < 2) return false;
var valNew;
var val2 = aVals.pop();
var val1 = aVals.pop();
switch(chOp) {
case '*':
valNew = val1 * val2;
break;
case '/':
if (!val2) return false;
valNew = val1 / val2;
break;
case '%':
if (!val2) return false;
valNew = val1 % val2;
break;
case '+':
valNew = val1 + val2;
break;
case '-':
valNew = val1 - val2;
break;
case '<<':
valNew = val1 << val2;
break;
case '>>':
valNew = val1 >> val2;
break;
case '>>>':
valNew = val1 >>> val2;
break;
case '<':
valNew = (val1 < val2? 1 : 0);
break;
case '<=':
valNew = (val1 <= val2? 1 : 0);
break;
case '>':
valNew = (val1 > val2? 1 : 0);
break;
case '>=':
valNew = (val1 >= val2? 1 : 0);
break;
case '==':
valNew = (val1 == val2? 1 : 0);
break;
case '!=':
valNew = (val1 != val2? 1 : 0);
break;
case '&':
valNew = val1 & val2;
break;
case '^':
valNew = val1 ^ val2;
break;
case '|':
valNew = val1 | val2;
break;
case '&&':
valNew = (val1 && val2? 1 : 0);
break;
case '||':
valNew = (val1 || val2? 1 : 0);
break;
default:
return false;
}
aVals.push(valNew|0);
}
return true;
};
/**
* parseExpression(sExp, fPrint)
*
* A quick-and-dirty expression parser. It takes an expression like:
*
* EDX+EDX*4+12345678
*
* and builds a value stack in aVals and a "binop" (binary operator) stack in aOps:
*
* aVals aOps
* ----- ----
* EDX +
* EDX *
* 4 +
* ...
*
* We pop 1 "binop" from aOps and 2 values from aVals whenever a "binop" of lower priority than its
* predecessor is encountered, evaluate, and push the result back onto aVals.
*
* Unary operators like '~' and ternary operators like '?:' are not supported; neither are parentheses.
*
* However, parseReference() now makes it possible to write parenthetical-style sub-expressions by using
* {...} (braces), as well as address references by using [...] (brackets).
*
* Why am I using braces instead of parentheses for sub-expressions? Because parseReference() serves
* multiple purposes, the other being reference replacement in message strings passing through replaceRegs(),
* and I didn't want parentheses taking on a new meaning in message strings.
*
* @this {Debugger6502}
* @param {string|undefined} sExp
* @param {boolean} [fPrint] is true to print all resolved values, false for quiet parsing
* @return {number|undefined} numeric value, or undefined if sExp contains any undefined or invalid values
*/
Debugger6502.prototype.parseExpression = function(sExp, fPrint)
{
var value;
if (sExp) {
/*
* First process (and eliminate) any references, aka sub-expressions.
*/
sExp = this.parseReference(sExp);
var i = 0;
var fError = false;
var sExpOrig = sExp;
var aVals = [], aOps = [];
/*
* All browsers (including, I believe, IE9 and up) support the following idiosyncrasy of a regexp split():
* when the regexp uses a capturing pattern, the resulting array will include entries for all the pattern
* matches along with the non-matches. This effectively means that, in the set of expressions that we
* support, all even entries in asValues will contain "values" and all odd entries will contain "operators".
*
* And although I tried to list the supported operators in "precedential" order, bitwise operators must
* be out-of-order so that we don't mistakenly match either '>' or '<' when they're part of '>>' or '<<'.
*/
var regExp = /(\|\||&&|\||^|&|!=|==|>=|>>>|>>|>|<=|<<|<|-|\+|%|\/|\*)/;
var asValues = sExp.split(regExp);
while (i < asValues.length) {
var sValue = asValues[i++];
var cchValue = sValue.length;
var s = str.trim(sValue);
if (!s) {
fError = true;
break;
}
var v = this.parseValue(s, null, fPrint === false);
if (v === undefined) {
fError = true;
fPrint = false;
break;
}
aVals.push(v);
if (i == asValues.length) break;
var sOp = asValues[i++], cchOp = sOp.length;
this.assert(Debugger6502.aBinOpPrecedence[sOp] != null);
if (aOps.length && Debugger6502.aBinOpPrecedence[sOp] < Debugger6502.aBinOpPrecedence[aOps[aOps.length-1]]) {
this.evalExpression(aVals, aOps, 1);
}
aOps.push(sOp);
sExp = sExp.substr(cchValue + cchOp);
}
if (!this.evalExpression(aVals, aOps) || aVals.length != 1) {
fError = true;
}
if (!fError) {
value = aVals.pop();
if (fPrint) this.printValue(null, value);
} else {
if (fPrint) this.println("error parsing '" + sExpOrig + "' at character " + (sExpOrig.length - sExp.length));
}
}
return value;
};
/**
* parseReference(s)
*
* Returns the given string with any "{expression}" sequences replaced with the value of the expression,
* and any "[address]" references replaced with the contents of the address. Expressions are parsed BEFORE
* addresses. Owing to this function's simplistic parsing, nested braces/brackets are not supported
* (define intermediate variables if needed).
*
* @this {Debugger6502}
* @param {string} s
* @return {string}
*/
Debugger6502.prototype.parseReference = function(s)
{
var a;
while (a = s.match(/\{(.*?)}/)) {
if (a[1].indexOf('{') >= 0) break; // unsupported nested brace(s)
var value = this.parseExpression(a[1]);
s = s.replace('{' + a[1] + '}', value != null? str.toHex(value) : "undefined");
}
while (a = s.match(/\[(.*?)]/)) {
if (a[1].indexOf('[') >= 0) break; // unsupported nested bracket(s)
var dbgAddr = this.parseAddr(a[1]);
s = s.replace('[' + a[1] + ']', dbgAddr? str.toHex(this.getWord(dbgAddr), 4) : "undefined");
}
return this.parseSysVars(s);
};
/**
* parseSysVars(s)
*
* Returns the given string with any recognized "$var" replaced with its value; eg:
*
* $ops: the number of opcodes executed since the last time it was displayed (or reset)
*
* @this {Debugger6502}
* @param {string} s
* @return {string}
*/
Debugger6502.prototype.parseSysVars = function(s)
{
var a;
while (a = s.match(/\$([a-z]+)/i)) {
var v = null;
switch(a[1].toLowerCase()) {
case "ops":
v = this.cOpcodes - this.cOpcodesStart;
break;
}
if (v == null) break;
s = s.replace(a[0], v.toString());
}
return s;
};
/**
* parseValue(sValue, sName, fQuiet)
*
* @this {Debugger6502}
* @param {string|undefined} sValue
* @param {string|null} [sName] is the name of the value, if any
* @param {boolean} [fQuiet]
* @return {number|undefined} numeric value, or undefined if sValue is either undefined or invalid
*/
Debugger6502.prototype.parseValue = function(sValue, sName, fQuiet)
{
var value;
if (sValue !== undefined) {
var iReg = this.getRegIndex(sValue);
if (iReg >= 0) {
value = this.getRegValue(iReg);
} else {
value = this.getVariable(sValue);
if (value === undefined) value = str.parseInt(sValue);
}
if (value === undefined && !fQuiet) this.println("invalid " + (sName? sName : "value") + ": " + sValue);
} else {
if (!fQuiet) this.println("missing " + (sName || "value"));
}
return value;
};
/**
* printValue(sVar, value)
*
* @this {Debugger6502}
* @param {string|null} sVar
* @param {number|undefined} value
* @return {boolean} true if value defined, false if not
*/
Debugger6502.prototype.printValue = function(sVar, value)
{
var sValue;
var fDefined = false;
if (value !== undefined) {
fDefined = true;
sValue = str.toHexLong(value) + " " + value + ". (" + str.toBinBytes(value) + ")";
}
sVar = (sVar != null? (sVar + ": ") : "");
this.println(sVar + sValue);
return fDefined;
};
/**
* printVariable(sVar)
*
* @this {Debugger6502}
* @param {string} [sVar]
* @return {boolean} true if all value(s) defined, false if not
*/
Debugger6502.prototype.printVariable = function(sVar)
{
if (sVar) {
return this.printValue(sVar, this.aVariables[sVar]);
}
var cVariables = 0;
for (sVar in this.aVariables) {
this.printValue(sVar, this.aVariables[sVar]);
cVariables++;
}
return cVariables > 0;
};
/**
* delVariable(sVar)
*
* @this {Debugger6502}
* @param {string} sVar
*/
Debugger6502.prototype.delVariable = function(sVar)
{
delete this.aVariables[sVar];
};
/**
* getVariable(sVar)
*
* @this {Debugger6502}
* @param {string} sVar
* @return {number|undefined}
*/
Debugger6502.prototype.getVariable = function(sVar)
{
return this.aVariables[sVar];
};
/**
* setVariable(sVar, value)
*
* @this {Debugger6502}
* @param {string} sVar
* @param {number} value
*/
Debugger6502.prototype.setVariable = function(sVar, value)
{
this.aVariables[sVar] = value;
};
/**
* comparePairs(p1, p2)
*

View file

@ -100,11 +100,6 @@ function Debugger8080(parmsDbg)
*/
this.dbgAddrNextCode = this.newAddr();
this.dbgAddrNextData = this.newAddr();
/*
* fAssemble is true when "assemble mode" is active, false when not.
*/
this.fAssemble = false;
this.dbgAddrAssemble = this.newAddr();
/*

View file

@ -73,18 +73,21 @@ try {
* ]
*
* Every component name comes from the component filename, minus the ".js" extension;
* Create is the constructor returned by require(). The only bit of fudging we do is
* overriding the constructor for component "cpu" with the constructor for "x86cpu",
* because when a "cpu" definition is encountered, it's the "x86cpu" subclass that we
* actually want to create, not the "cpu" superclass. See aSubClasses for the complete
* list of subclassed components we manage like that.
* Create is the constructor returned by require().
*
* TODO: Update the list of ignored (ie, ignorable) components.
*/
var Component;
var dbg;
var aComponents = [];
var asComponentsIgnore = ["embed","save"];
var asComponentsIgnore = ["embed", "save"];
/*
* A few of the components are subclasses of other classes (eg, "x86cpu" is a subclass
* of "cpu"). In those situations, we "hoist" the subclass constructor into the
* corresponding superclass, because it is the name of the superclass that we rely on during
* machine initialization.
*/
var aSubClasses = {
"pcx86/lib/x86cpu": "pcx86/lib/cpu",
"pcx86/lib/debugger": "shared/lib/debugger"

View file

@ -164,11 +164,6 @@ function DebuggerX86(parmsDbg)
*/
this.dbgAddrNextCode = this.newAddr();
this.dbgAddrNextData = this.newAddr();
/*
* fAssemble is true when "assemble mode" is active, false when not.
*/
this.fAssemble = false;
this.dbgAddrAssemble = this.newAddr();
/*

View file

@ -2631,7 +2631,7 @@ Card.prototype.dumpVideoCard = function()
* TODO: Make these options more general-purpose (it currently assumes a conventional VGA planar layout).
*
* @this {Card}
* @param {Array.<string>} asArgs
* @param {Array.<string>} asArgs (all numeric arguments default to base 16 unless otherwise specified)
*/
Card.prototype.dumpVideoBuffer = function(asArgs)
{
@ -2648,12 +2648,12 @@ Card.prototype.dumpVideoBuffer = function(asArgs)
var s = asArgs[i];
if (!i) {
idw = str.parseInt(s);
idw = str.parseInt(s, 16);
continue;
}
var ch = s.charAt(0);
j = str.parseInt(s.substr(1));
j = str.parseInt(s.substr(1), 16);
switch(ch) {
case 'l':

View file

@ -99,11 +99,6 @@ function DebuggerPDP11(parmsDbg)
*/
this.dbgAddrNextCode = this.newAddr();
this.dbgAddrNextData = this.newAddr();
/*
* fAssemble is true when "assemble mode" is active, false when not.
*/
this.fAssemble = false;
this.dbgAddrAssemble = this.newAddr();
/*
@ -3434,83 +3429,6 @@ if (DEBUGGER) {
}
};
/**
* parseCommand(sCmd, fSave, chSep)
*
* @this {DebuggerPDP11}
* @param {string|undefined} sCmd
* @param {boolean} [fSave] is true to save the command, false if not
* @param {string} [chSep] is the command separator character (default is ';')
* @return {Array.<string>}
*/
DebuggerPDP11.prototype.parseCommand = function(sCmd, fSave, chSep)
{
if (fSave) {
if (!sCmd) {
if (this.fAssemble) {
sCmd = "end";
} else {
sCmd = this.aPrevCmds[this.iPrevCmd+1];
}
} else {
if (this.iPrevCmd < 0 && this.aPrevCmds.length) {
this.iPrevCmd = 0;
}
if (this.iPrevCmd < 0 || sCmd != this.aPrevCmds[this.iPrevCmd]) {
this.aPrevCmds.splice(0, 0, sCmd);
this.iPrevCmd = 0;
}
this.iPrevCmd--;
}
}
var a = [];
if (sCmd) {
/*
* With the introduction of breakpoint commands (ie, quoted command sequences
* associated with a breakpoint), we can no longer perform simplistic splitting.
*
* a = sCmd.split(chSep || ';');
* for (var i = 0; i < a.length; i++) a[i] = str.trim(a[i]);
*
* We may now split on semi-colons ONLY if they are outside a quoted sequence.
*
* Also, to allow quoted strings *inside* breakpoint commands, we first replace all
* DOUBLE double-quotes with single quotes.
*/
sCmd = sCmd.toLowerCase().replace(/""/g, "'");
var iPrev = 0;
var chQuote = null;
chSep = chSep || ';';
/*
* NOTE: Processing charAt() up to and INCLUDING length is not a typo; we're taking
* advantage of the fact that charAt() with an invalid index returns an empty string,
* allowing us to use the same substring() call to capture the final portion of sCmd.
*
* In a sense, it allows us to pretend that the string ends with a zero terminator.
*/
for (var i = 0; i <= sCmd.length; i++) {
var ch = sCmd.charAt(i);
if (ch == '"' || ch == "'") {
if (!chQuote) {
chQuote = ch;
} else if (ch == chQuote) {
chQuote = null;
}
}
else if (ch == chSep && !chQuote || !ch) {
/*
* Recall that substring() accepts starting (inclusive) and ending (exclusive)
* indexes, whereas substr() accepts a starting index and a length. We need the former.
*/
a.push(str.trim(sCmd.substring(iPrev, i)));
iPrev = i + 1;
}
}
}
return a;
};
/**
* shiftArgs(asArgs)
*

View file

@ -66,6 +66,11 @@ function Debugger(parmsDbg)
this.nCycles = 0;
this.cOpcodes = this.cOpcodesStart = 0;
/*
* fAssemble is true when "assemble mode" is active, false when not.
*/
this.fAssemble = false;
/*
* This maintains command history. New commands are inserted at index 0 of the array.
* When Enter is pressed on an empty input buffer, we default to the command at aPrevCmds[0].
@ -215,6 +220,83 @@ if (DEBUGGER) {
return true;
};
/**
* parseCommand(sCmd, fSave, chSep)
*
* @this {Debugger}
* @param {string|undefined} sCmd
* @param {boolean} [fSave] is true to save the command, false if not
* @param {string} [chSep] is the command separator character (default is ';')
* @return {Array.<string>}
*/
Debugger.prototype.parseCommand = function(sCmd, fSave, chSep)
{
if (fSave) {
if (!sCmd) {
if (this.fAssemble) {
sCmd = "end";
} else {
sCmd = this.aPrevCmds[this.iPrevCmd+1];
}
} else {
if (this.iPrevCmd < 0 && this.aPrevCmds.length) {
this.iPrevCmd = 0;
}
if (this.iPrevCmd < 0 || sCmd != this.aPrevCmds[this.iPrevCmd]) {
this.aPrevCmds.splice(0, 0, sCmd);
this.iPrevCmd = 0;
}
this.iPrevCmd--;
}
}
var a = [];
if (sCmd) {
/*
* With the introduction of breakpoint commands (ie, quoted command sequences
* associated with a breakpoint), we can no longer perform simplistic splitting.
*
* a = sCmd.split(chSep || ';');
* for (var i = 0; i < a.length; i++) a[i] = str.trim(a[i]);
*
* We may now split on semi-colons ONLY if they are outside a quoted sequence.
*
* Also, to allow quoted strings *inside* breakpoint commands, we first replace all
* DOUBLE double-quotes with single quotes.
*/
sCmd = sCmd.toLowerCase().replace(/""/g, "'");
var iPrev = 0;
var chQuote = null;
chSep = chSep || ';';
/*
* NOTE: Processing charAt() up to and INCLUDING length is not a typo; we're taking
* advantage of the fact that charAt() with an invalid index returns an empty string,
* allowing us to use the same substring() call to capture the final portion of sCmd.
*
* In a sense, it allows us to pretend that the string ends with a zero terminator.
*/
for (var i = 0; i <= sCmd.length; i++) {
var ch = sCmd.charAt(i);
if (ch == '"' || ch == "'") {
if (!chQuote) {
chQuote = ch;
} else if (ch == chQuote) {
chQuote = null;
}
}
else if (ch == chSep && !chQuote || !ch) {
/*
* Recall that substring() accepts starting (inclusive) and ending (exclusive)
* indexes, whereas substr() accepts a starting index and a length. We need the former.
*/
a.push(str.trim(sCmd.substring(iPrev, i)));
iPrev = i + 1;
}
}
}
return a;
};
/**
* parseExpression(sExp, fPrint)
*
@ -383,7 +465,7 @@ if (DEBUGGER) {
value = this.getRegValue(iReg);
} else {
value = this.getVariable(sValue);
if (value === undefined) value = str.parseInt(sValue);
if (value === undefined) value = str.parseInt(sValue, 16);
}
if (value === undefined && !fQuiet) this.println("invalid " + (sName? sName : "value") + ": " + sValue);
} else {

View file

@ -41,7 +41,7 @@ var str = {};
* So use this function to validate the entire string.
*
* @param {string} s is the string representation of some number
* @param {number} [base] is the radix of the number represented above; 10 is the default (only 2, 8, 10 and 16 are supported)
* @param {number} [base] is the radix of the above number; 10 is the default (only 2, 8, 10 and 16 are supported)
* @return {boolean} true if valid, false if invalid (or the specified base isn't supported)
*/
str.isValidInt = function(s, base)
@ -63,14 +63,14 @@ str.isValidInt = function(s, base)
* for binary, because 1) it's not commonly used, and 2) it conflicts with valid hex sequences.
*
* @param {string} s is the string representation of some number
* @param {number} [base] is the default radix to use (default is 16); can be overridden by prefixes/suffixes
* @param {number} [base] is the default radix to use (default is 10); can be overridden by prefixes/suffixes
* @return {number|undefined} corresponding value, or undefined if invalid
*/
str.parseInt = function(s, base)
{
var value;
if (s) {
if (!base) base = 16;
if (!base) base = 10;
if (s.charAt(0) == '$') {
base = 16;
s = s.substr(1);

View file

@ -232,7 +232,7 @@ TextOut.prototype.massageLines = function()
var cBytes = 0, c;
var sBytes = match[1], sASCIILine = "";
for (var i = 0; i < sBytes.length; i += 2) {
c = str.parseInt(sBytes.substr(i, 2));
c = str.parseInt(sBytes.substr(i, 2), 16);
if (c != 0x0D && c != 0x0A && (c < 0x20 || c >= 0x7F)) {
c = 0x2E;
fASCII = false;
@ -357,7 +357,7 @@ TextOut.prototype.labelTargets = function()
} else {
sTarget = sTarget.substr(sShort.length);
}
target = str.parseInt(sTarget);
target = str.parseInt(sTarget, 16);
if (target == undefined) continue;
if (aTargets.indexOf(target) < 0) {
aTargets.push(target);
@ -376,7 +376,7 @@ TextOut.prototype.labelTargets = function()
for (i = 0; i < this.asLines.length; i++) {
as = this.getLineParts(i);
if (!as) continue;
addr = str.parseInt(as[4]);
addr = str.parseInt(as[4], 16);
if (addr == undefined) continue;
j = aTargets.indexOf(addr);
if (j >= 0) {
@ -398,7 +398,7 @@ TextOut.prototype.labelTargets = function()
as = this.getLineParts(i);
if (!as) continue;
if (as[3].charAt(0) == chPrefix) {
addr = str.parseInt(as[3].substr(1));
addr = str.parseInt(as[3].substr(1), 16);
if (aTargets.indexOf(addr) >= 0) {
/*
* Instead of putting back the original target address, let's just convert the line to a "db"