I've created in windows c++ project in Visual Studio to learn how to write asm functions.
So in my project I've got hello.asm with this simple code:
.686
.MODEL FLAT
.STACK
.DATA
.CODE
hello PROC
xor eax,eax
ret
hello ENDP
END
and asm_test.cpp with main function like this:
#include "stdafx.h"
#include <Windows.h>
extern "C" void hello();
int _tmain(int argc, _TCHAR* argv[])
{
hello();
return 0;
}
So in general ml.exe doesnt have any problem compiling asm file to hello.obj
but hello() function doesnt' know where should it be taken from. And here is what compiler tells me.
1>------ Построение начато: проект: asm_test, Конфигурация: Debug Win32 ------
1> Assembling hello.asm...
1>asm_test.obj : error LNK2019: ссылка на неразрешенный внешний символ _hello в функции _wmain
1>G:\renderer\asm_test\Debug\asm_test.exe : fatal error LNK1120: неразрешенных внешних элементов: 1
========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========
Sorry, it's on russion, but it's clear that it can not find hello function
change hello to be _hello plz. for your hello.asm, it should be:
.686
.MODEL FLAT
.STACK
.DATA
.CODE
_hello PROC
xor eax,eax
ret
_hello ENDP
END
Related
This question already has answers here:
How to set gcc or clang to use Intel syntax permanently for inline asm() statements?
(2 answers)
Can I use Intel syntax of x86 assembly with GCC?
(2 answers)
Closed last year.
I'd like to use intel syntax gcc inline assembly, leaving gcc's default -masm=att dialect untouched.
The following code works fine:
#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 123;
int b = 0;
printf("before: a = %d\n", a);
printf("before: b = %d\n", b);
__asm__ __volatile__ (
".intel_syntax noprefix\n\t"
"mov eax, %[a]\n\t"
"mov %[b], eax\n\t"
".att_syntax prefix\n\t"
: [b]"+r"(b)
: [a]"r"(a)
: "eax"
);
printf("after: a = %d\n", a);
printf("after: b = %d\n", b);
return 0;
}
// before: a = 123
// before: b = 0
// after: a = 123
// after: b = 123
But if i change Output Operands Constraint from register('r') to memory('m'), error occurs:
Error: junk `(%rbp)' after expression
In the generated assembly file, I find this:
#APP
.intel_syntax noprefix
mov eax, -16(%rbp)
mov -12(%rbp), eax
.att_syntax prefix
#NO_APP
It looks like gcc renders Assembler Template using AT&T Effective-Address dialect.
I searched the web, Extended Asm shows something like "Multiple assembler dialects in asm templates" and "x86 Operand Modifiers", but I still didn't solve the problem.
Is there a way to tell gcc, (maybe some instructions around __asm__, telling gcc to do operand-substitution with Intel-syntax addressing modes temporarily, like -masm=intel do in the whole file), render the Assembler Template using Intel Effective-Address dialect temporarily in __asm__ () block, not the whole file, like this:
#APP
.intel_syntax noprefix
mov eax, [%rbp - 16]
mov [%rbp - 12], eax
.att_syntax prefix
#NO_APP
I have a program that was an example from our textbook, however when i put it in visual studio i get all kinds of errors. I am very new to Assembly, so I don't really know what this code is supposed to do, and i don't know why it is not working. Here is the code:
.model flat,c
.code
; extern "C" int CalcResult1_(int a, int b, int c);
CalcResult1_ proc
push ebp
mov ebp,esp
mov eax,[ebp+8]
mov ecx,[ebp+12]
mov edx,[ebp+16]
add eax,ecx
imul eax,edx
pop ebp
ret
CalcResult1_ endp
end
Here are the errors it gives:
1>------ Build started: Project: CompOrgHW2, Configuration: Debug Win32 ------
1>assembly_.asm
1>g:\comporghw2\comporghw2\assembly_.asm(1): error C2059: syntax error: '.'
1>g:\comporghw2\comporghw2\assembly_.asm(2): error C2059: syntax error: '.'
1>g:\comporghw2\comporghw2\assembly_.asm(7): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>g:\comporghw2\comporghw2\assembly_.asm(7): error C2365: 'CalcResult1_': redefinition; previous definition was 'function'
1>g:\comporghw2\comporghw2\assembly_.asm(4): note: see declaration of 'CalcResult1_'
1>g:\comporghw2\comporghw2\assembly_.asm(7): error C2146: syntax error: missing ';' before identifier 'proc'
1>Done building project "CompOrgHW2.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I'm using Visual Studio 2017 Community to build a test console C++ application. I need to include an assembly function into that project:
extern "C" void* __fastcall getBaseFS(void);
To include an asm file I right-clicked the project and went to "Build dependencies" -> "Build Customization" and checked "masm" in the list there.
I can then add an asm file by right-clicking my project -> Add New item -> and then add "asm_x64.asm" file where I write my x86-64 asm code:
.code
getBaseFS PROC
mov ecx, 0C0000100H ; IA32_FS_BASE
rdmsr
shl rdx, 32
or rax, rdx
ret
getBaseFS ENDP
END
This works in a 64-bit project.
The problem is that when I switch solution platform from x64 to x86:
my asm file needs to change. So in a sense I need to include a different "asm_x86.asm" file into compilation that is used only for x86 builds vs. x64 builds.
What's the best way to automate this switch?
OK, thanks to Michael Petch, I got it solved. Had to put both x64 and x86 code in one .asm file.
(There's another proposed option to deal with build configuration, but I prefer the method I'm showing here. I had a bad luck with those build configurations disappearing when solutions were moved from computer to computer.)
So, I'm not sure why using IFDEF RAX works, and Microsoft's own proposed ifndef X64 doesn't. But oh well. If anyone knows, please post a comment.
asm_code.asm file:
IFDEF RAX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; x64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WinAPI to call
extrn Beep : proc
.data
align 8
beep_freq:
dq 700 ; hz
beep_dur:
dq 200 ; ms
str_from:
db "Hail from x64 asm", 0
.code
useless_sh_t_function__get_GS_a_string_and_beep PROC
; parameter = CHAR** for a string pointer
; return = value of GS register selector
mov rax, str_from
mov [rcx], rax
mov rdx, qword ptr [beep_dur]
mov rcx, qword ptr [beep_freq]
call Beep
mov rax, gs
ret
useless_sh_t_function__get_GS_a_string_and_beep ENDP
ELSE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; x86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.686p
.XMM
.model flat, C
.data
align 4
beep_freq dd 700 ; hz
beep_dur dd 200 ; ms
str_from db "Hail from x86 asm", 0
.code
; WinAPI to call
extrn stdcall Beep#8 : proc
useless_sh_t_function__get_GS_a_string_and_beep PROC
; parameter = CHAR** for a string pointer
; return = value of GS register selector
mov eax, [esp + 4]
mov [eax], OFFSET str_from
push dword ptr [beep_dur]
push dword ptr [beep_freq]
call Beep#8
mov eax, gs
ret
useless_sh_t_function__get_GS_a_string_and_beep ENDP
ENDIF
END
main.cpp file:
#include "stdafx.h"
#include <Windows.h>
extern "C" {
size_t useless_sh_t_function__get_GS_a_string_and_beep(const CHAR** ppString);
};
int main()
{
const char* pString = NULL;
size_t nGS = useless_sh_t_function__get_GS_a_string_and_beep(&pString);
printf("gs=0x%Ix, %s\n", nGS, pString);
return 0;
}
Good that you found a way to handle your use case.
However, if you have more asm files, or only need them for some build types, you could also change the settings for each individual file for the parts where it differs from the project defaults.
Just right-click a file name to get to its individual properties.
To have an asm file included in x64 builds only, you can use these settings:
And then exclude it from 32-bit builds:
These settings are available for all file type, not only for .asm files.
Here's what my screen looks like when I hit "Local Windows Debugger", then click the breakpoint button. The point it goes to is.....
http://i.stack.imgur.com/yufiH.png
My asm file says:
.model small
.stack
.data
.code
_Func proc
mov ax, 1
leave
ret
_Func endp
end
And the cpp file:
extern "C" {
int Func();
}
int main(int argc, char** argv) {
Func();
return 0;
}
So I'm wondering, why does this code hit this weird breakpoint. It isn't in my code...
And yes, I know what "int 3" in assembly means, that isn't what I'm wondering about. It isn't my code but it doesn't let my code run...
.model small is for 16-bit-MSDOS, not for 32-bit-Windows (Win32). Try following code:
.model flat
.code
_Func proc
mov eax, 1
ret
_Func endp
end
I am now trying to compile the following codes with gcc and codeblock:
#include <stdio.h>
int main()
{
char alphabet = 'X';
printf ("Type letter = ");
asm{ //line 8
mov ah, 02
mov dl, [alphabet] // line 9
int 21h
}
printf ("\n");
return (0);
}
The error messages I have got are as follows:
error: expected '(' before '{' token line 8
error: 'mov' was not declared in this scope line9
I am compiling for x86 computer, and was wondering how I could compile the above codes successfully. Thanks!
Unfortunately gcc doesn't support simple syntax like this:
asm {
mov ah, 02
mov dl, [alphabet]
int 21h
}
You can find more information on the gcc-inline-assembler with the link DCoder commented: click me
Explaining everything would be too much for an answer, so I simply write the code for gcc, which should do the job for you:
__asm__(
"movb $2, %%ah;"
"movb %0, %%dl;"
"int $0x21;"
:
: "r"(alphabet)
: "%ah", "%dl"
);
Note, that you can also use the keyword asm instead of __asm__.