PDA

View Full Version : win32 machine code assembler with Delphi



Georgy
05-01-2010, 09:11 PM
After spending some time on TDG3D Engine and hl2 smd loader I've played with machine codes. It is quite interesting thing. I have never seen small source in delphi for making real EXE files, so I decided to make my own mini-compiler.

http://www.igrodel.ru/tdg3d/pe-asm0.2.zip (20kb) - exe+source code+examples

Currently it supports only three instructions (see readme.txt). But it's enough to compile small examples like that:


.import
import Kernel32.dll WriteFile
import Kernel32.dll GetStdHandle

.var
string s1 "This is a loop!"
byte STD_INPUT_HANDLE 0xf5
dword count 0x00000000

.code

:label1
push =STD_INPUT_HANDLE
call getstdhandle

push 0x00 // lpOverlapped
push @count // lpNumberOfBytesWritten
push =length(s1) // nNumberOfBytesToWrite
push @s1 // lpBuffer
push eax // hFile
call writefile
jmp label1

I release source code, maybe it will be useful, making engine script compiler to machine code, for students learning delphi, and so on.

chronozphere
06-01-2010, 09:13 AM
Cool.. I always wondered how to make a compiler. :)

Brainer
06-01-2010, 05:28 PM
Cool.. I always wondered how to make a compiler. :)

Visit this -> http://compilers.iecc.com/crenshaw/

noeska
06-01-2010, 06:22 PM
Some more intereting things on making compilers/scripting languages:

http://www.scifac.ru.ac.za/compilers/conts.htm (about coco/r) and http://parserbuilder.sourceforge.net/ for a delphi coco/r version with ide.
http://www.andreadrian.de/tbng/index.html (making a pascal like language compiler with coco/r)

http://homepages.cwi.nl/~steven/pascal/ (p4 pascal)

jdarling
07-01-2010, 02:37 PM
Its worth pointing out that what you've written is a very special type of compiler called an assembler. Many people write compilers that simply take an input language (C, JavaScript, Pascal, or some custom language) and output assembler code or pcode (aligned typically) to be ran inside a virtual machine. Then rely upon an assembler to actually generate the binary code for execution.

This is because the actual assembling of the binary code is more difficult than (especially with advanced platforms like the x86) generating assembly code. Proper opcode output generation isn't trivial in the slightest (as I'm sure you already know).

Your usage of a Crenshaw style while building an assembler makes perfect sense, but I have to ask why you didn't opt for a lookup table for your output generator instead of the Crenshaw style of one method per opcode?

Now you just need to finish adding in the rest of the symbols, extend it so you can have an optimizer, and add some good documentation and your ready for others to use it simply because its unique :)

Congrats on a great start! You've made it further than I ever did, I never released anything I wrote on the subject to the public. Too afraid of the comments people would leave, or the work was for corporate usage and fell under NDA LOL.

- Jeremy

PS: As far as books go, the best I've found are Compilers - Principles Techniques and Tools by Alfred Aho - Monica Lam- Ravi Sethi- Jeffrey Ullman - Second Edition (The Dragon Book, hard read but still the best) and Game Scripting Mastery. MUD Game Programming has some good sections in it (Chapter 14), but leaves a lot to be desired in the end :(

Georgy
12-01-2010, 12:55 PM
new version released!

30kb: http://www.igrodel.ru/tdg3d/peasm-0.3beta.zip (sources, examples, compiler)

added feauteres:

...
record msg
dword hwnd 0x00000000
dword code 0x00000000
dword wparam 0x00000000
dword lparam 0x00000000
dword time 0x00000000
dword mousex 0x00000000
dword mousey 0x00000000
end
...
push @msg.hwnd
call DispatchMessageA
...
and some more!

New opcodes and better parser:

smartparser('push ^', 'text|push~ val|1'); // PUSH ^var
smartparser('push @', 'text|push~0x ptr|1'); // PUSH @var
smartparser('push 0x??', 'text|6A raw|1'); // PUSH Imm8 "6A 00"
smartparser('push 0x????????', 'text|68 raw|1'); // PUSH IMM32 "68 00 00 00 00"
smartparser('push ???', 'text|50 +reg|1'); // push r32 "50+reg"
smartparser('call 0x????????', 'text|FF15 raw|1'); // CALL r/m32 "ff 15 00 00 00 00"
smartparser('call ?', 'text|FF15 dll|1'); // CALL r/m32 "ff 15 00 00 00 00"
smartparser('jmp 0x????????', 'text|E9 raw|1'); // JMP
smartparser('jmp ?', 'text|E9 label|1'); // JMP
smartparser('mov ^ eax', 'text|mov~0: ptr|1 text|~eax'); // MOV ^var,eax
smartparser('mov 0:???????? eax', 'text|A3 raw|1'); // MOV ptr,eax
smartparser('mov eax ^', 'text|mov~eax~0: ptr|2'); // MOV eax, ^var
smartparser('mov eax 0:????????', 'text|A1 raw|2'); // MOV eax, ptr
Add your opcodes!