583 lines
21 KiB
HTML
583 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" class="no-tui-scroll">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>IA86 Debugger</title>
|
|
<script src="../dist/tuicss.min.js"></script>
|
|
<script src="../dist/keystone-x86.min.js"></script>
|
|
<script src="../dist/keystone.min.js"></script>
|
|
<script src="../dist/jquery-2.2.0.min.js"></script>
|
|
<script src="../dist/download.js"></script>
|
|
<link rel="stylesheet" href="../dist/tuicss.min.css">
|
|
</head>
|
|
|
|
<body style="height: 100vh;">
|
|
<div class="tui-screen bordered tui-bg-blue-black" style="height: 100vh;">
|
|
|
|
<!-- Sidenav -->
|
|
<nav class="tui-sidenav absolute">
|
|
<ul>
|
|
<li>
|
|
<a href="/index.html">Reboot <span class="tui-shortcut">F10</span></a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<!-- Navbar -->
|
|
<nav class="tui-nav absolute">
|
|
<span class="tui-datetime" data-format="h:m:s a"></span>
|
|
<ul>
|
|
<li class="tui-sidenav-button red-168-text">≡</li>
|
|
<li class="tui-dropdown">
|
|
<span class="red-168-text">F</span>ile
|
|
<div class="tui-dropdown-content">
|
|
<ul>
|
|
<li>
|
|
<a href="javascript:newfile()">
|
|
<span class="red-168-text">N</span>ew
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:openfile()">
|
|
<span class="red-168-text">O</span>pen
|
|
<span class="tui-shortcut">F5</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:savefile()">
|
|
<span class="red-168-text">S</span>ave
|
|
<span class="tui-shortcut">F6</span>
|
|
</a>
|
|
</li>
|
|
<div class="tui-black-divider"></div>
|
|
<li>
|
|
<a href="javascript:importfile()">
|
|
<span class="red-168-text">I</span>mport
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:exportfile()">
|
|
<span class="red-168-text">Ex</span>port
|
|
</a>
|
|
</li>
|
|
<div class="tui-black-divider"></div>
|
|
<li>
|
|
<a href="/index.html">
|
|
<span class="red-168-text">Q</span>uit
|
|
<span class="tui-shortcut">F7</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</li>
|
|
<li class="tui-dropdown">
|
|
<span class="red-168-text">E</span>dit
|
|
<div class="tui-dropdown-content">
|
|
<ul>
|
|
<li>
|
|
<a href="javascript:">
|
|
<span class="red-168-text">C</span>ut
|
|
<span class="tui-shortcut">Ctrl+X</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:">
|
|
C<span class="red-168-text">o</span>py
|
|
<span class="tui-shortcut">Ctrl+C</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:">
|
|
<span class="red-168-text">P</span>aste
|
|
<span class="tui-shortcut">Ctrl+P</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:">
|
|
<span class="red-168-text">S</span>elect all
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:">
|
|
<span class="red-168-text">D</span>elete
|
|
</a>
|
|
</li>
|
|
<div class="tui-black-divider"></div>
|
|
<li>
|
|
<a href="/index.html">
|
|
<span class="red-168-text">F</span>ind
|
|
<span class="tui-shortcut">F3</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/index.html">
|
|
<span class="red-168-text">R</span>eplace
|
|
<span class="tui-shortcut">Alt+F3</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="/index.html">
|
|
<span class="red-168-text">G</span>oto
|
|
<span class="tui-shortcut">Ctrl+G</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</li>
|
|
<li class="tui-dropdown">
|
|
<span class="red-168-text">P</span>rogram
|
|
<div class="tui-dropdown-content">
|
|
<ul>
|
|
<li>
|
|
<a href="javascript:make()">
|
|
<span class="red-168-text">A</span>ssemble
|
|
<span class="tui-shortcut">F8</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:">
|
|
<span class="red-168-text">D</span>ebug
|
|
<span class="tui-shortcut">F9</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:download()">
|
|
<span class="red-168-text">D</span>ownload
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</li>
|
|
<li class="tui-dropdown">
|
|
<span class="red-168-text">O</span>ptions
|
|
<div class="tui-dropdown-content">
|
|
<ul>
|
|
<li class="tui-dropdown block">
|
|
<span class="right">►</span>
|
|
<span class="red-168-text">S</span>yntax
|
|
<div class="tui-dropdown-content">
|
|
<ul>
|
|
<li>
|
|
<a href="javascript:toSyntax('intel')">
|
|
<span id="intel">√</span> <span class="red-168-text">I</span>ntel
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:toSyntax('att')">
|
|
<span id="att"> </span> <span class="red-168-text">A</span>T&T
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="tui-dropdown block">
|
|
<span class="right">►</span>
|
|
<span class="red-168-text">R</span>esults
|
|
<div class="tui-dropdown-content">
|
|
<ul>
|
|
<li>
|
|
<a href="javascript:toResult('binary')">
|
|
<span id="binary">√</span> <span class="red-168-text">B</span>inary
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:toResult('string')">
|
|
<span id="string"> </span> C <span class="red-168-text">S</span>tring
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="javascript:toResult('array')">
|
|
<span id="array"> </span> C <span class="red-168-text">A</span>rray
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</li>
|
|
</li>
|
|
<li class="tui-dropdown">
|
|
<span class="red-168-text">H</span>elp
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<!-- Edit panel -->
|
|
<div class="tui-window full-width tui-no-shadow" style="margin-top: 23px;height:60%">
|
|
<fieldset class="tui-fieldset" style="height:100%">
|
|
<legend id="filename" class="tui-filed-text" style="margin-left:30px"></legend>
|
|
<span class="tui-fieldset-button"><span class="green-255-text">↑</span></span>
|
|
<span class="tui-fieldset-button left"><span class="green-255-text">■</span></span>
|
|
<span class="tui-fieldset-text right" style="margin-bottom: -5px;" id="syntax"> Syntax:Intel </span>
|
|
<textarea id="editor" class="tui-textarea full-width" style="overflow: scroll;height:100%;width:100%"></textarea></div>
|
|
|
|
<div class="tui-window tui-no-shadow" style="height:20%;width:1000px">
|
|
<fieldset class="tui-fieldset" style="height:100%">
|
|
<legend class="center">Results</legend>
|
|
<div id="result" class="" style="overflow: scroll;height:100%;width:100%"></div>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<div class="tui-window tui-no-shadow" style="height:20%;width:520px">
|
|
<fieldset class="tui-fieldset" style="height:100%">
|
|
<legend class="center">Memory zones</legend>
|
|
<div id="result2" class="" style="overflow: scroll;height:100%;width:100%"></div>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<div class="tui-window full-width tui-no-shadow" style="height:14%">
|
|
<fieldset class="tui-fieldset" style="height:100%">
|
|
<legend class="center">Status</legend>
|
|
<div id="status" class="full-width" style="overflow: scroll;height:100%"></div>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<!-- Status bar -->
|
|
<div class="tui-statusbar absolute">
|
|
<ul>
|
|
<li><a href="#!"><span class="red-168-text">F1</span> Help</a></li>
|
|
<li><a href="javascript:exportfile()"><span class="red-168-text">F2</span> Save</a></li>
|
|
<li><a href="javascript:importfile()"><span class="red-168-text">F3</span> Open</a></li>
|
|
<li><a href="javascript:make()"><span class="red-168-text">F8</span> Assemble</a></li>
|
|
<li><a href="javascript:make()"><span class="red-168-text">F9</span> Debug</a></li>
|
|
<span class="tui-statusbar-divider"></span>
|
|
<li><a href="/index.html"><span class="red-168-text">F10</span> Reboot</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<input id="file" type="file" hidden accept=".asm" onchange="realopen(this)"/>
|
|
</body>
|
|
<script>
|
|
var type='binary';
|
|
var syntax='intel';
|
|
var filename='';
|
|
var zones = [];
|
|
|
|
newfile();
|
|
|
|
function setFilename(name){
|
|
$("#filename").html(name);
|
|
filename=name;
|
|
}
|
|
|
|
function toSyntax(atype)
|
|
{
|
|
$("#att").html(" ");
|
|
$("#intel").html(" ");
|
|
if (atype=="att")
|
|
{
|
|
$("#att").html("√");
|
|
$("#syntax").html(" Syntax:AT&T ");
|
|
}
|
|
else
|
|
{
|
|
$("#intel").html("√");
|
|
$("#syntax").html(" Syntax:Intel ");
|
|
}
|
|
syntax=atype;
|
|
$("#result").html("");
|
|
}
|
|
|
|
function toResult(atype)
|
|
{
|
|
$("#array").html(" ");
|
|
$("#string").html(" ");
|
|
$("#binary").html(" ");
|
|
if (atype=="binary")
|
|
$("#binary").html("√");
|
|
else if (atype=="string")
|
|
$("#string").html("√");
|
|
else
|
|
$("#array").html("√");
|
|
type=atype;
|
|
$("#result").html("");
|
|
}
|
|
|
|
function newfile(){
|
|
$("#editor").val(".org 0000000\n.code 16\n.title vector\ndw 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x1233,0x4874,0x7847,0x1887,0x1887,0x1887\n.org 100000\n.title prog\n.code 32\nmov ax,1200\nmov esi,0x00000000\nmov edi,0x00000000\n.org 1000\nmov ecx,0x0000FFFF\nrep movsb\nhlt\n.org 1FFFFFFFF\n\.title 64bits\n.code 64\nmov rax,01");
|
|
$("#result").html("");
|
|
setFilename("new.asm");
|
|
}
|
|
|
|
function importfile(){
|
|
$("#file").trigger("click");
|
|
}
|
|
|
|
function exportfile(){
|
|
saveTextAsFile($("#editor").val(),file);
|
|
}
|
|
|
|
function download(){
|
|
if ($("#result").val()=="")
|
|
return
|
|
if (type=="array" || type=="string")
|
|
var ext=".c";
|
|
else
|
|
var ext=".bin";
|
|
saveTextAsFile($("#result").val, file+ext);
|
|
}
|
|
|
|
function saveTextAsFile(textToWrite, fileNameToSaveAs) {
|
|
var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
|
|
var downloadLink = document.createElement("a");
|
|
downloadLink.download = fileNameToSaveAs;
|
|
downloadLink.innerHTML = "Download File";
|
|
if (window.webkitURL != null) {
|
|
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
|
|
}
|
|
else {
|
|
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
|
|
downloadLink.onclick = destroyClickedElement;
|
|
downloadLink.style.display = "none";
|
|
document.body.appendChild(downloadLink);
|
|
}
|
|
downloadLink.click();
|
|
}
|
|
|
|
function realopen(file)
|
|
{
|
|
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
|
|
alert('The File APIs are not fully supported in this browser.');
|
|
return;
|
|
}
|
|
if (! file.files[0]) {
|
|
alert("Please select a file before clicking 'Load'");
|
|
return
|
|
}
|
|
else {
|
|
file = file.files[0];
|
|
var fr = new FileReader();
|
|
fr.readAsText(file);
|
|
fr.onload = function() {
|
|
$("#editor").val(fr.result);
|
|
$("#result").val("");
|
|
$("#legend").val(file);
|
|
};
|
|
}
|
|
};
|
|
|
|
function hexQword(value) {
|
|
value = value < 0 ? (value + 0x10000000000000000) : (value);
|
|
var str = '0000000000000000' + value.toString(16).toUpperCase();
|
|
return str.slice(-16);
|
|
};
|
|
|
|
function hexDword(value) {
|
|
value = value < 0 ? (value + 0x100000000) : (value);
|
|
var str = '00000000' + value.toString(16).toUpperCase();
|
|
return str.slice(-8);
|
|
};
|
|
|
|
function hexWord(value) {
|
|
value = value < 0 ? (value + 0x10000) : (value);
|
|
var str = '0000' + value.toString(16).toUpperCase();
|
|
return str.slice(-4);
|
|
};
|
|
|
|
function hexByte(value) {
|
|
value = value < 0 ? (value + 0x100) : (value);
|
|
var str = '00' + value.toString(16).toUpperCase();
|
|
return str.slice(-2);
|
|
};
|
|
|
|
function dumpall(zones)
|
|
{
|
|
if (type=="binary")
|
|
var output = '<table class="">';
|
|
else
|
|
var output = '';
|
|
for (const zone of zones)
|
|
output+=dump(zone);
|
|
if (type=="binary")
|
|
output += '</table>';
|
|
showresult(output);
|
|
}
|
|
|
|
function dump(zone) {
|
|
var mcLen = zone.asm.length;
|
|
if (type=="binary")
|
|
var output = '<tr>';
|
|
else
|
|
var output = '';
|
|
switch (type) {
|
|
case 'binary':
|
|
var address=zone.offset;
|
|
for (var offset = 0; offset < mcLen; offset += 16) {
|
|
output += "<td>"+toHex(address,zone.code)+"</td><td> | </td><td>";
|
|
var ascii='';
|
|
for (var i = offset; i < offset + 16 && i < mcLen; i++) {
|
|
if (zone.asm[i]>31)
|
|
ascii += String.fromCharCode(zone.asm[i]);
|
|
else
|
|
ascii += '.';
|
|
output += hexByte(zone.asm[i]) + " ";
|
|
}
|
|
output += "</td><td> | </td><td>"+ascii+"</td></tr>";
|
|
address+=16;
|
|
}
|
|
break;
|
|
case 'array':
|
|
output += "const uint8_t buffer[] = {\n";
|
|
for (var offset = 0; offset < mcLen; offset += 8) {
|
|
output += " ";
|
|
for (var i = offset; i < offset + 8 && i < mcLen; i++) {
|
|
output += "0x" + hexByte(zone.asm[i]) + ", ";
|
|
}
|
|
output = output.substring(0, output.length - 1);
|
|
output += "\n";
|
|
}
|
|
output = output.substring(0, output.length - 2);
|
|
output += "\n};\n";
|
|
break;
|
|
case 'string':
|
|
output += "const char* buffer =\n";
|
|
for (var offset = 0; offset < mcLen; offset += 16) {
|
|
output += " \"";
|
|
for (var i = offset; i < offset + 16 && i < mcLen; i++) {
|
|
output += "\\x" + hexByte(zone.asm[i]);
|
|
}
|
|
output += "\"\n";
|
|
}
|
|
output = output.substring(0, output.length - 1);
|
|
output += ";\n";
|
|
break;
|
|
}
|
|
return output;
|
|
}
|
|
|
|
function showzones(zones)
|
|
{
|
|
table='<table class="tui-table striped-purple"><thead><tr><th>Id</th><th>Title</th><th>Offset</th><th>Size</th><th>Type</th><th>Compiled</th></tr></thead>';
|
|
for (const zone of zones)
|
|
table+="<tr><td align='right'>"+zone.id+"</td><td align='left'>"+zone.title+"</td><td align='right'>"+zone.realoffset+"</td><td align='right'>"+zone.asm.length+"</td><td align='right'>"+zone.code+"</td><td align='right'>"+(zone.asm.length>0)+"</td></tr>";
|
|
table+="</table>"
|
|
$("#result2").html(table);
|
|
}
|
|
|
|
function make()
|
|
{
|
|
var assembly = $("#editor").val();
|
|
var id=0;
|
|
var org=0;
|
|
var type=32;
|
|
var zones=[];
|
|
var status=true;
|
|
showresult('');
|
|
while (assembly.length!=0)
|
|
{
|
|
pos=assembly.search(/\.org [0-9A-F]+/);
|
|
offset=org;
|
|
if (pos==0)
|
|
{
|
|
pos=assembly.search(/\n/);
|
|
org=parseInt(assembly.substring(5,pos),16);
|
|
assembly=assembly.substring(pos+1,assembly.lenght);
|
|
continue;
|
|
}
|
|
else if (pos==-1)
|
|
{
|
|
pos=assembly.length;
|
|
src=assembly.substring(0,pos);
|
|
assembly='';
|
|
}
|
|
else
|
|
{
|
|
src=assembly.substring(0,pos);
|
|
assembly=assembly.substring(pos,assembly.length);
|
|
pos=assembly.search(/\n/);
|
|
org=parseInt(assembly.substring(5,pos),16);
|
|
assembly=assembly.substring(pos+1,assembly.length);
|
|
}
|
|
pos=src.search(/\.title [0-9a-zZ-Z]+/);
|
|
if (pos>-1)
|
|
{
|
|
title=src.substring(pos,src.length);
|
|
pos=title.search(/\n/);
|
|
title=title.substring(7,pos);
|
|
}
|
|
else
|
|
title='notitle';
|
|
pos=src.search(/\.code [0-9]+/);
|
|
if (pos>-1)
|
|
{
|
|
code=src.substring(pos,src.length);
|
|
pos=code.search(/\n/);
|
|
code=parseInt(code.substring(6,pos),10);
|
|
}
|
|
if (code!=16 && code!=32 && code!=64)
|
|
code=32;
|
|
zone={"id":id,"offset":offset,"src":src,"size":0,"title":title,"code":code,"asm":[]};
|
|
if (assemble(zone)==true)
|
|
{
|
|
zones.push(zone);
|
|
dumpall(zones);
|
|
showzones(zones);
|
|
}
|
|
else
|
|
{
|
|
zones.push(zone);
|
|
showzones(zones);
|
|
return;
|
|
}
|
|
id++;
|
|
}
|
|
showstatus("Project is built");
|
|
}
|
|
|
|
function showstatus(text)
|
|
{
|
|
$("#status").html($("#status").html()+text+"<br>");
|
|
$("#status").scrollTop($("#status")[0].scrollHeight);
|
|
}
|
|
|
|
function showresult(text)
|
|
{
|
|
$("#result").html(text);
|
|
}
|
|
|
|
function toHex(hexa,code)
|
|
{
|
|
if (code==16)
|
|
result=hexWord(hexa);
|
|
else if (code==32)
|
|
result=hexDword(hexa);
|
|
else
|
|
result=hexQword(hexa);
|
|
return result;
|
|
}
|
|
|
|
function assemble(zone)
|
|
{
|
|
if (zone.code==16)
|
|
realtype=ks.MODE_16;
|
|
else if (zone.code==32)
|
|
realtype=ks.MODE_32;
|
|
else
|
|
realtype=ks.MODE_64;
|
|
zone.realoffset=toHex(zone.offset,zone.code);
|
|
allstatus="Assembling zone "+zone.id+":"+zone.title+"@"+zone.realoffset+" ("+zone.code+"bits) => ";
|
|
a = new ks.Keystone(ks.ARCH_X86, realtype);
|
|
if (syntax=="att")
|
|
a.option(ks.OPT_SYNTAX, ks.OPT_SYNTAX_ATT);
|
|
else
|
|
a.option(ks.OPT_SYNTAX, ks.OPT_SYNTAX_NASM);
|
|
try
|
|
{
|
|
zone.asm = a.asm(zone.src, zone.offset);
|
|
allstatus+="DONE";
|
|
showstatus(allstatus);
|
|
a.close();
|
|
return true;
|
|
}
|
|
catch(err)
|
|
{
|
|
zone.asm = [];
|
|
allstatus+="ERROR: "+err;
|
|
showstatus(allstatus);
|
|
a.close();
|
|
return false;
|
|
}
|
|
}
|
|
</script>
|
|
</html>
|