Playing with NASM

This commit is contained in:
Jeff Parsons 2015-04-04 12:35:36 -07:00 committed by jeffpar
commit 96a39c9bbe
8 changed files with 15310 additions and 2 deletions

View file

@ -358,7 +358,7 @@ The only other information I have about revision levels comes from a March 30, 1
However, that document does not indicate how a 80386-C0 part was marked, and I've found very little other
information on the C0 stepping; it may have been quickly superseded by the D0 stepping, which used revision
identifier 0x05.
identifier 0x05. D1 and D2 steppings used identifier 0x08.
### Errata

View file

@ -46,7 +46,7 @@ However, don't use that technique to check for optional parameters:
if (!parameter) { ... }
because a valid numeric parameter could include 0, a valid string parameter could include "", etc.
if a valid numeric parameter could include 0, or a valid string parameter could include "", etc.
Problems with type coercion are **NOT** problems caused by a poor choice of operators, so trying to make
those problems go away by artificially limiting your choice of operators seems like the wrong solution.

File diff suppressed because it is too large Load diff

View file

@ -62,3 +62,20 @@ the DEVICE OPERATION table indicated that, for a READ operation, /CE and /OE pin
while the /PGM should be connected to INPUT HIGH VOLTAGE. So I wired pin 27 (/PGM) to +5V instead of GND, and the dump
worked perfectly. The NYC Resistor article implied that every *active low* pin should be connected to GND, but apparently
there are exceptions to that general rule.
Producing Source Code with NDISASM
---
From the current directory, I ran:
ndisasm -o0x8000 private/1988-01-28.rom > 1988-01-28.nasm
Then I massaged the output with a regex:
^([0-9A-F]+)\s+([0-9A-F]+)\s+(o32 |a32 |)([^\s]*) *(.*)$ --> \t$3$4\t$5\t\t\t; $1 $2
Then I ran a TextOut command to vertically align all the comments:
node ~/Sites/pcjs/modules/textout/bin/textout --file=1988-01-28.nasm --alignvert > t.nasm
mv t.nasm 1988-01-28.nasm
To be continued....

View file

@ -0,0 +1,40 @@
#!/usr/bin/env node
/**
* @fileoverview Provides miscellaneous text-munging services
* @author <a href="mailto:Jeff@pcjs.org">Jeff Parsons</a>
* @version 1.0
* @suppress {missingProperties}
* Created 2015-Apr-04
*
* Copyright © 2012-2015 Jeff Parsons <Jeff@pcjs.org>
*
* This file is part of the JavaScript Machines Project (aka JSMachines) at <http://jsmachines.net/>
* and <http://pcjs.org/>.
*
* JSMachines 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 3
* of the License, or (at your option) any later version.
*
* JSMachines is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with JSMachines.
* If not, see <http://www.gnu.org/licenses/gpl.html>.
*
* You are required to include the above copyright notice in every source code file of every
* copy or modified version of this work, and to display that copyright notice on every screen
* that loads or runs any version of this software (see Computer.sCopyright).
*
* Some JSMachines files also attempt to load external resource files, such as character-image files,
* ROM files, and disk image files. Those external resource files are not considered part of the
* JSMachines Project for purposes of the GNU General Public License, and the author does not claim
* any copyright as to their contents.
*/
"use strict";
var path = require("path");
var fs = require("fs");
var lib = path.join(path.dirname(fs.realpathSync(__filename)), "../lib/");
require(lib + "textout.js").CLI();

View file

@ -0,0 +1,309 @@
/**
* @fileoverview Provides miscellaneous text-munging services
* @author <a href="mailto:Jeff@pcjs.org">Jeff Parsons</a> (@jeffpar)
* @version 1.0
* Created 2015-Apr-04
*
* Copyright © 2012-2015 Jeff Parsons <Jeff@pcjs.org>
*
* This file is part of the JavaScript Machines Project (aka JSMachines) at <http://jsmachines.net/>
* and <http://pcjs.org/>.
*
* JSMachines 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 3
* of the License, or (at your option) any later version.
*
* JSMachines is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with JSMachines.
* If not, see <http://www.gnu.org/licenses/gpl.html>.
*
* You are required to include the above copyright notice in every source code file of every
* copy or modified version of this work, and to display that copyright notice on every screen
* that loads or runs any version of this software (see Computer.sCopyright).
*
* Some JSMachines files also attempt to load external resource files, such as character-image files,
* ROM files, and disk image files. Those external resource files are not considered part of the
* JSMachines Project for purposes of the GNU General Public License, and the author does not claim
* any copyright as to their contents.
*/
"use strict";
var fs = require("fs");
var path = require("path");
var mkdirp = require("mkdirp");
var net = require("../../shared/lib/netlib");
var proc = require("../../shared/lib/proclib");
/**
* TextOut()
*
* @constructor
*/
function TextOut()
{
this.fDebug = false;
this.sServerRoot = process.cwd();
this.sText = null;
this.nTabWidth = 8;
this.sTarget = "; ";
}
/*
* Class methods
*/
/**
* CLI()
*
* Provides the command-line interface for the TextOut module.
*
* Usage
* ---
* textout --file=({path}|{URL}) [--alignvert]
*
* Arguments
* ---
* --alignvert looks for tabs preceding certain characters (eg, ';') in the first line, and endeavors
* to ensure that the same tab+character combination(s) in all subsequent lines start at the same column.
*
* For now, all output is written to stdout only.
*
* Examples
* ---
* node modules/textout/bin/textout --file=devices/pc/bios/compaq/deskpro386/1988-01-28.nasm --alignvert
*/
TextOut.CLI = function()
{
var args = proc.getArgs();
if (!args.argc) {
console.log("usage: textout --file=({path}|{URL}) [--alignvert]");
return;
}
var argv = args.argv;
var sFile = argv['file'];
if (!sFile) {
TextOut.logError(new Error("bad or missing input filename"));
return;
}
var text = new TextOut();
text.loadFile(sFile, function(err) {
if (!err) {
if (argv['alignvert']) {
text.alignVertical();
}
text.outputText();
}
});
};
/**
* logError(err)
*
* Conditionally logs an error to the console.
*
* @param {Error} err
* @return {string} the error message that was logged (or that would have been logged had logging been enabled)
*/
TextOut.logError = function(err)
{
var sError = "";
if (err) {
sError = "textout error: " + err.message;
console.log(sError);
}
return sError;
};
/*
* Object methods
*/
/**
* loadFile(sFile, done)
*
* @this {TextOut}
* @param {string} sFile
* @param {function(Error)} done
*/
TextOut.prototype.loadFile = function(sFile, done)
{
var obj = this;
var options = {encoding: "utf8"};
var sFilePath = net.isRemote(sFile)? sFile : path.join(this.sServerRoot, sFile);
if (!this.sFilePath) this.sFilePath = sFilePath;
if (this.fDebug) console.log("loadFile(" + sFilePath + ")");
if (net.isRemote(sFilePath)) {
net.getFile(sFilePath, options.encoding, function(err, status, buf) {
if (err) {
TextOut.logError(err);
done(err);
return;
}
obj.setText(buf);
done(null);
});
} else {
fs.readFile(sFilePath, options, function(err, buf) {
if (err) {
TextOut.logError(err);
done(err);
return;
}
obj.setText(buf);
done(null);
});
}
};
/**
* setText(buf)
*
* Records the given file data in the TextOut's buffer
*
* @this {TextOut}
* @param {Buffer|string} buf
* @return {boolean}
*/
TextOut.prototype.setText = function(buf)
{
var b, i, j, s;
if (typeof buf == "string") {
this.sText = buf;
return true;
}
TextOut.logError(new Error("setText(): invalid data"));
return false;
};
/**
* alignVertical()
*
* @this {TextOut}
*/
TextOut.prototype.alignVertical = function()
{
if (!this.sText) return;
var asLines = this.sText.split('\n');
var iTarget = -1;
if (asLines.length) {
iTarget = this.findTarget(asLines[0]);
}
if (iTarget < 0) return;
if (this.fDebug) console.log("target vertical alignment: " + (iTarget + 1));
var iLine, fModified = false;
for (iLine = 1; iLine < asLines.length; iLine++) {
var iVictim;
var sLine = asLines[iLine];
var fModifiedLine = false;
while ((iVictim = this.findTarget(sLine)) != iTarget) {
if (iVictim < 0) break;
if (this.fDebug) console.log("line " + (iLine + 1) + ": current vertical alignment: " + (iVictim + 1));
if (iVictim > iTarget) {
if (!this.iTargetIndex) break;
var ch = sLine.charAt(this.iTargetIndex-1);
if (ch != ' ' && ch != '\t') break;
sLine = sLine.substr(0, this.iTargetIndex-1) + sLine.substr(this.iTargetIndex);
} else {
sLine = sLine.substr(0, this.iTargetIndex) + ' ' + sLine.substr(this.iTargetIndex);
}
fModifiedLine = true;
}
if (fModifiedLine) {
asLines[iLine] = sLine;
fModified = true;
}
}
if (fModified) {
this.sText = "";
for (iLine = 0; iLine < asLines.length; iLine++) {
if (this.sText) this.sText += '\n';
this.sText += asLines[iLine];
}
}
};
/**
* findTarget(sSrc, fDebug)
*
* This does not return the physical 0-based index of sTarget within sSrc, but rather the logical
* 0-based position, taking into account tab stops, based on the current nTabWidth setting.
*
* @this {TextOut}
* @param {string} sSrc
* @param {boolean} [fDebug]
* @return {number} logical position of sTarget within sSrc, -1 if not found
*/
TextOut.prototype.findTarget = function(sSrc, fDebug)
{
var i = 0, iPos = 0, iTarget;
if (fDebug) console.log('findTarget("' + sSrc + '")');
if ((iTarget = sSrc.indexOf(this.sTarget, i)) >= 0) {
/*
* i is a physical position, whereas iPos is the logical position (ie, taking into account tab stops),
* so we have to walk i up to iTarget, advancing iPos as we go.
*/
while (i < iTarget) {
var ch = sSrc.charAt(i++);
if (ch != '\t') {
iPos++;
} else {
iPos = iPos + (this.nTabWidth - (iPos % this.nTabWidth));
}
if (fDebug) console.log('\t"' + ch + '": index=' + (i - 1) + ', pos=' + iPos);
}
this.iTargetIndex = iTarget;
iTarget = iPos;
}
return iTarget;
};
/**
* outputText(sOutputFile, fOverwrite)
*
* @this {TextOut}
* @param {string} [sOutputFile]
* @param {boolean} [fOverwrite]
*/
TextOut.prototype.outputText = function(sOutputFile, fOverwrite)
{
if (this.sText) {
if (sOutputFile) {
try {
if (fs.existsSync(sOutputFile) && !fOverwrite) {
console.log(sOutputFile + " exists, use --overwrite to rewrite");
} else {
var sDirName = path.dirname(sOutputFile);
if (!fs.existsSync(sDirName)) mkdirp.sync(sDirName);
fs.writeFileSync(sOutputFile, this.sText);
console.log(this.sText.length + "-byte file saved as " + sOutputFile);
}
} catch(err) {
TextOut.logError(err);
}
} else {
console.log(this.sText);
}
}
};
module.exports = TextOut;

4
tests/pc/80386/makefile Normal file
View file

@ -0,0 +1,4 @@
all: tests.rom
tests.rom: tests.nasm
nasm -f bin tests.nasm -l tests.lst -o tests.rom

14
tests/pc/80386/tests.nasm Normal file
View file

@ -0,0 +1,14 @@
cpu 386
org 0x0000
section .text
bits 16
start: mov eax,0x11223344
mov edx,0x55667788
times 0xfff0-($-$$) db 0
bits 16
jmp 0xf000:start