Early VGA Tests
I've decided to make a DOS game. This is one of the earliest tests,
which just writes the entire palette to the corner of the screen.
Currently using Mode 13h.
Using DOSBox in the short term for testing. Still need to acquire a
real 486 with VGA and a SoundBlaster compatible sound card.
Posted: 2017-01-22
LilyVM - Addressing Modes
Well, I guess I settled on that last addressing mode. It's two more
modes, which pretty much just copy the existing
immediate-memory-location and something-from-the-stack addressing
modes.
Again, my terminology might be way off, but I'm going to call it
indirect-whatever mode.
Syntax in the assember for it is *address, or $stack_offset.
Here's what it's doing in code for the "fetch" part. (Excuse the
crappy temporary error handling for now.)
inline LilyVM::Word LilyVM::fetchParameterByType(LilyVM::ParamType type)
{
switch(type) {
case PARAM_NULL: return 0;
case PARAM_IMMEDIATE: return fetchInstruction();
case PARAM_ADDRESS: return fetchRaw(fetchInstruction());
case PARAM_STACK: return fetchRaw(stackPointer + fetchInstruction());
case PARAM_INDIRECT_ADDRESS: return fetchRaw(fetchRaw(fetchInstruction()));
case PARAM_INDIRECT_STACK: return fetchRaw(fetchRaw(stackPointer + fetchInstruction()));
default:
break;
}
// TODO: Throw error (bad instruction).
cout << "Bad addressing mode for read: " << type << endl;
exit(1);
return 0;
}
And here's a little example snippet of assembly demonstrating it.
mov 123 **someAddress
mov 123 *$somestackOffset
The ability to add in-line, immediate data was also added in the last
couple of revisions. There are assembly directives to have the next
few Words be some explicit values, or to fill the next 'n' Words with
some specific value.
I think the incomplete VM code might almost be not-embarrassing enough
to toss up GitHub soon.
Next up: Profiling and comparisons against Lua and native code. Then
taking out some of the modulo crap and trying it again.
Posted: 2016-07-25
LilyVM - RC4 Cryptography Example
To test the existing functionality of LilyVM and its assembler, I
decided to implement a simple, well-known cryptography algorithm,
RC4. It's not the kind that
anyone should use today, because it's got a lot of known effective
attacks against it, but it's an easy real-world example of a simple
algorithm to play with.
I also like to use it as a random number generator.
Lessons learned tonight:
-
Some more addressing modes to handle things like de-reference
pointers without separate load/store instructions would make
things MUCH more concise. I think I can add more addressing modes
without any overhead.
-
I thought about adding a "swap" instruction because it's done
twice in this example. Still not sure about this one.
-
I need better debugging tools! (You'd think inspecting the state
of your own VM would be easy.)
-
The code is getting a bit messy and needs a cleanup pass.
-
I really really really need a way to define arbitrary data. In
this example I used instructions in place of data just so I had
data to work with on the algorithm. Something to just occupy a
block of some number of Words, literal numbers, and possibly
literal strings would go a long way here.
-
Emacs's asm-mode is barely suitable for this. Maybe I just need to
get used to it.
-
I ended up using the stack as though it was just a big series of
registers. I guess it's how local variables really would be used
normally, so maybe it's not so bad.
-
Being able to create labels that map to arbitrary values instead
of just memory locations could have replaced a lot of the
arbitrarily-numbered stack positions.
-
I lack sufficient error handling. I want to avoid excessive error
checking, and I want to run in places where exceptions are
disabled. (I'm looking at you, Unreal 4.) I might have to resort
to the evil black magic that is setjmp()/longjmp().
-
I have need function calls. I have no kind of calling convention
or anything. There was only a little bit of duplicated code here,
though.
Here's
the RC4 implementation I made a long time ago that I tested it
against.
The actual code follows below. Excuse the lack of syntax highlighting.
I guess I need to make the syntax a little more like some common
assembler syntax to use an off-the-shelf syntax highlighter.
This code probably will not work for much longer because the assembler
and VM are both works in progress. Not that it matters, because I
still haven't actually put the source code out anywhere yet. This is
mostly a message to any future users (and myself) that this code is
not a good example to use.
Final disclaimer: There may be lots of bugs in this implementation.
;;; ----------------------------------------------------------------------
;;; Code section
;;; ----------------------------------------------------------------------
start:
;;; ----------------------------------------------------------------------
;;; Initialize state array and i, j variables
mov 256 $0
cryptoFillLoop:
add $0 -1 $0
add $0 rc4_cryptostate $1
store $0 $1
brnz $0 cryptoFillLoop
;; null can be used instead of zero here, and the entire mov
;; instruction will omit the parameter Word for that.
mov null *rc4_j ; j = 0
mov null *rc4_i ; i = 0
;;; ----------------------------------------------------------------------
;;; Take the key and use it to initialize the state array
setKeyLoop:
;; Key length is hardcoded here until I have a better way to
;; specify it.
div *rc4_i 8 null $4 ; keyval = key[i % 8] (8 is key length)
add key $4 $4
load $4 $4
div $4 256 null $4 ; keyval %= 256
add rc4_cryptostate *rc4_i $5
load $5 $5
add *rc4_j $5 *rc4_j ; j += state[i]
add *rc4_j $4 *rc4_j ; j += keyval
div *rc4_j 256 null *rc4_j ; j %= 256
;; Swap state[i] and state[j]
add rc4_cryptostate *rc4_j $5
add rc4_cryptostate *rc4_i $6
load $5 $7
load $6 $8
store $7 $6
store $8 $5
;; i++
add *rc4_i 1 *rc4_i
;; loop if i != 256
add *rc4_i -256 $3
brnz $3 setKeyLoop
;;; ----------------------------------------------------------------------
;;; Get ready to encrypt
;; Reset i, j
mov null *rc4_j
mov null *rc4_i
;; Loop counter
mov 0 $10
;;; ----------------------------------------------------------------------
;;; Encryption loop
encryptLoop:
;; i = (i + 1) % 256;
add *rc4_i 1 *rc4_i
div *rc4_i 256 null *rc4_i
;; j = (j + state[i]) % 256;
add rc4_cryptostate *rc4_i $6 ; $6 = &state[i]
load $6 $6 ; $6 = *$6
add *rc4_j $6 *rc4_j ; j += $6
div *rc4_j 256 null *rc4_j ; j %= 256
;; Swap state[i] and state[j]
add rc4_cryptostate *rc4_j $5
add rc4_cryptostate *rc4_i $6
load $5 $7
load $6 $8
store $7 $6
store $8 $5
add $7 $8 $9 ; $9 = state[i] + state[j]
div $9 256 null $9 ; $9 %= 256
;; $9 = state[$9]
add rc4_cryptostate $9 $9
load $9 $9
;; At this point we have our byte of randomness from RC4, and
;; can go ahead and encrypt another byte with a xor.
add $10 plaintext $11 ; Get a plaintext byte
load $11 $12
xor $12 $9 $12 ; XOR it
store $12 $11 ; Store it right back to the same
; buffer.
;; $10++
add $10 1 $10
;; loop if $10 != 8
add $10 -8 $11
brnz $11 encryptLoop
;;; ----------------------------------------------------------------------
;;; Done!
stop
;;; ----------------------------------------------------------------------
;;; Some empty space
invalid
invalid
invalid
invalid
invalid
invalid
invalid
invalid
;;; ----------------------------------------------------------------------
;;; Static variables
;;; ----------------------------------------------------------------------
;; The assembler lacks features to declare bytes or volumes of
;; space directly, so we're cheating for now and using
;; instructions with known opcode values to fill space.
;; Plaintext is just 8 Words of zero right now.
.export plaintext
plaintext:
invalid
invalid
invalid
invalid
invalid
invalid
invalid
invalid
;; Can't declare words or bytes, so the machine code generated
;; from this snippet of assembly will be our key because I'm a
;; horrible person. It's 8 words long.
.export key
key: add 1 2 3
add 4 5 6
;; rc4_j and rc4_i are the i and j variables from the RC4
;; algorithm.
.export rc4_i
rc4_i: invalid
.export rc4_j
rc4_j: invalid
.export rc4_cryptostate
rc4_cryptostate:
invalid
;; I guess the crypto state is the rest of memory.
It'll probably take a while before I get all the fixes and changes
done I mentioned here. So I'm not sure when the next time I'll post is
going to be.
Posted: 2016-07-20
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 [ 72 ] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Previous | Next