1.11M Members

Assembly vs. C++ Performance

 
0
 

Alright guys, I'm a total n00b to assembly. NOTE: I am not a student -- I am a professional lawyer who loves to tinker with the computer and waste time.

Using Visual Studio 2008 Express (C++), I actually managed to write a function in assembly language that evaluates a character, and if it is a lower case letter, returns the corresponding uppercase letter, if not a lower case letter, returns the same character evaluated.

I wrote this function in C++, assembly (in-line) and assembly (MASM).

Here is the C++ Code:

char cppToUpper(char c)
{
    if (c > 122 || c < 97 )
	   return c;
    else return c - 32;
}

Here is the inline assembly Code:

char cToUpper(int c)
{
    //
    //cout << cLowerLimit;
    _asm
    {
    
    //Copy the character onto the arithmetic register for single bytes
	   mov eax, c;

    //Test the Upper Limit
	   cmp eax, 122; // Compare the Character to 122
	   ja End;  //  Jump to the end if above -- the character is too high to be a lower case letter
	
    //Test the lower limit
	   cmp eax, 97 //Compare the character to 97
	   jb End; // Jump to the end if below == the character is too low to be a lower case letter
	   
	   //Now the operation begins
	   sub eax, 32; //Subtract 32 from the character in the register

	   
     End:
	 // mov result, al; //Move the Character in the register into the result variable

    }
    

}

And here is the function in pure assembly language:

.686
.model flat, stdcall
option casemap :none

.code

cUpperCase2 proc cValue:DWORD

  mov eax, cValue
  
  cmp eax, 122
  
  ja TEnd
  
  cmp eax, 97
  
  jb TEnd
  
  sub eax, 32
  
  
              
  TEnd:

    ret
      
cUpperCase2 endp

end

Now, here is what the C++ function disassembles to:

char cppToUpper(char c)
{
01271680  push        ebp  
01271681  mov         ebp,esp 
01271683  sub         esp,0C0h 
01271689  push        ebx  
0127168A  push        esi  
0127168B  push        edi  
0127168C  lea         edi,[ebp-0C0h] 
01271692  mov         ecx,30h 
01271697  mov         eax,0CCCCCCCCh 
0127169C  rep stos    dword ptr es:[edi] 
    if (c > 122 || c < 97 )
0127169E  movsx       eax,byte ptr [c] 
012716A2  cmp         eax,7Ah 
012716A5  jg          cppToUpper+30h (12716B0h) 
012716A7  movsx       eax,byte ptr [c] 
012716AB  cmp         eax,61h 
012716AE  jge         cppToUpper+37h (12716B7h) 
	   return c;
012716B0  mov         al,byte ptr [c] 
012716B3  jmp         cppToUpper+3Eh (12716BEh) 
012716B5  jmp         cppToUpper+3Eh (12716BEh) 
    else return c - 32;
012716B7  movsx       eax,byte ptr [c] 
012716BB  sub         eax,20h 
}
012716BE  pop         edi  
012716BF  pop         esi  
012716C0  pop         ebx  
012716C1  mov         esp,ebp 
012716C3  pop         ebp  
012716C4  ret

ALRIGHT HERE'S the question. Why is the C++ code considerably faster even though it compiles to far more instructions than my assembly language code uses? 48 "ticks" expire when executing the pure assembly language function 10,000,000 times (I'll put this stuff at the very bottom); 0 ticks when executing it in C++, and 16 when using inline assembly?

I am impressed that I was even able to get it to work in assembly but perplexed at the performance results. I'll put the main() function below along with the efficiency timing stuff for your reference.

Any ideas? I am just trying to learn a little assembly because I am curious about how computers actually work.

Thanks,
Chris

#include "stdafx.h"
#include <iostream>
#include <string>
#include "windows.h"
#include "time.h"
using namespace std;
extern "C" int _stdcall cUpperCase2(char c);

class stopwatch
{
public:
 stopwatch() : start(clock()){} //start counting time
 ~stopwatch();
private:
 clock_t start;
};

stopwatch::~stopwatch()
{
 clock_t total = clock()-start; //get elapsed time
 cout<<"total of ticks for this activity: "<<total<<endl;
 cout <<"in seconds: "<< double(total/CLK_TCK) <<endl;
}

void main()
{
bool bAgain = true;

    while (bAgain)
    {
//     unsigned long lTimeNow = t_time;

     

	   	char c = 'a';
		char d = '!';
		char e;

	//cout << "A lowercase character will be converted to Uppercase:" << endl;
	//cin >> c;
	  {
		   stopwatch watch;
		   for (int i=0; i < 10000000; i++) 
		   {
			 e= cUpperCase2(c);
			 e= cUpperCase2(d);
		   }
    	     
	    }
		  cout << "That was the external function written in assembler." << endl;
	
	    {
		   stopwatch watch;
		   for (int i=0; i < 10000000; i++) 
		   {
    		  
			 // cout << cppToUpper(c);
			 //cout << cppToUpper(d);
			 e= cppToUpper(c);
			 e= cppToUpper(d);
		   }
    	   
	    }
	    cout << "That was C++\n";
	   {
		   stopwatch watch;
		   for (int i=0; i < 10000000; i++) 
		   {
			 e= cToUpper(c);
			 e= cToUpper(d);
		   }
    	 
	    }
	        cout << "That was in line assembler\n";
	 


	    cout << "Enter a letter and hit enter to exit (a will repeat) . . ." << endl;
	    cin >> c;

	//return 0;
	    if (c != 'a')
		  bAgain = false;

    }	

}
 
0
 

Alright to simply answer your question as to why C++ is "faster" than Assembly, the reason being is because at some time in the 50's or 60's (don't remember when) at the Bell company (or some company) some programmers were sick of coding in Assembly Languages so they asked their bosses if they could create a simpler new language also known as C which was created in Assembly (correct me if I'm wrong considering thats what they were coding in.) at some point C++ was made (duno by who) which is an extended version of C (adding more capabilities) so C / C++ were made to make programming quicker because Assembly is a low level programming language (non-english syntax) and C / C++ along with a lot of other languages are high level languages (english-like syntax) so programming is easier because its more english like so it would take you less time to make a server for a huge game in C++ than it would in Assembly if you don't end up with a brain tumor before you finish.

 
0
 

The person who posted above me is completely wrong. Assembly is faster than any other code if you use/code it correctly. It could be that the optimizations the compiler made for the C++ code were good optimizations, whereas the code you wrote was poorly designed and written.

 
0
 

The person who posted above me is completely wrong. Assembly is faster than any other code if you use/code it correctly. It could be that the optimizations the compiler made for the C++ code were good optimizations, whereas the code you wrote was poorly designed and written.

Best Jew: you are half right. Assembly speed = C++ as C++ is compiled into assembly code. With handwritten assembly, you might be able to make the routine more efficient than the C++ compiler does. On most modern systems though, the results aren't noticeable. The difference is that C++ is much faster development time while assembly is much better for custom processors.

 
0
 

Yeah, I know that. What I was saying is that if the C++ code was good to begin with, and the compiler optimized it well, whereas the assembly was poorly written....

 
0
 

Hi guys. Thanks for the replies. I kinda guessed that the reason why the routine in assembly was slower was because it was poorly written -- I am not a pro programmer and that seems like the only logical explanation. Nevertheless, I was rather surprised at that result -- compare the how many lines of code my assembly function takes to the lines of (assembly) code the c++ functionis compiled into. I was wondering whether you had any thoughts on why, in this particular example, the c++ code runs faster even though it has so many more lines of code. I was puzzled.

 
-1
 

That code cant be best possible because assembly is much faster and u can know it because its used on bootloaders and other things that need extreme speed. i also know that microsoft compilers arent usually very good. For example microsoft visual c++ compiles code that does nothing into 155kb as mingw based (mingw is made from gcc) dev-cpp compiles it into 15kb. somebody should try some different compiler(NASM for example)

 
0
 

hi cpsusi,

I can't find anything wrong with your assembly. The C++-output however looks awful. And I also don't have a clue why it perform worse than your C++-code.

A reason might be, that MASM puts tons of unnecessary stuff to your simple code. Try NASM instead. That really is a reliable and fast assembler. Maybe you can get the programm run faster than compiled in C++.

 
0
 

Assembly code is the faster and lightweight(If written efficiently).

People say that C++ code is faster because in most cases and when the program is large, the code optimizer and intermediate code generator of C++ compiler produces more efficient assembly code than those written by hand.

If you write Assembly code properly, it will be faster

Please correct me if i am wrong

 
0
 

The reason C++ shows 0 ticks is because the compiler optimizes the code away! The loop is never executed because the result is known for every iteration. In the case of the inline Assembly or external assembly program the code is there unmodified!

 
0
 

The speed depends on how well the code was written, in asm and C/C++.
And to correct the above history to my understanding:
People at IBM where sick of programing in assembly so they asked there bosses if they could make a more portable and convenient language: FORTRAN.
Because most high quality ASM was fast (and in those days FASTwas important) FORTRAN had to compete with a language that when well written is still very fast today it had to be just as good or better. C was made (coughsotheycouldbragtootherpeoplecough) for general purpose/UNIX. And (how many grammatical mistakes have I made?) UNIX got C going, and since inertia applies to software, C/C++ will be around for a long time.
To explain my last sentence: read newton's first law then look at computers, x86 wont leave the stage for a long time (there is an x86-64 and I count that under x86) there is a reson that windows won't be replaced for a long time (wine once working well could be a strong unbalanced force, for more search World Domination 201, it should be first link), Almost everything basic and leading up to will be C/C++ , leading up to what? Java, I hate it (it's syntax, I have not yet used oop and will use it when I want to not everywhere like java) but over 50% of code written is written in java. Interact applies to coputers, wow I did all this to explain the strange world of computers... End Rant

 
0
 

Assembly, is the fastest language that exists, because thats the processor "human-undestandable" language, for now, you can't build a faster or smaller application than the assembly ones

 
1
 

The truth of the matter is, you can write slow code in any language, and it is generally a lot easier to write inefficient code than efficient code. The main advantage of C - and high-level languages in general - is that it is easier to write fast code in them than in assembly.

This does not mean that C is faster than assembly. In the end, all code is running in machine code, regardless of how it is implemented - even interpreted code is running as a machine code program, just as one that happens to interpret some text as a series of instructions. Assembly language is harder to write efficiently, and beating an optimizing compiler takes considerable skill. In the end, however, assembly code isn't simply faster; it is all there really is. Everything else is for giving you a more accessible notation - they improve the efficiency of the programmer, not of the program.

Mind you, on multitasking systems, especially those with virtual memory (which is nearly all of them today), the speed with which a program runs has more to do with the speed of the processor, the system load, and the available real memory, than with the efficiency of the program itself. Furthermore, IMAO, efficiency for event-driven programs is false fire - your program will spend more time waiting on user events (mouse clicks, keypresses) than on actual processor time. Even in CPU-bound code, most of the processing time is usually in a single small area of the program - the 'bottleneck' - and only that section really benefits from extensive optimization, and the location of the bottleneck can only be determined empirically after careful testing and profiling.

This isn't to say that efficiency isn't desirable, but in real-world terms, programmer efficiency is worth far more than code size and speed. It usually makes sense to use an effective notation - that is, a suitable HLL that matches the problem domain - and get the program working correctly, then profile the result and if necessary, optimize the bottlenecks away in assembly. Trying to optimize the whole program is rarely worth the effort, and is more likely to result in what assembly-language guru Michael Abrash calls a 'fast slow program' than a really efficient one.

(And don't forget to test your 'optimization' afterwards, as it may end up running slower than the 'unoptimized' version! Abrash mentions a case of this happening at the beginning of chapter 3 of the Graphics Programming Black Book - which is still the best work on assembly code optimization out there after over fifteen years.)

To sum up: knowing assembly language and efficient programming techniques is both useful and desirable, but knowing when to use them is even more important.

 
1
 

A relevant quote from Abrash on this topic may clarify things:

Never underestimate the importance of the flexible mind. Good assembly code is better than good compiled code. Many people would have you believe otherwise, but they’re wrong. That doesn’t mean that high-level languages are useless; far from it. High-level languages are the best choice for the majority of programmers, and for the bulk of the code of most applications. When the best code - the fastest or smallest code possible - is needed, though, assembly is the only way to go.

Simple logic dictates that no compiler can know as much about what a piece of code needs to do or adapt as well to those needs as the person who wrote the code. Given that superior information and adaptability, an assembly language programmer can generate better code than a compiler,all the more so given that compilers are constrained by the limitations of high-level languages and by the process of transformation from high-level to machine language. Consequently, carefully optimized assembly is not just the language of choice but the only choice for the l percent to 10 percent of code - usually consisting of small, well-defined subroutines - that determines overall program performance, and it is the only choice for code that must be as compact as possible, as well. In the run-of-the-mill, non-time-critical portions of your programs, it makes no sense to waste time and effort on writing optimized assembly code-concentrate your efforts on loops and the like instead; but in those areas where you need the finest code quality, accept no substitutes.

Note that I said that an assembly programmer can generate better code than a compiler, not will generate better code. While it is true that good assembly code is better than good compiled code, it is also true that bad assembly code is often much worse than bad compiled code; since the assembly programmer has so much control over the program, he or she has virtually unlimited opportunities to waste cycles and bytes. The sword cuts both ways, and good assembly code requires more, not less, forethought and planning than good code written in a high-level language. [Emphasis added]

 
0
 

Sorry to be so late, but I just read this forum post.

The answer to why the assembler implementation showed a slower time is quite simple, and it's something you can test to prove. The main reason is that an external DLL was called, which is slower than the other calls.

As stated previously, the C++ compiler likely identified this code as "doing nothing" and optimized it to run just once. That takes virtually no time at all. (You can test a slight change to the algorithm to convince the compiler that this is real code that should be executed by, for example, using the output of the first call as input to the second, and saving the result to be reused the next iteration.)

The assembler code is completely different from the other two tests because it's called from an external DLL, which will be slower than the other calls. You should be able to test this by creating an external function that does nothing but return, and compare that speed to this function that converts case. And the difference between those two tests will tell you how fast the assembler code is.

 
0
 

Of all the people who answered, only ejamesr seems to have read the 'question'.Nice work mate!
cpsusie posted the exact code, so why the hell do people say: 'if you write better code in assembly, it should be faster...' - well if that's the case post the 'better' or 'optimized' code in assembly!

 
0
 

In general, assembly IS faster than C++ because it's simply is the computer language, you can see that every single executable is written in a language then its moved to assembly and then hex...In inline, i think the asm part will be better, but i'm not that sure

 
0
 

Assembly vs. C++ Performance

 
0
 

I've been watching this thread for a while and can offer a solution.
The program has a dynamic data item, which gets over written.
it's called self modifying code when a dynamic variable occupies the same 2048kb memory block as the code. which is being executed
You need to separate the code from the variable.

It's explained here.
The difference in speed is massive.

http://www.bbcbasic.co.uk/bbcwin/manual/bbcwina.html#cache

So you need to find out how to separate your executing code and any dynamic variables for your particular flavour of assembly

You
This article has been dead for over six months: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article