Playing with NASM
This commit is contained in:
parent
29d5f078a7
commit
96a39c9bbe
8 changed files with 15310 additions and 2 deletions
|
|
@ -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
|
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
|
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
|
### Errata
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ However, don't use that technique to check for optional parameters:
|
||||||
|
|
||||||
if (!parameter) { ... }
|
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
|
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.
|
those problems go away by artificially limiting your choice of operators seems like the wrong solution.
|
||||||
|
|
|
||||||
14924
devices/pc/bios/compaq/deskpro386/1988-01-28.nasm
Normal file
14924
devices/pc/bios/compaq/deskpro386/1988-01-28.nasm
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
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
|
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.
|
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....
|
||||||
|
|
|
||||||
40
modules/textout/bin/textout
Normal file
40
modules/textout/bin/textout
Normal 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();
|
||||||
309
modules/textout/lib/textout.js
Normal file
309
modules/textout/lib/textout.js
Normal 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
4
tests/pc/80386/makefile
Normal 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
14
tests/pc/80386/tests.nasm
Normal 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
|
||||||
Loading…
Reference in a new issue