PCjs can now connect a serial port to the console
This commit is contained in:
parent
0cc582405d
commit
464219a4c1
6 changed files with 367 additions and 117 deletions
|
|
@ -1,12 +1,15 @@
|
||||||
{
|
{
|
||||||
|
"machine": {
|
||||||
|
"id": "ibm5150"
|
||||||
|
},
|
||||||
"computer": {
|
"computer": {
|
||||||
"id": "ibm5150.pc-mda-64k",
|
"id": "pc-mda-64k",
|
||||||
"name": "IBM PC",
|
"name": "IBM PC",
|
||||||
"resume": "1",
|
"resume": "1",
|
||||||
"state": ""
|
"state": ""
|
||||||
},
|
},
|
||||||
"ram": [
|
"ram": [
|
||||||
{ "id": "ibm5150.ramLow",
|
{ "id": "ramLow",
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 0x00000,
|
"addr": 0x00000,
|
||||||
"size": 0,
|
"size": 0,
|
||||||
|
|
@ -14,14 +17,14 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rom": [
|
"rom": [
|
||||||
{ "id": "ibm5150.romBASIC",
|
{ "id": "romBASIC",
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 0xf6000,
|
"addr": 0xf6000,
|
||||||
"size": 0x08000,
|
"size": 0x08000,
|
||||||
"file": "/devices/pc/basic/ibm-basic-1.00.json",
|
"file": "/devices/pc/basic/ibm-basic-1.00.json",
|
||||||
"notify": ""
|
"notify": ""
|
||||||
},
|
},
|
||||||
{ "id": "ibm5150.romBIOS",
|
{ "id": "romBIOS",
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 0xfe000,
|
"addr": 0xfe000,
|
||||||
"size": 0x02000,
|
"size": 0x02000,
|
||||||
|
|
@ -30,7 +33,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"video": [
|
"video": [
|
||||||
{ "id": "ibm5150.videoMDA",
|
{ "id": "videoMDA",
|
||||||
"name": "Monochrome Display",
|
"name": "Monochrome Display",
|
||||||
"model": "",
|
"model": "",
|
||||||
"mode": 7,
|
"mode": 7,
|
||||||
|
|
@ -45,7 +48,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"cpu": {
|
"cpu": {
|
||||||
"id": "ibm5150.cpu8088",
|
"id": "cpu8088",
|
||||||
"name": "",
|
"name": "",
|
||||||
"model": 8088,
|
"model": 8088,
|
||||||
"clock": 0,
|
"clock": 0,
|
||||||
|
|
@ -56,12 +59,12 @@
|
||||||
"csStop": -1
|
"csStop": -1
|
||||||
},
|
},
|
||||||
"keyboard": {
|
"keyboard": {
|
||||||
"id": "ibm5150.keyboard",
|
"id": "keyboard",
|
||||||
"name": "",
|
"name": "",
|
||||||
"model": ""
|
"model": ""
|
||||||
},
|
},
|
||||||
"fdc": {
|
"fdc": {
|
||||||
"id": "ibm5150.fdcNEC",
|
"id": "fdcNEC",
|
||||||
"name": "",
|
"name": "",
|
||||||
"autoMount": {
|
"autoMount": {
|
||||||
"A": {
|
"A": {
|
||||||
|
|
@ -75,7 +78,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chipset": {
|
"chipset": {
|
||||||
"id": "ibm5150.chipset",
|
"id": "chipset",
|
||||||
"name": "",
|
"name": "",
|
||||||
"model": "5150",
|
"model": "5150",
|
||||||
"sw1": "01000001",
|
"sw1": "01000001",
|
||||||
|
|
@ -83,7 +86,7 @@
|
||||||
"sound": true
|
"sound": true
|
||||||
},
|
},
|
||||||
"debugger": {
|
"debugger": {
|
||||||
"id": "ibm5150.debugger",
|
"id": "debugger",
|
||||||
"name": "",
|
"name": "",
|
||||||
"messages": ""
|
"messages": ""
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -217,8 +217,25 @@ function loadMachine(sFile)
|
||||||
* in the browser, by walking the list of PCjs components we loaded above and looking for
|
* in the browser, by walking the list of PCjs components we loaded above and looking for
|
||||||
* matches.
|
* matches.
|
||||||
*/
|
*/
|
||||||
|
var idMachine = "";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 'machine' is a pseudo-component that is only used to define an ID for the entire machine;
|
||||||
|
* if it exists, then that ID is prepended to every component ID, just as our XSLT code would
|
||||||
|
* do for a machine XML file. This relieves the JSON file from having to manually prepend
|
||||||
|
* a machine ID to every component ID itself.
|
||||||
|
*
|
||||||
|
* This doesn't mean I anticipate a Node environment running multiple machines, as we do in
|
||||||
|
* a browser; it only means that I'm trying to make both environments operate similarly.
|
||||||
|
*/
|
||||||
|
if (machine['machine']) {
|
||||||
|
idMachine = machine['machine']['id'];
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < aComponents.length; i++) {
|
for (i = 0; i < aComponents.length; i++) {
|
||||||
var parms = machine[aComponents[i].name];
|
|
||||||
|
var component = aComponents[i];
|
||||||
|
var parms = machine[component.name];
|
||||||
/*
|
/*
|
||||||
* If parms is undefined, it means there is no component with that name defined in the
|
* If parms is undefined, it means there is no component with that name defined in the
|
||||||
* machine object (NOT that the component has no parms), and therefore we should skip it.
|
* machine object (NOT that the component has no parms), and therefore we should skip it.
|
||||||
|
|
@ -233,22 +250,27 @@ function loadMachine(sFile)
|
||||||
for (j = 0; j < aParms.length; j++) {
|
for (j = 0; j < aParms.length; j++) {
|
||||||
|
|
||||||
var obj;
|
var obj;
|
||||||
if (fDebug) console.log("creating " + aComponents[i].name + "...");
|
var parmsObj = aParms[j];
|
||||||
if (fDebug) console.log(aParms[j]);
|
if (idMachine) parmsObj['id'] = idMachine + '.' + parmsObj['id'];
|
||||||
|
|
||||||
if (aComponents[i].name == "cpu") {
|
if (fDebug) {
|
||||||
aParms[j]['autoStart'] = false;
|
console.log("creating " + component.name + "...");
|
||||||
|
console.log(parmsObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.name == "cpu") {
|
||||||
|
parmsObj['autoStart'] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
obj = new aComponents[i].Create(aParms[j]);
|
obj = new component.Create(parmsObj);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.log("error creating " + aComponents[i].name + ": " + err.message);
|
console.log("error creating " + component.name + ": " + err.message);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(obj['id'] + " object created");
|
console.log(obj['id'] + " object created");
|
||||||
aComponents[i].objects.push(obj);
|
component.objects.push(obj);
|
||||||
|
|
||||||
if (obj.type == "Debugger") {
|
if (obj.type == "Debugger") {
|
||||||
dbg = obj;
|
dbg = obj;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
{
|
{
|
||||||
|
"machine": {
|
||||||
|
"id": "pc386"
|
||||||
|
},
|
||||||
"computer": {
|
"computer": {
|
||||||
"id": "pc386.computer",
|
"id": "computer",
|
||||||
"name": "Compaq DeskPro 386",
|
"name": "Compaq DeskPro 386",
|
||||||
"resume": 0,
|
"resume": 0,
|
||||||
"state": "",
|
"state": "",
|
||||||
"busWidth": 32
|
"busWidth": 32
|
||||||
},
|
},
|
||||||
"ram": [
|
"ram": [
|
||||||
{ "id": "pc386.ramLow",
|
{ "id": "ramLow",
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 0,
|
"addr": 0,
|
||||||
"size": 655360,
|
"size": 655360,
|
||||||
|
|
@ -15,17 +18,17 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rom": [
|
"rom": [
|
||||||
{ "id": "pc386.romTests",
|
{ "id": "test386",
|
||||||
"name": "",
|
"name": "",
|
||||||
"addr": 983296,
|
"addr": 983296,
|
||||||
"size": 65280,
|
"size": 65280,
|
||||||
"alias": 4294902016,
|
"alias": 4294902016,
|
||||||
"file": "/tests/pc/80386/tests.json",
|
"file": "/tests/pc/80386/test386.json",
|
||||||
"notify": ""
|
"notify": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"video": [
|
"video": [
|
||||||
{ "id": "pc386.videoMDA",
|
{ "id": "videoMDA",
|
||||||
"name": "Monochrome Display",
|
"name": "Monochrome Display",
|
||||||
"model": "",
|
"model": "",
|
||||||
"mode": 7,
|
"mode": 7,
|
||||||
|
|
@ -40,7 +43,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"cpu": {
|
"cpu": {
|
||||||
"id": "pc386.cpu",
|
"id": "cpu",
|
||||||
"name": "",
|
"name": "",
|
||||||
"model": 80386,
|
"model": 80386,
|
||||||
"clock": 0,
|
"clock": 0,
|
||||||
|
|
@ -51,12 +54,12 @@
|
||||||
"csStop": -1
|
"csStop": -1
|
||||||
},
|
},
|
||||||
"keyboard": {
|
"keyboard": {
|
||||||
"id": "pc386.keyboard",
|
"id": "keyboard",
|
||||||
"name": "",
|
"name": "",
|
||||||
"model": ""
|
"model": ""
|
||||||
},
|
},
|
||||||
"fdc": {
|
"fdc": {
|
||||||
"id": "pc386.fdcNEC",
|
"id": "fdcNEC",
|
||||||
"name": "",
|
"name": "",
|
||||||
"autoMount": {
|
"autoMount": {
|
||||||
"A": {
|
"A": {
|
||||||
|
|
@ -70,13 +73,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chipset": {
|
"chipset": {
|
||||||
"id": "pc386.chipset",
|
"id": "chipset",
|
||||||
"name": "",
|
"name": "",
|
||||||
"model": "deskpro386",
|
"model": "deskpro386",
|
||||||
"sound": false
|
"sound": false
|
||||||
|
},
|
||||||
|
"serialport": {
|
||||||
|
"id": "com2",
|
||||||
|
"adapter": 2,
|
||||||
|
"binding": "console"
|
||||||
},
|
},
|
||||||
"debugger": {
|
"debugger": {
|
||||||
"id": "pc386.debugger",
|
"id": "debugger",
|
||||||
"name": "",
|
"name": "",
|
||||||
"commands": "",
|
"commands": "",
|
||||||
"messages": ""
|
"messages": ""
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
if (NODE) {
|
if (NODE) {
|
||||||
|
var str = require("../../shared/lib/strlib");
|
||||||
var web = require("../../shared/lib/weblib");
|
var web = require("../../shared/lib/weblib");
|
||||||
var Component = require("../../shared/lib/component");
|
var Component = require("../../shared/lib/component");
|
||||||
var Messages = require("./messages");
|
var Messages = require("./messages");
|
||||||
|
|
@ -79,9 +80,17 @@ function SerialPort(parmsSerial) {
|
||||||
Component.warning("Unrecognized serial adapter #" + this.iAdapter);
|
Component.warning("Unrecognized serial adapter #" + this.iAdapter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* consoleOutput becomes a string that records serial port output if the 'binding' property is set to the
|
||||||
|
* reserved name "console". Nothing is written to the console, however, until a linefeed (0x0A) is output
|
||||||
|
* or the string length reaches a threshold (currently, 1024 characters).
|
||||||
|
*
|
||||||
|
* @type {string|null}
|
||||||
|
*/
|
||||||
|
this.consoleOutput = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* controlIOBuffer is a DOM element, if any, bound to the port (currently for output purposes only; see echoByte())
|
* controlIOBuffer is a DOM element, if any, bound to the port (currently used for output only; see echoByte()).
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
@ -89,7 +98,15 @@ function SerialPort(parmsSerial) {
|
||||||
|
|
||||||
Component.call(this, "SerialPort", parmsSerial, SerialPort, Messages.SERIAL);
|
Component.call(this, "SerialPort", parmsSerial, SerialPort, Messages.SERIAL);
|
||||||
|
|
||||||
Component.bindExternalControl(this, parmsSerial['binding'], SerialPort.sIOBuffer);
|
var sBinding = parmsSerial['binding'];
|
||||||
|
if (sBinding == "console") {
|
||||||
|
this.consoleOutput = "";
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* NOTE: If sBinding is not the name of a valid Control Panel DOM element, this call does nothing.
|
||||||
|
*/
|
||||||
|
Component.bindExternalControl(this, sBinding, SerialPort.sIOBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -787,6 +804,14 @@ SerialPort.prototype.echoByte = function(b)
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (this.consoleOutput != null) {
|
||||||
|
this.consoleOutput += String.fromCharCode(b);
|
||||||
|
if (b == 0x0A || this.consoleOutput.length >= 1024) {
|
||||||
|
this.println(str.trim(this.consoleOutput));
|
||||||
|
this.consoleOutput = "";
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
all: tests.json
|
all: test386.json
|
||||||
|
|
||||||
tests.com: tests.nasm ../inc/dos.inc ../inc/misc.inc ../inc/x86.inc
|
test386.com: test386.nasm ../inc/dos.inc ../inc/misc.inc ../inc/x86.inc
|
||||||
nasm -i../inc/ -f bin tests.nasm -l tests.lst -o tests.com
|
nasm -i../inc/ -f bin test386.nasm -l test386.lst -o test386.com
|
||||||
|
|
||||||
tests.json: tests.com
|
test386.json: test386.com
|
||||||
node ../../../modules/filedump/bin/filedump --file=tests.com --output=tests.json --overwrite
|
node ../../../modules/filedump/bin/filedump --file=test386.com --output=test386.json --overwrite
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,32 @@
|
||||||
;
|
;
|
||||||
|
; test386.nasm
|
||||||
|
; Copyright © 2012-2015 Jeff Parsons <Jeff@pcjs.org>
|
||||||
|
;
|
||||||
|
; This file is part of PCjs, which is part of the JavaScript Machines Project (aka JSMachines)
|
||||||
|
; at <http://jsmachines.net/> and <http://pcjs.org/>.
|
||||||
|
;
|
||||||
|
; PCjs 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.
|
||||||
|
;
|
||||||
|
; PCjs 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 PCjs. 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 PCjs 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
|
||||||
|
; PCjs program for purposes of the GNU General Public License, and the author does not claim
|
||||||
|
; any copyright as to their contents.
|
||||||
|
;
|
||||||
|
; Overview
|
||||||
|
; --------
|
||||||
; This file is designed to run both as a test ROM and as a DOS COM file (hence the "org 0x100"),
|
; This file is designed to run both as a test ROM and as a DOS COM file (hence the "org 0x100"),
|
||||||
; which is why it has a ".com" extension instead of the more typical ".rom" extension.
|
; which is why it has a ".com" extension instead of the more typical ".rom" extension.
|
||||||
;
|
;
|
||||||
|
|
@ -464,6 +492,8 @@ toProt32:
|
||||||
;
|
;
|
||||||
; Now run a series of unverified opcode tests (verification will happen later, by comparing the output of the tests)
|
; Now run a series of unverified opcode tests (verification will happen later, by comparing the output of the tests)
|
||||||
;
|
;
|
||||||
|
int3
|
||||||
|
cld
|
||||||
mov esi,tableOps ; ESI -> tableOps entry
|
mov esi,tableOps ; ESI -> tableOps entry
|
||||||
testOps:
|
testOps:
|
||||||
movzx ecx,byte [cs:esi] ; ECX == length of instruction sequence
|
movzx ecx,byte [cs:esi] ; ECX == length of instruction sequence
|
||||||
|
|
@ -472,8 +502,12 @@ testOps:
|
||||||
shl ebx,5 ; EBX == type * 32
|
shl ebx,5 ; EBX == type * 32
|
||||||
movzx edx,byte [cs:esi+2] ; EDX == SIZE
|
movzx edx,byte [cs:esi+2] ; EDX == SIZE
|
||||||
lea ebx,[cs:typeValues+ebx+edx*8] ; EBX -> values for type
|
lea ebx,[cs:typeValues+ebx+edx*8] ; EBX -> values for type
|
||||||
add esi,3 ; ESI -> instruction sequence to test
|
add esi,3 ; ESI -> instruction mnemonic
|
||||||
|
skipOp: cs lodsb
|
||||||
|
test al,al
|
||||||
|
jnz skipOp
|
||||||
|
|
||||||
|
xor eax,eax ; set flags to known values prior tests
|
||||||
push ecx
|
push ecx
|
||||||
mov ecx,[cs:ebx] ; ECX == count of values for dst
|
mov ecx,[cs:ebx] ; ECX == count of values for dst
|
||||||
mov ebx,[cs:ebx+4] ; EBX -> values for dst
|
mov ebx,[cs:ebx+4] ; EBX -> values for dst
|
||||||
|
|
@ -482,17 +516,29 @@ testOps:
|
||||||
testDst:
|
testDst:
|
||||||
push ebp
|
push ebp
|
||||||
push edi
|
push edi
|
||||||
|
pushfd
|
||||||
testSrc:
|
testSrc:
|
||||||
mov eax,[cs:ebx] ; EAX == dst
|
mov eax,[cs:ebx] ; EAX == dst
|
||||||
mov edx,[cs:edi] ; EDX == src
|
mov edx,[cs:edi] ; EDX == src
|
||||||
call esi
|
popfd
|
||||||
|
call printOp
|
||||||
|
call printEAX
|
||||||
|
call printEDX
|
||||||
|
call printPS
|
||||||
|
call esi ; execute the instruction sequence
|
||||||
|
call printEAX
|
||||||
|
call printEDX
|
||||||
|
call printPS
|
||||||
|
call printEOL
|
||||||
|
pushfd
|
||||||
add edi,4 ; EDI -> next src
|
add edi,4 ; EDI -> next src
|
||||||
dec ebp ; decrement src count
|
dec ebp ; decrement src count
|
||||||
jnz testSrc
|
jnz testSrc
|
||||||
|
|
||||||
|
popfd
|
||||||
pop edi ; ESI -> restored values for src
|
pop edi ; ESI -> restored values for src
|
||||||
pop ebp ; EBP == restored count of values for src
|
pop ebp ; EBP == restored count of values for src
|
||||||
add ebx,4 ; EBX -> next dst
|
lea ebx,[ebx+4] ; EBX -> next dst (without modifying flags)
|
||||||
loop testDst
|
loop testDst
|
||||||
|
|
||||||
pop ecx
|
pop ecx
|
||||||
|
|
@ -502,32 +548,178 @@ testSrc:
|
||||||
doneOps:
|
doneOps:
|
||||||
jmp doneProt
|
jmp doneProt
|
||||||
|
|
||||||
|
;
|
||||||
|
; printOp(ESI -> instruction sequence)
|
||||||
|
;
|
||||||
|
; Rewinds ESI to the start of the mnemonic preceding the instruction sequence and prints the mnemonic
|
||||||
|
;
|
||||||
|
; Uses: None
|
||||||
|
;
|
||||||
|
printOp:
|
||||||
|
pushfd
|
||||||
|
pushad
|
||||||
|
findOp: dec esi
|
||||||
|
mov al,[cs:esi-1]
|
||||||
|
cmp al,32
|
||||||
|
jae findOp
|
||||||
|
call printStr
|
||||||
|
mov al,' '
|
||||||
|
call printChar
|
||||||
|
popad
|
||||||
|
popfd
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; printEAX()
|
||||||
|
;
|
||||||
|
; Uses: None
|
||||||
|
;
|
||||||
|
printEAX:
|
||||||
|
pushfd
|
||||||
|
pushad
|
||||||
|
mov esi,strEAX
|
||||||
|
call printStr
|
||||||
|
mov cl,8
|
||||||
|
call printVal
|
||||||
|
popad
|
||||||
|
popfd
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; printEDX()
|
||||||
|
;
|
||||||
|
; Uses: None
|
||||||
|
;
|
||||||
|
printEDX:
|
||||||
|
pushfd
|
||||||
|
pushad
|
||||||
|
mov esi,strEDX
|
||||||
|
call printStr
|
||||||
|
mov cl,8
|
||||||
|
mov eax,edx
|
||||||
|
call printVal
|
||||||
|
popad
|
||||||
|
popfd
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; printPS()
|
||||||
|
;
|
||||||
|
; Uses: None
|
||||||
|
;
|
||||||
|
printPS:
|
||||||
|
pushfd
|
||||||
|
pushad
|
||||||
|
pushfd
|
||||||
|
pop eax
|
||||||
|
mov esi,strPS
|
||||||
|
call printStr
|
||||||
|
mov cl,4
|
||||||
|
call printVal
|
||||||
|
popad
|
||||||
|
popfd
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; printEOL()
|
||||||
|
;
|
||||||
|
; Uses: None
|
||||||
|
;
|
||||||
|
printEOL:
|
||||||
|
pushfd
|
||||||
|
pushad
|
||||||
|
mov al,0x0d
|
||||||
|
call printChar
|
||||||
|
mov al,0x0a
|
||||||
|
call printChar
|
||||||
|
popad
|
||||||
|
popfd
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; printChar(AL)
|
||||||
|
;
|
||||||
|
; Uses: None
|
||||||
|
;
|
||||||
|
printChar:
|
||||||
|
push edx
|
||||||
|
mov dx,0x2F8 ; EDX -> COM2 I/O port
|
||||||
|
out dx,al
|
||||||
|
pop edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; printStr(ESI -> zero-terminated string)
|
||||||
|
;
|
||||||
|
; Uses: ESI, Flags
|
||||||
|
;
|
||||||
|
printStr:
|
||||||
|
push eax
|
||||||
|
psLoop: cs lodsb
|
||||||
|
test al,al
|
||||||
|
jz psDone
|
||||||
|
call printChar
|
||||||
|
jmp psLoop
|
||||||
|
psDone: pop eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; printVal(EAX == value, CL == number of hex digits)
|
||||||
|
;
|
||||||
|
; Uses: EAX, ECX, Flags
|
||||||
|
;
|
||||||
|
printVal:
|
||||||
|
shl cl,2 ; CL == number of bits (4 times the number of hex digits)
|
||||||
|
jz pvDone
|
||||||
|
pvLoop: sub cl,4
|
||||||
|
push eax
|
||||||
|
shr eax,cl
|
||||||
|
and al,0x0f
|
||||||
|
add al,'0'
|
||||||
|
cmp al,'9'
|
||||||
|
jbe pvOK
|
||||||
|
add al,'A'-'0'-10
|
||||||
|
pvOK: call printChar
|
||||||
|
pop eax
|
||||||
|
test cl,cl
|
||||||
|
jnz pvLoop
|
||||||
|
pvDone: mov al,' '
|
||||||
|
call printChar
|
||||||
|
ret
|
||||||
|
|
||||||
TYPE_ARITH equ 0
|
TYPE_ARITH equ 0
|
||||||
|
|
||||||
SIZE_BYTE equ 0
|
SIZE_BYTE equ 0
|
||||||
SIZE_SHORT equ 1
|
SIZE_SHORT equ 1
|
||||||
SIZE_LONG equ 2
|
SIZE_LONG equ 2
|
||||||
|
|
||||||
%macro defOp 4
|
%macro defOp 5
|
||||||
%ifidn %2,al
|
%ifidni %3,al
|
||||||
%assign size SIZE_BYTE
|
%assign size SIZE_BYTE
|
||||||
%elifidn %2,ax
|
%elifidni %3,ax
|
||||||
%assign size SIZE_SHORT
|
%assign size SIZE_SHORT
|
||||||
%else
|
%else
|
||||||
%assign size SIZE_LONG
|
%assign size SIZE_LONG
|
||||||
%endif
|
%endif
|
||||||
db %%end-%%beg,%4,size
|
db %%end-%%beg,%5,size
|
||||||
%%beg: %1 %2,%3
|
%%name: db %1,0
|
||||||
|
%%beg: %2 %3,%4
|
||||||
ret
|
ret
|
||||||
%%end:
|
%%end:
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
strEAX: db "EAX=",0
|
||||||
|
strEDX: db "EDX=",0
|
||||||
|
strPS: db "PS=",0
|
||||||
|
|
||||||
tableOps:
|
tableOps:
|
||||||
defOp add,al,dl,TYPE_ARITH
|
defOp "ADD",ADD,AL,DL,TYPE_ARITH
|
||||||
defOp add,ax,dx,TYPE_ARITH
|
defOp "ADD",ADD,AX,DX,TYPE_ARITH
|
||||||
defOp add,eax,edx,TYPE_ARITH
|
defOp "ADD",ADD,EAX,EDX,TYPE_ARITH
|
||||||
db 0
|
db 0
|
||||||
|
|
||||||
|
align 4
|
||||||
|
|
||||||
typeValues:
|
typeValues:
|
||||||
dd 9,arithValues,18,arithValues,27,arithValues,0,0
|
dd 9,arithValues,18,arithValues,27,arithValues,0,0
|
||||||
|
|
||||||
Loading…
Reference in a new issue