5150/wozmon.cc

152 lines
2.9 KiB
C++

#include <cstdint>
namespace {
uint8_t getc() {
register uint8_t c asm ("al");
asm volatile (
"mov $0x00, %%ah\n"
"int $0x16\n"
: "=r" (c)
);
return c;
}
void putc(uint8_t c) {
asm volatile (
"mov %0, %%al\n"
"mov $0x0e, %%ah\n"
"int $0x10\n"
:: "r" (c)
);
}
void Jump(uint32_t addr) {
auto jump = reinterpret_cast<void (*)()>(addr);
jump();
}
constexpr uint8_t kBackspace = 0x7f;
constexpr uint8_t kOtherBackspace = 0x08;
uint8_t ReadHexNibble(uint8_t c) {
// lowercase only
if (c <= '9') {
return c - '0';
}
return 10 + (c - 'a');
}
uint32_t ReadHex(const char* buf) {
uint32_t out = 0;
while (*buf == ' ') {
buf++;
}
for (int i = 0; i < 8; i++) {
uint8_t c = ReadHexNibble(*buf);
if (c > 0xf) {
break;
}
out = (out << 4) + c;
buf++;
}
return out;
}
void WriteHexNibble(uint8_t c) {
if (c > 9) {
putc('a' + c - 10);
} else {
putc('0' + c);
}
}
void WriteUint32(uint32_t a) {
for (int i = 0; i < 8; i++) {
WriteHexNibble((a >> 28) & 0xf);
a <<= 4;
}
}
void WriteUint8(uint8_t a) {
WriteHexNibble(a >> 4);
WriteHexNibble(a & 0xf);
}
void Dump(uint32_t addr, int count) {
for (int i = 0; i < count; i++) {
putc(' ');
WriteUint8(*reinterpret_cast<uint8_t*>(addr + i));
}
}
void DumpHex(uint32_t addr) {
addr &= 0xfffffffc;
WriteUint32(addr);
putc(':');
Dump(addr, 4);
putc('\r');
putc('\n');
}
int FindChar(const char* buf, uint8_t c) {
int found = 0;
while (*buf) {
if (*buf == c) {
return found;
}
found++;
buf++;
}
return -1;
}
void wozmon() {
uint32_t cur_addr = 0;
uint32_t cur_data = 0;
char inbuf[64] = {};
char* inptr = inbuf;
while (1) {
uint8_t c = getc();
putc(c); // echo
if (c == '\r') {
*inptr = 0;
if (inptr == inbuf) {
cur_addr += 4;
} else if (FindChar(inbuf, 'r') >= 0) {
Jump(cur_addr);
} else {
cur_addr = ReadHex(inbuf);
putc('\n');
}
DumpHex(cur_addr);
int assigned = FindChar(inbuf, ':');
if (assigned >= 0) {
cur_data = ReadHex(inbuf + assigned + 1);
*(reinterpret_cast<uint32_t*>(cur_addr)) = cur_data;
}
inptr = inbuf;
} else if (c == kBackspace) {
inptr--;
if (inptr < inbuf) {
inptr = inbuf;
continue;
}
putc(kOtherBackspace);
putc(' ');
putc(kOtherBackspace);
} else {
*inptr++ = c;
}
}
}
} // namespace
int main() {
wozmon();
}