This question already has answers here:
What is the difference between 'asm', '__asm' and '__asm__'?
(4 answers)
Closed 3 years ago.
Several years ago I wrote some significant Cpp code that accessed the hardware registers by a coding command that switches to assembler language. I lost the compiler and computer. Please tell me a Cpp compiler that allows inline asembler in the middle of the Cpp code. Intel cpu, Windows. Thank you.
It seems I lacked clarity in the question. My apologies. The answers given were a refresher of the code. Well done. The answers given today suggest the C++ compilers might not have been updated for 64 bit assemblers. Here is a clearer question which has been only partially answered. It needs an updated response.
I am thinking of buying an Intel i7 desk computer. I will write C++ code for i/o and setup. The inner loops will be written in assembler language to take advantage of the hardware register multiply and divide: two multiplicands in separate registers give a double register product. My experience years ago was that not all C++ compilers are alike. Which of the many brands of C++ software out there give a good link to assembler, __asm, and make full advantage of 64 bit machines?
I feel this question has not been asked. Thanks for the great answers so far.
I once used Microsoft Visual Studio to write inline assembly, like this:
// --- Get current frame pointer
ADDR oriFramePtr = 0;
_asm mov DWORD PTR [oriFramePtr], ebp
Unfortunately, this only worked for 32-bit, because at that time the 64-bit compiler of Microsoft didn't support inline assembly (didn't check recently).
By default, C++ provides the asm keyword for writing assembly (bolded by me):
7.4 The asm declaration [dcl.asm]
1 An asm declaration has the form
asm-definition:
asm ( string-literal ) ;
The asm declaration is conditionally-supported; its meaning is implementation-defined. [ Note: Typically it is used to pass information through the implementation to an assembler. — end note ]
GCC appears to support asm based on the above article on asm, but I couldn't find anything besides its support in C
MSVC does support assembly, but not via the asm keyword; one must use __asm:
The __asm keyword invokes the inline assembler and can appear wherever a C or C++ statement is legal.
Visual C++ support for the Standard C++ asm keyword is limited to the fact that the compiler will not generate an error on the keyword. However, an asm block will not generate any meaningful code. Use __asm instead of asm.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I'm currently trying to get into OS development, mostly following the articles and tutorials from OSDev. As os now, I have multiple assembly files I need to e.g. enable paging and setting up long mode.
While the only assembler code I'm certain about needs to be separated in an own file is the boot assembly file, I'm curious about the practices and "standards" how to deal with assembly in an OS written in C. Is it convenient to separate assembler from C or is there a reason why e.g. Linux wraps most of the assembly code inside C functions and calls them using the asm volatile directives?
I don't see much difference, as you can return results from assembly by moving the value into the eax register, or when using asm and asm volatile, you can specify parameters and output operands where to store the result. However, you always need to separate multiple instructions by using \n or \n\t.
As of now, I only found out about the different ways of dealing with assembly in a larger project, but not why some chose to separate assembly code from C or C++, and why some chose to use inline assembly thorough the whole program.
I hope you could give me some insights about the different ways used regarding this topic.
Interface, Procotol & Conventions
In a pure assembly language project, you need to set up protocols or conventions for passing values and returning values.
When mixing assembly language functions with C or C++, you will need to follow the parameter passing conventions of C or C++ as dictated by the compiler you are using.
Some compilers may use a convention of passing the first parameter in R0, while others may pass the last parameter in R0. Some compilers may place the variables on the stack and not use registers. Others may use registers for a few parameters and the remaining on the stack.
Inline vs Separate Assembly functions
One issue is portability. Assembly language is processor specific. For example, ARM assembly doesn't have an EAX register. Intel assembly doesn't have R10 register. When using inline assembly, the assembly must change depending on the processor, which includes modifying the high level language function to account for all target processors. When implementing as a separate assembly function (file), only the file needs to be swapped out when porting to other processors.
IMHO, pure assembly functions are easier to read than intermixed C and inline assembly.
Guidelines for High Level Language Usage in OS
The quantity of assembly language should be minimized. Assembly language takes longer to develop (typing, and debugging, more lines == high possible injected defects), whereas the high level language is more productive with lower risks.
Prefer to write the entire OS in a high level language. Get this version working robustly. Replace C functions with assembly functions for more efficiency, or when specific assembly language instructions are required.
This question already has answers here:
How can I detect g++ and MinGW in C++ preprocessor?
(2 answers)
Closed 7 years ago.
EDIT: Ha ha, search terms are a weird thing. I actually had to use the answer I got as a term for the search to finally find this question. In the spirit of StackOverflow, I'll vote to close my
own question as duplicate instead of deleting it, in case it'll serve as a landing point for
someone else.
I am writing several functions that are using asm, but I only want them to function when they're compiled with a compiler that can work with NASM. (I'm on C++11, by the way.)
I'm a little bit new to the whole concept of asm, but this is what I think I know:
GCC and its "relatives" (MinGW, TDM-GCC) use NASM, which is what I'm writing my functions for.
All Intel and AMD processors can theoretically understand NASM, regardless of operating system, because...
The X86/X64 assembler is determined by what the compiler implements.
Assuming the above is correct, what macro can I use to ensure that the functions I'm writing are defined if and only if I'm using a GCC (or similar) compiler, or a compiler that uses NASM? (The #ELSE would be a usable dummy version of the function to ensure general compatibility with other compilers.)
The only macros I know about of this sort relate to determining operating system (such as #IFDEF _WIN32), but that macro would incorrectly get used in the situations where I'm compiling with TDM-GCC or MinGW on Windows.
NOTE: In case anyone wonders, the functions in question are basically
"helpful, but not vital" utility functions. We don't have any plans to
compile with a non-GCC compiler, but it's open source code, so we want
to be considerate of others.
You can use the __GNUC__ macro to identify GCC (and some mostly compatible compilers like Clang and Intel's C++ compiler).
MinGW (any version) can be checking for __MINGW32__ and/or __MINGW64__.
This question already has answers here:
Do all C++ compilers generate C code?
(5 answers)
Closed 8 years ago.
I have read that the original implementation of C++ by Bjarne Stroustrup was using a compiler named Cfront that converted C++ to C during the compilation process.
Is this still the case with modern compilers (most of them ?) ?
I couldn't find a good answer using Google (or I couldn't find the right search terms).
edit: This is not an exact duplicate because I'm asking for current/modern ones. But both questions & answers apply.
Absolutely not. The CFront way of doing things became untenable long ago. There are some C++ constructs with no C interpretation, especially exceptions, and stamping out literal C source for every template instantiation is a bit ridiculous. The entire reason Bjarne stopped making Cfront is because it was impossible.
It is, however, common to lower the code to a more useful IR like LLVM IR, and GCC also has an internal IR, before converting to machine code.
Short answer: no. Modern C++ compilers generate native code directly.
There's no reason why you can't compile C++ to C, there's just no real reason to do so either any more, so you're adding an extra stage in the compilation process that could just as easily not exist. However, there are still a couple of options if you really need C code output for some reason: the Comeau C++ compiler emits C code with the aim of porting your C++ to platforms where a C++ compiler may not exist (which these days, is very few), and Clang uses LLVM as a backend code generator, which has C as one of its many target instruction languages. (edit: of these options, the first is outdated and the second is no longer maintained)
In neither case does the C look anything like the code you put in: it's significantly less readable than machine code would be. The days of converting method calls to function calls with a this are certainly long gone - it's very much a case of "compiling" rather than "converting".
No, modern compilers, such as GCC and clang (and others based on LLVM) have generally two parts: back-end and front-end.
Front-end handles compiling source code language into some intermediate representaton, such as LLVM IR.
Back-end generates machine code on target platform, possibly using some optimisations from that intermediate form.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have been making a programming language compiler in C++, which converts my code to Assembly. However, I do not know how to the convert this assembly code into an executable format (.exe preferably). How would I be able to do that?
Use Microsoft Macro Assembler 8.0 (MASM) Package (x86)
The Microsoft Macro Assembler 8.0 (MASM) is a tool that consumes x86 assembly language programs and generates corresponding binaries.
You assemble assembly code rather than compile it, and an assembler is the tool you need for that.
The exact assembler that you will need will depend on the target instruction set - assembly language is not in fact a language, it describes any language where mnemonics are used to represent individual machine code instructions.
Even for a single architecture, assembly language syntax may vary - for example on x86 there are at least two syntaxes - Intel and AT&T, so even for x86 you will need an assembler that copes with whatever syntax your tool outputs. Your tool will of course need to output something that can be used by the assembler, which may mean the generation of additional assembler and target specific directives rather than just the raw assembler mnemonics.
It may have been simpler for your language compiler to output C or C++ code (strictly a translator rather than a compiler), that is how early C++ "compilers" worked (and Comeau C++ still does), your language will then at least be more easily portable between different architectures. C compilers are almost as ubiquitous as assemblers for any target, but translation to C allows you to have a single back-end for all target architectures.
I'm writing a performance-critical, number-crunching C++ project where 70% of the time is used by the 200 line core module.
I'd like to optimize the core using inline assembly, but I'm completely new to this. I do, however, know some x86 assembly languages including the one used by GCC and NASM.
All I know:
I have to put the assembler instructions in _asm{} where I want them to be.
Problem:
I have no clue where to start. What is in which register at the moment my inline assembly comes into play?
You can access variables by their name and copy them to registers.
Here's an example from MSDN:
int power2( int num, int power )
{
__asm
{
mov eax, num ; Get first argument
mov ecx, power ; Get second argument
shl eax, cl ; EAX = EAX * ( 2 to the power of CL )
}
// Return with result in EAX
}
Using C or C++ in ASM blocks might be also interesting for you.
The microsoft compiler is very poor at optimisations when inline assembly gets involved. It has to back up registers because if you use eax then it won't move eax to another free register it will continue using eax. The GCC assembler is far more advanced on this front.
To get round this microsoft started offering intrinsics. These are a far better way to do your optimisation as it allows the compiler to work with you. As Chris mentioned inline assembly doesn't work under x64 with the MS compiler as well so on that platform you REALLY are better off just using the intrinsics.
They are easy to use and give good performance. I will admit I am often able to squeeze a few more cycles out of it by using an external assembler but they're bloody good for the productivity improvement they provide
Nothing is in the registers. as the _asm block is executed. You need to move stuff into the registers. If there is a variable: 'a', then you would need to
__asm {
mov eax, [a]
}
It is worth pointing out that VS2010 comes with Microsofts assembler. Right click on a project, go to build rules and turn on the assembler build rules and the IDE will then process .asm files.
this is a somewhat better solution as VS2010 supports 32bit AND 64bit projects and the __asm keyword does NOT work in 64bit builds. You MUST use external assembler for 64bit code :/
I prefer writing entire functions in assembly rather than using inline assembly. This allows you to swap out the high level language function with the assembly one during the build process. Also, you don't have to worry about compiler optimizations getting in the way.
Before you write a single line of assembly, print out the assembly language listing for your function. This gives you a foundation to build upon or modify. Another helpful tool is the interweaving of assembly with source code. This will tell you how the compiler is coding specific statements.
If you need to insert inline assembly for a large function, make a new function for the code that you need to inline. Again replace with C++ or assembly during build time.
These are my suggestions, Your Mileage May Vary (YMMV).
Go for the low hanging fruit first...
As other have said, the Microsoft compiler is pretty poor at optimisation. You may be able to save yourself a lot of effort just by investing in a decent compiler, such as Intel's ICC, and re-compiling the code "as is". You can get a 30 day free evaluation license from Intel and try it out.
Also, if you have the option to build a 64-bit executable, then running in 64-bit mode can yield a 30% performance improvement, due to the x2 increase in number of available registers.
I really like assembly, so I'm not going to be a nay-sayer here. It appears that you've profiled your code and found the 'hotspot', which is the correct way to start. I also assume that the 200 lines in question don't use a lot of high-level constructs like vector.
I do have to give one bit of warning: if the number-crunching involves floating-point math, you are in for a world of pain, specifically a whole set of specialized instructions, and a college term's worth of algorithmic study.
All that said: if I were you, I'd step through the code in question in the VS debugger, using the Disassembly view. If you feel comfortable reading the code as you go along, that's a good sign. After that, do a Release compile (Debug turns off optimization) and generate an ASM listing for that module. Then if you think you see room for improvement...you have a place to start. Other people's answers have linked to the MSDN documentation, which is really pretty skimpy but still a reasonable start.