To create files with 64-bit assembly functions using Visual Studio 2015 (Community):
- Right-click on your project, enter the menu
Build Dependencies
and then Build Customizations...
. In the customizations screen, select the masm(.targets, .props)
option:
- Inyourproject,inthe
SourceFiles
folder,addanewitemUtility
oftypeTextFile(.txt)
(textfile).Afteradding,renamethefilefrom.txt
to.asm
(example:funcao.txt
tofuncao.asm
):
- Right-clickthe
funcao.asm
fileandselectProperties
.InthePropertieswindow,changetheItemType
fromText
toMicrosoftMacroAssembler
:
- Inthe
C
sourcecode,declaretheprototypeofthefunctionsasextern
.IftheprogramisinC++
,declareextern"C"
. In your example, the main file looks like this:
#include "stdafx.h"
// delcaração da função em assembly
extern "C" long long int formula(long long int a, long long int b, long long int *r2);
// Função em C que implementa o mesmo cálculo (apenas para teste)
long long int formula2(long long int a, long long int b, long long int *r2)
{
*r2 = (a*b) / (a*a / b + b*b / a);
return a*a + b*b;
}
int main(int argc, char *argv[])
{
long long int ret1;
long long int ret2;
printf("inicio\n");
// Execução em C
ret1 = formula2(12, 16, &ret2);
printf("Resultado C: ret1=%lld, ret2=%lld\n", ret1, ret2);
// Execução em Assembly
ret1 = formula(12, 16, &ret2);
printf("Resultado ASM: ret1=%lld, ret2=%lld\n", ret1, ret2);
printf("fim.\n");
getchar();
return 0;
}
The type long long int
defines the variables ret1
and ret2
as integers of 64 bits.
Depending on the logic you want to implement, the type may change and how the assembly code will be developed, too.
- In the assembly source code, declare the functions as
public
. For your example, the file funcao.asm
looks like this:
.code
public formula
; formula(a,b,ret2) = a*a + b*b
; *ret2 = ( a*b )/( a*a/b + b*b/a )
formula proc
mov r11, rdx ; r11 <- b
xor rdx, rdx ; rdx = 0
mov rax, rcx
imul rax, rax
mov r9, rax ; r9 <- a^2
mov rax, r11
imul rax, rax
mov r10, rax ; r10 <- b^2
idiv rcx
mov r12, rax ; r12 <- b^2/a
xor rdx, rdx
mov rax, r9
idiv r11
add rax, r12
mov r13, rax ; r13 <- b^2/a + a^2/b
xor rdx, rdx
mov rax, rcx
imul rax, r11
idiv r13
mov qword ptr [r8], rax ; resultado em rax
mov rax, r9
add rax, r10
ret
formula endp
end
In assembly 64 bits, parameter passing, declaration of local variables, return of functions, etc. are different from 32-bit assembly .
Here are some links that talk about it (for programming Windows
, the main one is the first link):
The result, after running the program:
inicio
Resultado C: ret1=400, ret2=6
Resultado ASM: ret1=400, ret2=6
fim.
Edit
In response to the comment, to compile a mixed code (32 and 64bit), as defined in VS2015:
- Right-click the
funcao.asm
file and enter Properties
. In the properties window, change (if necessary) the items: Configuration
to All Configurations
and Platform
to Win32
or Active(Win32)
(if this platform is already selected)
- Change the item
Excluded From Build
to Yes
Withthischange,thefuncao.asm
filewillonlybecompiledwhentheplatformissetto64-bit.
Inthesourcecode,usethe_WIN64
macrotosettheprototypefunctionsasextern
to64bits,orwithassemblyinline(forexample)to32bits.
Theimportantpoint(ifpossible)istokeeptheprototypefunctionsidenticalforboth32and64bits.
Afterthechanges,thesourcecodeinC
lookslikethis:
#include "stdafx.h"
#ifdef _WIN64
// Código 64 bits
// delcaração da função em assembly
extern "C" long long int formula(long long int a, long long int b, long long int *r2);
#else
// Código 32 bits
// Inline
long long int _cdecl formula(long long int a, long long int b, long long int *ret2) {
int sqa, sqb, dv;
int ret_local; // Acrescentei esta variável
__asm {
mov eax, dword ptr[a]
mul eax
mov dword ptr[sqa], eax
div dword ptr[b]
mov dword ptr[dv], eax
mov eax, dword ptr[b]
mul eax
mov dword ptr[sqb], eax
div dword ptr[a]
add dword ptr[dv], eax
mov eax, dword ptr[a]
mul dword ptr[b]
div dword ptr[dv]
mov [ret2], eax ; Aqui, o código estava incorreto
mov eax, dword ptr[sqa]
add eax, dword ptr[sqb]
mov [ret_local], eax ; Armazena o retorno
}
return (long long int) ret_local;
}
#endif // _WIN64
// Função em C que implementa o mesmo cálculo (apenas para teste)
long long int formula2(long long int a, long long int b, long long int *r2)
{
*r2 = (a*b) / (a*a / b + b*b / a);
return a*a + b*b;
}
int main(int argc, char *argv[])
{
long long int ret1;
long long int ret2;
printf("inicio\n");
// Execução em C
ret1 = formula2(12, 16, &ret2);
printf("Resultado C: ret1=%lld, ret2=%lld\n", ret1, ret2);
// Execução em Assembly
ret1 = formula(12, 16, &ret2);
printf("Resultado ASM: ret1=%lld, ret2=%lld\n", ret1, ret2);
printf("fim.\n");
getchar();
return 0;
}
Note: I just made a small correction to the inline tag and added a local variable to return the result of the function.
The result of the execution is the same as that reported in the answer above.
Obs2: There are other, possibly better, ways of organizing the mixed code (32 and 64 bits) within Solution
of VS2015. This answer is just a "starting point" to show how to compile the mixed code.