# An assembler, completely in AutoIt

## Recommended Posts

There are 34 different versions of the MOV mnemonic. All of them use different kinds and sizes of operands.

There are 8 general purpose registers.

The MOV mnemonic takes two operands, so there are about 8*34*2 = 544 combinations.

You might think I'm forgetting the immediate values: that will decrease the amount of possibilities. Yes, but I'm not mentioning the abilities to do [eax], [eax+2] and [4*eax+ebx] either.

Anyway, I've seen people trying to convert assembly to machine code before, but they all wrote a different function for every single combination.

Not really handy, I'd say...

Right now this assembler supports the following functions:

INC

DEC

CMP

AND

OR

XOR

MOV

PUSH

JMP

XCHG

RET

SBB

SUB

POP

A hell load of Jump functions (JA, JAE, etc)

MUL

IMUL

DIV

IDIV

CALL

You could probably understand that I haven't had the time yet to test them all...

This is an example code. It should work... I hope (It works on my 32 bit computer. I don't see why it wouldn't work on a 64 bit system)

#include "ASM.au3"
\$Code = ASMInstruction("MOV","eax",10) & _      ; Move '10' to EAX
ASMInstruction("INC","eax") & _            ; Increase EAX (same as ADD(EAX,1) but faster)
ASMInstruction("XOR","ebx","ebx") & _   ; Shortcut for making EBX zero(0)
ASMInstruction("MOV","bl",2) & _       ; Move '2' to BL
ASMInstruction("RET")                  ; Return EAX

\$hCode = ASMCompile(\$Code)

\$iRetVal = ASMExecute(\$hCode)

MsgBox(0,"sd",\$iRetVal,0)

You need to download both attachments, and have to put them in the same directory.

ASM.au3

IA-32 Instruction Set.txt

Edited by Kip

##### Share on other sites
Thanks so much! Respect.

[size="5"] [/size]

##### Share on other sites

Looks clever Kip, but since I never do anything in machine code or assembler it is not something I would use or even know how to use.

I would expect that someone who does write assembler would write something like this

MOV eax 10  ; Move '10' to EAX
INC eax     ; Increase EAX (same as ADD(EAX,1) but faster)
XOR ebx ebx ; Shortcut for making EBX zero(0)
MOV bl 2    ; Move '2' to BL
RET     ; Return EAX

so wouldn't it be better if you had a text file which you imported and parsed rather than the lengthy function calls?

Since I don't know what I'm talking about just tell me if that's nonsense.

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

##### Share on other sites

True, but I don't like to write a parser for that file too. I'm currently busy with labels.

##### Share on other sites

Well, I know pretty much nothing about assembly language also, but here is a very very basic parser.

#include "ASM.au3"
#include <file.au3>
Dim \$lines, \$code = ""

For \$n = 1 to \$lines[0]
For \$m = 1 to \$split[0]
If \$split[\$m] = "" Then
\$split[0] -= 1
EndIf
Next
If \$split[0] <> 0 Then
\$code &= getASM(\$split,\$split[0])
EndIf
Next

\$hCode = ASMCompile(\$code)
\$iRetVal = ASMExecute(\$hCode)

MsgBox(0,"sd",\$iRetVal,0)

Func getASM(\$codeArray,\$number)
Switch \$number
Case 1
return ASMInstruction(\$codeArray[1])
Case 2
return ASMInstruction(\$codeArray[1],\$codeArray[2])
Case 3
return ASMInstruction(\$codeArray[1],\$codeArray[2],\$codeArray[3])
EndSwitch
EndFunc

Just put the code example of martins in a text file and then select that text file when you run my code.

Not sure if you ever have a ASMInstruction with more than three parameters, but if you do, just add it to the switch statement.

Like I said above, this is a very crude parser but it works.

Cheers,

Disabled Monkey

Edited by DisabledMonkey

##### Share on other sites

Well, I know pretty much nothing about assembly language also, but here is a very very basic parser.

#include "ASM.au3"
#include <file.au3>
Dim \$lines, \$code = ""

For \$n = 1 to \$lines[0]
For \$m = 1 to \$split[0]
If \$split[\$m] = "" Then
\$split[0] -= 1
EndIf
Next
If \$split[0] <> 0 Then
\$code &= getASM(\$split,\$split[0])
EndIf
Next

\$hCode = ASMCompile(\$code)
\$iRetVal = ASMExecute(\$hCode)

MsgBox(0,"sd",\$iRetVal,0)

Func getASM(\$codeArray,\$number)
Switch \$number
Case 1
return ASMInstruction(\$codeArray[1])
Case 2
return ASMInstruction(\$codeArray[1],\$codeArray[2])
Case 3
return ASMInstruction(\$codeArray[1],\$codeArray[2],\$codeArray[3])
EndSwitch
EndFunc

Just put the code example of martins in a text file and then select that text file when you run my code.

Not sure if you ever have a ASMInstruction with more than three parameters, but if you do, just add it to the switch statement.

Like I said above, this is a very crude parser but it works.

Cheers,

Disabled Monkey

The maximum number of operands is 4, although I've never seen an instruction like that myself.

Besides, 2 is the maximum the assembler can handle.

##### Share on other sites

Very interesting Kip, however I'm going to wait for labels before I give this a real go.

So, when's the AutoIt compiler coming out?

I tried, I really did. But I just cannot see the connection.

Broken link? PM me and I'll send you the file!

##### Share on other sites

I have some experience with monoceres's sense of humor and I can say he's lying now.

He tried nothing, just saw something he felt is stupid and made fun of it.

He is mean and he hates you JRowe.

Edited by trancexx

.

eMyvnE

##### Share on other sites

I was trying to point out that Kip's done a whole lot of great, complicated things, and tried to think of a "take it to the next level", impossible goal type of thing, and a compiler was the best I could come up with. Kinda like a "gee whiz, what'll he think of next." It was a lazy compliment, and I should have tried harder.

@trancexx, lol~

##### Share on other sites

This is great Kip. Its been awhile since I did anything in assembly, but what I remember most from when I was toying around with it was how much I hated looking up the opcodes. This will help a lot if I ever go back and try more.

"Only those who have the patience to do simple things perfectly will acquire the skill to do difficult things easily" - Johann von Schiller

##### Share on other sites

Why would you wanna look them up yourself. Can't you use an already excisting assembler to do that for you?

##### Share on other sites

Why would you wanna look them up yourself. Can't you use an already excisting assembler to do that for you?

That's almost the same if I would ask you why would you write a new assembler when there are others out there?

And you will say because blah blah blah...

And I will say exactly. But would you understand what I said?

I wrote few bytes of instructions over a time. Never used tools for that.

.

eMyvnE

##### Share on other sites

Why would you wanna look them up yourself. Can't you use an already excisting assembler to do that for you?

I guess you kinda have to see it from my shoes. Back then (and still now), All I new of assembly was from the sweet ass examples trancexx was giving. I thought it was so awesome how much she was doing so much with so little cpu usage. There was alot of things done in autoit that I really didn't know how I was going to do it in an other assembler. Take this small script that just performs a sleep operation.

#include <winapi.au3>
#include <Memory.au3>

\$pRemoteCode = _MemVirtualAlloc(0, 512, \$MEM_COMMIT, \$PAGE_EXECUTE_READWRITE)
\$CodeBuffer = DllStructCreate("byte[512]", \$pRemoteCode)

\$iMilliseconds = 5000

Local \$Opcode
\$Opcode &= "0x"
\$Opcode &= "33DB"                                   ;xor ebx, ebx
\$Opcode &= "B8" & SwapEndian(\$iMilliseconds)        ;move eax, \$milliseconds
\$Opcode &= "50"                                     ;push eax
\$Opcode &= "B8" & SwapEndian(\$SleepAddress)         ;mov eax, \$Sleep
\$Opcode &= "FFD0"                                   ;call eax
\$Opcode &= "53"                                     ;push ebx
\$Opcode &= "58"                                     ;pop eax
\$Opcode &= "C3"                                     ;ret

DllStructSetData(\$CodeBuffer, 1, \$Opcode)

ConsoleWrite('Start Sleep...' & @CRLF)
Local \$Ret = DllCall("user32.dll", "int", "CallWindowProc", "ptr", DllStructGetPtr(\$CodeBuffer), "int", 0, "int", 0, "int", 0, "int", 0)
ConsoleWrite('Done' & @CRLF)

Func SwapEndian(\$hex)
Return Hex(BitOR(BitOR(BitOR(BitShift(\$hex, 24), _
BitAND(BitShift(\$hex, -8), 0x00FF0000)), _
BitAND(BitShift(\$hex, 8), 0x0000FF00)), _
BitShift(\$hex, -24)), 8)
EndFunc;==>SwapEndian

How do I do the dllcalls to get the function address? How do I do the SwapEndian function? What the fuck is the SwapEndian function?

I'm sure there were ways, but for what I was doing and what I new of assembly, to me it was just easier.

"Only those who have the patience to do simple things perfectly will acquire the skill to do difficult things easily" - Johann von Schiller

##### Share on other sites
whatever Edited by MvGulik

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...

##### Share on other sites

Func SwapEndian3(\$iVal)
Return Hex(Int(Binary('0x' & Hex(\$iVal)) & Binary(0)))
EndFunc
Is ~60% faster than original SwapEndian() in above post. (less mystifying code to)

I kinda think the speed of the swapendian function is really trivial. Its the execution of the opcode that really matters. Also that part was eventually changed to
Func SwapEndian(\$iValue)
Return Hex(BinaryMid(\$iValue, 1, 4))
EndFunc   ;==>SwapEndian

\$val = 2365100092 {I6} (0x8C.F8.90.3C)
\$ORG = FFFFFF8C {St}
\$SE3 = 3C90F88C {St}
\$val = -254955044 {I6} (0xFF.FF.FF.FF.F0.CD.B1.DC)
\$ORG = FFFFFFF0 {St}
\$SE3 = DCB1CDF0 {St}
I have no clue what that means.

"Only those who have the patience to do simple things perfectly will acquire the skill to do difficult things easily" - Johann von Schiller

##### Share on other sites
whatever Edited by MvGulik

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...

##### Share on other sites

Maybe this ASM interpreter can be useful. I'm using it to verify ASM code result.

#include <GUIConstants.au3>
#include "ASM.au3"
Global \$ASMCode = ""

\$ASMCode &= "MOV eax 10" & @CrLf
\$ASMCode &= "ADD eax 1" & @CrLf
\$ASMCode &= "INC eax" & @CrLf
\$ASMCode &= "XOR ebx ebx" & @CrLf
\$ASMCode &= "MOV bl 2" & @CrLf
\$ASMCode &= "ADD eax ebx" & @CrLf
\$ASMCode &= "RET"

Global \$Source, \$Result

\$hWnd = GUICreate("ASM Console", 400, 480)
;--------------------------------------------------
\$LabelTarget = GUICtrlCreateLabel("Your ASM:", 10, 10, 380, 21)
\$Source = GUICtrlCreateEdit(\$ASMCode, 10, 40, 380, 150)
\$Result = GUICtrlCreateEdit('', 10, 200, 380, 230)
;--------------------------------------------------
\$Execute = GUICtrlCreateButton("Execute", 150, 440, 100, 21)
GUISetState()

; Start the main loop
While 1
\$Msg = GUIGetMsg()
Select
Case \$Msg = \$GUI_EVENT_CLOSE
Exit
Case \$Msg = \$Execute
RunASM()
EndSelect
WEnd

;===============================
func RunASM()
local \$SourceContent, \$ResultContent, \$cmpCode
\$ASMLines = StringSplit(StringStripCR (\$SourceContent),@Lf)
\$Code = ""
for \$i = 1 to \$ASMLines[0]
\$ASM = StringSplit(\$ASMLines[\$i]," ")
Switch \$ASM[0]
case 1
\$Code &= ASMInstruction(\$ASM[1])
case 2
\$Code &= ASMInstruction(\$ASM[1],\$ASM[2])
case 3
\$Code &= ASMInstruction(\$ASM[1],\$ASM[2],\$ASM[3])
case 4
\$Code &= ASMInstruction(\$ASM[1],\$ASM[2],\$ASM[3],\$ASM[4])
EndSwitch
next
\$cmpCode = ASMCompile(\$Code)
\$ResultContent = ASMExecute(\$cmpCode)
GUICtrlSetData(\$Result, \$ResultContent)
endfunc

The point of world view

##### Share on other sites

Maybe this ASM interpreter can be useful. I'm using it to verify ASM code result.

#include <GUIConstants.au3>
#include "ASM.au3"
Global \$ASMCode = ""

\$ASMCode &= "MOV eax 10" & @CrLf
\$ASMCode &= "ADD eax 1" & @CrLf
\$ASMCode &= "INC eax" & @CrLf
\$ASMCode &= "XOR ebx ebx" & @CrLf
\$ASMCode &= "MOV bl 2" & @CrLf
\$ASMCode &= "ADD eax ebx" & @CrLf
\$ASMCode &= "RET"

Global \$Source, \$Result

\$hWnd = GUICreate("ASM Console", 400, 480)
;--------------------------------------------------
\$LabelTarget = GUICtrlCreateLabel("Your ASM:", 10, 10, 380, 21)
\$Source = GUICtrlCreateEdit(\$ASMCode, 10, 40, 380, 150)
\$Result = GUICtrlCreateEdit('', 10, 200, 380, 230)
;--------------------------------------------------
\$Execute = GUICtrlCreateButton("Execute", 150, 440, 100, 21)
GUISetState()

; Start the main loop
While 1
\$Msg = GUIGetMsg()
Select
Case \$Msg = \$GUI_EVENT_CLOSE
Exit
Case \$Msg = \$Execute
RunASM()
EndSelect
WEnd

;===============================
func RunASM()
local \$SourceContent, \$ResultContent, \$cmpCode
\$ASMLines = StringSplit(StringStripCR (\$SourceContent),@Lf)
\$Code = ""
for \$i = 1 to \$ASMLines[0]
\$ASM = StringSplit(\$ASMLines[\$i]," ")
Switch \$ASM[0]
case 1
\$Code &= ASMInstruction(\$ASM[1])
case 2
\$Code &= ASMInstruction(\$ASM[1],\$ASM[2])
case 3
\$Code &= ASMInstruction(\$ASM[1],\$ASM[2],\$ASM[3])
case 4
\$Code &= ASMInstruction(\$ASM[1],\$ASM[2],\$ASM[3],\$ASM[4])
EndSwitch
next
\$cmpCode = ASMCompile(\$Code)
\$ResultContent = ASMExecute(\$cmpCode)
GUICtrlSetData(\$Result, \$ResultContent)
endfunc

People, the fourth parameter of the ASMInstruction() function can't be used for third operands at all. I don't know where you got that idea.

It is for specifying the size of pointers and/or the data they point to.

For example:

PUSH [myLabel];

There is no way to tell the size of the data 'myLabel' is pointing to, so that's why the \$iSize parameter is there for:

PUSH dword [myLabel];

Edited by Kip

##### Share on other sites

There was some project released.

"Local Assembler for VB6"

See forum (in Russian): here

and homepage (in English): here

This tool has an IDE and full source code. Maybe it would be better to rewrite it into AutoIt.

The point of world view

## Create an account

Register a new account

×

• Wiki

• Back

• Git