The MASM Forum
Specialised Projects => Compiler Based Assembler => Assembler With Microsoft Visual C => Topic started by: Emil_halim on July 20, 2012, 05:52:29 PM
-
Hi Everyone.
I was using Ziron assembler , it is a high level asm. then i tried to implement some features of it with MSVC10 inline assembly.
also i was thinking to mix that with basic language. so i do it with BCX , Basic To C translator.
here are some examples showing you the idea.
Exm1
====
/********************************
High level asm Example No 1
By Emil Halim
9-7-2012
*********************************/
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
FUNCTION main()
!DWORD b; /* allocate a local variable in inline-C */
^ eax = 200 ' this is inline asm code inserted in BCX code
^ b = eax ' this two lines put 200 into b variable
PRINT b ' print the result to make sure the b equal 200
Pause
END FUNCTION
this example declare a variable "b" by using inline-c then puts 200 in eax register in high level asm so you code do it with that
^ mov eax,200
so this is the idea of using high level asm.
Exm2
====
/********************************
High level asm Example No 2
By Emil Halim
9-7-2012
*********************************/
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
function add(a as int,b as int)
^ eax = a ' we can use parametrs directly
^ eax += b ' see the power of MSVC10
end function
FUNCTION main()
PRINT add(10,5) ' print the result to make sure the add equal 15
Pause
END FUNCTION
this example show you how to use parameters and also any variables name directly with asm , thanks to MSVC10.
Exm3
====
/********************************
High level asm Example No 3
By Emil Halim
9-7-2012
*********************************/
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
// declare global variable
!int k = 10;
function add(a as int,b as int)
$asmx
eax = a
eax += b
eax += k
$asmx
end function
// declare global array
!int a[] = { 0x1234, 0x4567 };
FUNCTION main()
PRINT add(10,5) ' print the result to make sure the add equal 25
raw cc%
^ eax = a ' interpreted as eax <- a[0]
^ eax = &a ' interpreted as eax <- &a[0]
^ ebx = [eax]
^ ecx = [eax+4]
^ cc = ecx
PRINT hex$(cc) ' print 4567
Pause
END FUNCTION
I think now you got the idea of my project , if you see it is useful then let me know.
thanks.
-
Did I understand you right: you are creating an assembler named Ziron that should support shown syntax?
EDIT: I misunderstand it: for those who are not familiar with Ziron: http://www.movsd.com/board/index.php?topic=17429.msg146202#msg146202
-
I was just a user for Ziron.
the idea here is to simplify the inline asm with MSVC10 so you can use those syntex with high level asm
[ebp-16] = 256 --------should be------->> mov dowrd ptr[ebp-16] , 256
dwrod [ebp-16] = 256
dword ptr [ebp-16] = 256
long [ebp-16] = 256
char [ebp-16] = 256 --------should be------->> mov byte ptr [ebp-16] , 256
short [ebp-16] = 256
eax = [edx]
eax = [edx+ecx]
eax = [edx+ecx*4]
eax = [edx+ecx*4-16]
Eax += Edx --------should be------->> add eax,edx
Eax -= Esi
eax = & b --------should be------->> lea eax,b
eax = & [ebx+ecx] --------should be------->> lea eax , [ebx+ecx]
eax = & b
eax = [edx+ecx*4-16]
[ebp-16] = 256
eax += edx
eax += [edx+ecx*4]
eax -= [edx+ecx*4]
ax *= bx ' by defaulte unsigned multiply
ax *= (int) bx ' signed multiply
al *= [edx]
ah *= [edx]
ax *= [edx]
Eax *= [edx]
DX.AX *= [ecx]
EDX.EAX *= [ebx]
EDX.EAX *= byte [ebx]
-Eax
- [ebx+4]
~Eax
~ [ebx+4]
Eax >> 4 ' shr
[Eax+8] << 3 ' shl
Eax >> cl ' shr
[Eax+8] << cl
st = float[eax] --------should be------->> fld dword ptr [eax]
st = qword ptr[eax] --------should be------->> fld qword ptr [eax]
st = tbyte ptr[eax+10] --------should be------->> fld tbyte ptr [eax]
st = st(2)
float[eax] = st --------should be------->> fstp dword ptr [eax]
al = CARRY --------should be------->> setc al
[edx] = Carry
al = Zero
al = Sign
al = Ovrflw
al = Parity
invoke test4,10,20,30
esp += 3*4
eax = 130
ebx = 140
invoke test4,10, eax ,ebx
esp += 3*4
eax = 1200
cinvoke printf ,&frm,eax
[ebx] = tst5(eax,40,30) ; call tst5 function the move eax to [edx]
hope the idea is now more clear and simple.
-
Ziron looks similar to Sphinx C-- (http://c--sphinx.narod.ru/indexe.htm)
-
yes , i was asking Mr Colin several times to add some feature of Sphinx C-- .
i liked it very much but it is buggy and old.
-
Hi ,
all of us know that inline asm in MSVC10 does not allow using DB ,DW,DD,DQ. but allows us to use _emit directive to emit only one byte.
i have successfully allow that but inside a function , MSVC10 does not allow _emit outside a function.
here is an example
=============
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
FUNCTION main()
print asmtest()
Pause
END FUNCTION
function asmtest()
$asmx
goto fin
bytes:
DB 32,40,50,"emil",10,0
DW 0xFFAA,0xccbb,100
MyData:
DD 0xffaaccbb
DQ 0xffaaccbb11223344
frm:
DB "%d",10,0
nge:
-EAX
return
fin:
eax = 1200
eax++
cinvoke printf ,&frm,eax
eax = &bytes
al = char[eax]
eax &= 0xFF
gosub nge
$asmx
end function
-
Hi ,
I have implemented .if-.endif statement , hope to make the inline asm with MSVC10 as comparable as masm syntax.
here is an example
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
FUNCTION main()
! char frm[] = "%d\n";
$asmx
eax = 5
.if eax == 5
cinvoke printf ,&frm,eax
.endif
$asmx
Pause
END FUNCTION
-
hi ,
I have made a tool that will process the inline-c high level asm with MSVC10 , consider the following Example
/********************************
High level asm && VC10
Example No 2
By Emil Halim
26-7-2012
*********************************/
#include "Windows.h"
#include <conio.h>
#include <stdio.h>
void __declspec(naked) main()
{
int i;
static char frm[] = "welcome i=%d\n";
// Naked functions must provide their own prolog...
__asm {
push ebp
ebp = esp
esp -= __LOCAL_SIZE
i = 10
cinvoke printf,&frm,i
.if i > 15
eax = i
.else
eax = 0
.endif
eax = getch()
esp = ebp
pop ebp
ret
}
}
here is a beta version of cHLasm www.spoilerspace.com/bcxdx/cHLasm/cHLasm.zip (http://www.spoilerspace.com/bcxdx/cHLasm/cHLasm.zip)
just unzip it and run jfe editor , drag and drop Exm2.cpp , press Create Console bottom.
-
Hi Emil,
Is there a specific reason to use inline assembly as interfers with the C\C++ compiler's optimization engine?
-
Hi Vortex,
the point here is to make something similar to sphinx C-- and ziron , with a power and optimized compiler.
so when you like coding with asm and have the power of c/c++ , by mixing them i think you can get a good
resulte that saticfied your disirde.
also using high level asm will simplify programing in asm level.
-
Hi Emil,
If I remember well, Sphinx C-- can output object modules too. Does Ziron provide this feature?
-
No , Mr Colin the owner of Ziron was planning to allows Ziron to genrate obj file by using Ziron Plug-In extension.
-
Hi ,
i have added a .while-.endw loop and .repeat-.until loop.
also push will accept mor than one parametr.
Example
======
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
FUNCTION main()
! char frm[] = "%d\n";
$asmx
eax = 5
.while eax > 0
push eax
cinvoke printf ,&frm,eax
pop eax
eax--
.endw
push eax ebx ecx
pop ecx ebx eax
$asmx
Pause
END FUNCTION
-
Hi all
I have implement FastProc - EndFastProc with BCX just like PowerBasic
keyword.
FastProc will produce a function without stack frame.
Example
=======
/********************************
High level asm Example No 14
By Emil Halim
3-3-2013
*********************************/
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
'====================================
' in Fast Procedure you have
' no stack frame in the beginning
' of the function
'====================================
FASTPROC GetEAX()
print "Example of Function without frame stack"
^ EAX = 100
^ ret ' you have to wirte it by your self
End FASTPROC
FUNCTION main()
!DWORD b; /* allocate a local variable in inline-C */
b = GetEAX()
PRINT b ' print the result to make sure the b equal 100
Pause
END FUNCTION
-
FastProc Example Ported From PowerBasic
/********************************
High level asm Example No 16
By Emil Halim
3-3-2013
*********************************/
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FASTPROC ASM_len
$AsmX
eax = [esp+4] ; load the string address
eax-- ; set up the address for loop entry
lbl0:
eax++ ; increment up to the next character
.if [eax] != 0 ; test if character is terminator
jne lbl0 ; loop back if not
.endif
eax -= [esp+4] ; sub the start address from EAX
ret 4 ; return while balancing the stack
$AsmX
END FASTPROC
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION main()
LOCAL rval AS DWORD
LOCAL szStr AS STRING * 64
szStr = "1234567890"
^ invoke ASM_len , &szStr
^ rval = eax
PRINT rval
Pause
END FUNCTION
-
implemented .for - .endfor for using in HighLevelAsm.
Example
======
/********************************
High level asm Example No 17
By Emil Halim
5-3-2013
*********************************/
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
FUNCTION main()
!char* MyStr = "welcome....\n";
raw ndx
$AsmX
' using variable as a loop counter
.for ndx = 5 to 10
cinvoke printf,MyStr
.endfor
' using ecx rigester as a loop counter
' note well Printf will change ecx , so save it
.for ecx = 4 to 10 step 2
push ecx
cinvoke printf,MyStr
pop ecx
.endfor
' using space memory in the stack as a loop counter
' do nt forget to blanced the stack when loop finished
esp -= 4 // allocate local variable
.for [esp] = 5 to 10 // loop fro 5 to 10
cinvoke printf,MyStr
.endfor //end the loop here
esp += 4 // de aloacate the local variable
$AsmX
Pause
END FUNCTION
-
implemented masm label "@@:" with High Level Asm
here is example that has 2 procedures , both of them will convert string to value.
in the first one Ebx must hold string address , Ecx must hold end address of string
in the second one you call it by normal way.
the 2 procedures i got them from MASM forum and modified it.
/********************************
High level asm Example No 18
By Emil Halim
6-3-2013
*********************************/
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
FastProc atod_proc
$AsmX
xor edx, edx
@@:
movzx eax, byte ptr [ebx]
lea edx, [edx+4*edx]
lea edx, [2*edx+eax-48]
inc ebx
cmp ecx, ebx
jne @B
xchg eax, edx
ret
$AsmX
End FastProc
FastProc atod_proc_2
$AsmX
edx = [esp+4] ; get first para in edx
xor eax, eax ; clear eax
@@: movzx ecx, byte ptr [edx] ; move 1 byte into ecx
lea eax, [eax+4*eax] ; eax -> 5 * eax
lea eax, [2*eax+ecx-30h] ; eax -> 2 * eax + (ecx-30h)
edx++ ; inc edx
cmp byte ptr [edx], 0 ; if end of string then return
jne @b
ret
$AsmX
End FastProc
FUNCTION main()
!const char MyStr[] = "2000";
raw ln ,value
!ln = strlen( MyStr );
^ ebx = &MyStr ; get str address into ebx
^ ecx = ebx ; copy ebx to ecx
^ ecx += ln ; get length of str into ecx
^ call atod_proc ; call the function
^ value = eax ; store result in value variable
print value
print atod_proc_2(MyStr$)
Pause
END FUNCTION
-
also implemented Uses keyword that will save some registers in front of procedure and will be restored automatically when ret from procedure
Example
======
/********************************
High level asm Example No 19
By Emil Halim
7-3-2013
*********************************/
$CPP
$NOMAIN
$NOWIN
#include "Windows.h"
FastProc Test
$AsmX
'we want to save 2 registers esi and edi
uses esi edi
esi = [esp+4+8] ;get first arg into esi
edi = [esp+8+8] ;get second arg into edi
eax = esi ; copy esi to eax
eax += edi ; add eax and edi
' here HiegLivelAsm will restore the saved registers
ret
$AsmX
End FastProc
FUNCTION main()
print Test(10,20)
Pause
END FUNCTION
-
if someone interesting,
here is the source code of bcx 6.9.9.1 & HighLevelAsm source code.
www.spoilerspace.com/bcxdx/cHLasm/BCX6_9_9_1&HighLevelAsm_1.zip (http://www.spoilerspace.com/bcxdx/cHLasm/BCX6_9_9_1&HighLevelAsm_1.zip)
you must have MSVC10 to create BC translator with HighLevelAsm.
Feel free to improve and enhanced it.
thanks.
-
if it helps, you can temporarily disable the assembler prologue and epilogue
OPTION PROLOGUE:None
OPTION EPILOGUE:None
OpnFile PROC lpFileName:LPSTR,dwOpenFlags:DWORD
;code
ret 8 ;you must pop the parameters off the stack
OpnFile ENDP
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
-
thanks you.
actually , we can make a function without frame stack by many way in bcx & HighLevelAsm & VC10
Example
======
; FastProc Example
FastProc GetVal
^ Eax = 100
^ ret
End FastProc
this will translated to that
__declspec(naked) int GetVal(...)
{
__asm{
Mov Eax , 100
ret
}
}
second method is like that
!#define FastProc __declspec(naked)
!FastProc int add1(int a, int b)
!{
^ eax = a
^ eax += b
^ ret
!}
and yet another method that specific for VC10
!#pragma optimize( "y", on )
function add(a as int,b as int)
^ eax = a
^ eax += b
^ ret
end function
!#pragma optimize( "y", off )