Assembly language programming vs Other programming languages

Click For Summary
Assembly language is generally faster than higher-level languages like C, C++, or Python due to its closer proximity to machine code, allowing for more direct control over hardware. While compilers translate C code into machine code, they may introduce inefficiencies, whereas assembly allows programmers to optimize performance by eliminating unnecessary code. The size of executables can vary significantly between languages, with assembly producing much smaller binaries compared to C or VB.NET. However, for most applications, using assembly is considered overkill due to the extensive time required for development and maintenance compared to higher-level languages. Ultimately, while assembly can yield performance benefits, the trade-offs in productivity and maintainability often lead developers to choose higher-level languages for most tasks.
  • #91
ChrisVer said:
Wait, I am confused- why is jmp an example for not 1-to-1 correspondance between assembly and machine code?
My point was that the translated instruction is different depending on the address of the target of the jump. The assembler needs to figure out this address during compilation. So it's not really 1:1 correspondence between what you write and what results. Some CPUs have relative addressing of jumps, so
Code:
jmp imalabel
can result in different bytes every time it is used.
Compiling C, in my opinion, is more of the same, not something qualitatively different.
 
Technology news on Phys.org
  • #92
I think TMT has been misunderstood. Maybe English is not his first language? Anyway, I get the gist of the point he's trying to make. As SlowThinker pointed out, assembly does not always translate to the same string of machine code. The assembler is to assembly language what the compiler is to high level languages. It's just that modern high level languages have taken this idea to the extreme. In both cases the language was created to make programming easier and faster for humans.
 
  • #93
Remember debug that came with DOS? I remember using only debug to write assembly code that could be called from BASIC. It was a powerful combination. I remember my coworkers being dazzled and saying "Wow, how did you do that"?

But my first introduction to assembly was with the TRS-80 back in the late 70's. I wanted to write a program to send Morse code (ham radio), but I quickly discovered that BASIC was too slow, especially with a CPU running at less that 2MHz. So I ordered the technical reference manual for the TRS-80 and the instruction set for the Z80 microprocessor. I was amazed at being able to have complete control of the machine and all it's hardware. I remember dreaming of one day writing my own operating system. And it was probably a doable thing for just one person back in those days.

Even though I haven't used it for many years, assembly remains my favorite programming language. Modern machines and compilers have become so good that it's just no longer practical in most cases (except for microcontollers). Who cares if it takes 16k to do Hello World? It's kind of funny that 16k was the maximum RAM size on my TRS-80.
 
  • #94
TurtleMeister said:
I think TMT has been misunderstood. Maybe English is not his first language? Anyway, I get the gist of the point he's trying to make.

I think the point is that programming languages are normally considered "high-level" or "low-level" depending on how much they abstract the details of the hardware you're programming on. So Assembly is "low-level" because you're expressing how a program should accomplish some task directly in terms of the set of instructions supported by the processor. C is higher-level than Assembly but still a relatively low-level language: it hides the specific processor instruction set, but its feature set still largely corresponds to that of a sort of hypothetical "generic" processor and addressable memory. (One of C's nicknames is "portable assembly".)

Higher-level languages offer more insulation from the hardware, e.g. with features like automatic memory management, built-in collection types like lists and associative arrays, arbitrary-size integers that don't overflow, an exception system, anonymous functions/closures, dynamic typing, code and/or object reflection/introspection capabilities, etc.
 
  • #95
wle said:
I think the point is that programming languages are normally considered "high-level" or "low-level" depending on how much they abstract the details of the hardware you're programming on. So Assembly is "low-level" because you're expressing how a program should accomplish some task directly in terms of the set of instructions supported by the processor. C is higher-level than Assembly but still a relatively low-level language: it hides the specific processor instruction set, but its feature set still largely corresponds to that of a sort of hypothetical "generic" processor and addressable memory. (One of C's nicknames is "portable assembly".)

Higher-level languages offer more insulation from the hardware, e.g. with features like automatic memory management, built-in collection types like lists and associative arrays, arbitrary-size integers that don't overflow, an exception system, anonymous functions/closures, dynamic typing, code and/or object reflection/introspection capabilities, etc.

I agree. If you must draw a line between low-level and high-level then it would be the degree of isolation from the hardware. However, I don't think that was the point of misunderstanding.

TMT said:
I think both of you could not catch the idea by this example. I mean assembler may be count as high level languages if you consider a program (assembler) takes some line of instruction and create machine code. Same as high level language a program (compiler) takes lines of expression and (mostly) creates assembler (text code) than assembler creates machine code from it. Same pattern implemented.

phinds said:
That is NOT a reasonable use of the term "high level language". Assembly is specifically NOT a higher level language.

Assembly is not a higher level language. If you choose to call it so, you are defying standard terminology and people will disagree with you.

I do not think TMT is claiming that assembly is a high-level language per se, but only pointing out the similarities between the assembler and the compiler. And I also agree with TMT that assembly is not the same thing as machine code. Machine code makes me think of the computers before keyboards and monitors where you entered code via toggle switches and push button. And depending on the editor you're using, assembly language could be considered "higher level" than machine code. You can, for example, use variables in assembly programming. This in effect isolates you more from the machine than if you were doing machine code only.
 
  • #96
TurtleMeister said:
I do not think TMT is claiming that assembly is a high-level language

Well, I guess I was misled by his saying:

TMT said:
... assembler may be count as high level language

I tend to take words to mean what they say. I realize there were caveats on both of your statements but I don't think they negate the underlying statements. At any rate, we're arguing about how many angels can dance on the head of pin
 
  • #97
phinds said:
Well, I guess I was misled by his saying:

TMT said:
... assembler may be count as high level languages

That is really unfair to @TMT . His full quote was followed by an 'if':
TMT said:
I mean assembler may be count as high level languages if you consider a program (assembler) takes some line of instruction and create machine code. Same as high level language a program (compiler) takes lines of expression and (mostly) creates assembler (text code) than assembler creates machine code from it. Same pattern implemented.
Which clearly states that (following the OP's question) assembly language is to machine code, what other programming languages are to assembly language.

His opinion was that, with respect to machine code, assembly language is a higher level language which, I think, was demonstrated by @SlowThinker .
 
  • #98
TMT said:
I mean assembler may be count as high level languages if you consider a program (assembler) takes some line of instruction and create machine code.
Let's not refer to assembly and macro-assembly as "high level languages". That phrase was coined specifically to exclude such languages.
What makes a language "high level" is more than whether there is a one-to-one match between "lines of code" and machine instructions. For example, high level languages are expected to be portable from one processor to another.

The "generation" of the programming language is a closely related term. See https://en.wikipedia.org/wiki/Programming_language_generations.
 
  • Like
Likes jim mcnamara
  • #99
I'm going to stay out of this. But there are definition issues. Clear debate requires that every use the same terms with exactly the same meaning. Can we agree on meanings?

We also seem to have ESL issues, too. I've been part of discussions in languages that are not my native language. It is really hard to do well sometimes. FYI.
ESL=English as a Second Language.

So please try to work out definitions clearly, first. Thanks.

Thanks to @.Scott for trying.

This thread has some good content!
 
  • #100
jim mcnamara said:
I'm going to stay out of this. But there are definition issues. Clear debate requires that every use the same terms with exactly the same meaning. Can we agree on meanings?

We also seem to have ESL issues, too. I've been part of discussions in languages that are not my native language. It is really hard to do well sometimes. FYI.
ESL=English as a Second Language.

So please try to work out definitions clearly, first. Thanks.

Thanks to @.Scott for trying.

This thread has some good content!
Well, I think that everyone here would agree that:
Machine code = low level
Assembly = low level
C and most everything else = high level

It seems to me that the argument is whether it's ok to say that assembly is a higher level language than machine code rather than saying that they are the same thing.

Anyway, I agree that the thread has some good content, but I must leave for a while. Will check back when I can.
 
  • #101
jim mcnamara said:
I'm going to stay out of this. But there are definition issues. Clear debate requires that every use the same terms with exactly the same meaning. Can we agree on meanings?
Good idea. I've been too stuck on details, I think.

I understand what everyone is saying about the difference between machine code and assembly language, but let's do all stick to the standard terminology and agree that assembly is not a higher level language and in fact is disallowed from BEING a high level language by definition and common usage of the phrase.

The original question as about the speed difference between assembly language (~ machine code) vs high level languages. Are there still open questions about that?
 
  • #102
phinds said:
The original question as about the speed difference between assembly language (~ machine code) vs high level languages. Are there still open questions about that?
Most people think assembly is speedy than high level languages. But I'm telling if high level language is configured more intelligently, it may be faster than assembler. Speed is majorly dependent on algorithms. if you implement an algorithm time cost as W(n) in assembly code (supposed as faster) a high level language (basic or any interpreted) implement algorithm time cost as W(log n) your assembly programs will breath the dust of the high level language implementation.
Also the intelligence embedded in high level language may generate speeder code. since embedded algorithm may create more optimized code than human can create.
 
  • Like
Likes ChrisVer
  • #103
TMT said:
Most people think assembly is speedy than high level languages. But I'm telling if high level language is configured more intelligently, it may be faster than assembler. Speed is majorly dependent on algorithms.
Well, of course. No one in this thread is claiming that a slow algorithm coded in assembly will run faster than a faster algorithm coded in a higher-level language.
TMT said:
if you implement an algorithm time cost as W(n) in assembly code (supposed as faster) a high level language (basic or any interpreted) implement algorithm time cost as W(log n) your assembly programs will breath the dust of the high level language implementation.
Also the intelligence embedded in high level language may generate speeder code. since embedded algorithm may create more optimized code than human can create.
 
  • #104
TMT said:
Most people think assembly is speedy than high level languages. But I'm telling if high level language is configured more intelligently, it may be faster than assembler. Speed is majorly dependent on algorithms.
As Mark pointed out, you have set up a dummy straw man argument and then shown that it's wrong. Your point is valid but really is irrelevant to this thread.
 
  • #105
phinds said:
As Mark pointed out, you have set up a dummy straw man argument and then shown that it's wrong. Your point is valid but really is irrelevant to this thread.
Think on a case a machine having 16 register (as IBM), In program; you branch into a subroutine, you will going to save registers before starting subroutine and restore them before return back to caller Tel me how many programmer could count and mark which registers are altered in subroutine and write code to save and restore only those register. (register saving & restoring time cost is depend on # of register involved) But if your H_L compiler has an intelligence to consider this code will save & restore only altered registers process and optimize code accordingly. Please take this simple example as only to express my intention Since we can embed some logic in compiler we can let compiler will generate more optimal code than human can. (especially if you accept all programmer will not be smart as a versed one) in H_L compiler you even preprocess written code and localize some part as optimizable and apply specific process to optimize code generation. You can not train all your staff as versed assembler programmer. But you can use a high quality (optimization intelligence embedded) H_L language compiler to produce faster code.
 
  • #106
TMT said:
Think on a case a machine having 16 register (as IBM), In program; you branch into a subroutine, you will going to save registers before starting subroutine and restore them before return back to caller Tel me how many programmer could count and mark which registers are altered in subroutine and write code to save and restore only those register. (register saving & restoring time cost is depend on # of register involved) But if your H_L compiler has an intelligence to consider this code will save & restore only altered registers process and optimize code accordingly. Please take this simple example as only to express my intention Since we can embed some logic in compiler we can let compiler will generate more optimal code than human can. (especially if you accept all programmer will not be smart as a versed one) in H_L compiler you even preprocess written code and localize some part as optimizable and apply specific process to optimize code generation. You can not train all your staff as versed assembler programmer. But you can use a high quality (optimization intelligence embedded) H_L language compiler to produce faster code.
Yes, of course to this as well. It's not a surprise that a dim-witted assembly programmer would likely produce slower code than code written in a high-level language and using a compiler that produces highly optimized object code. No surprise here.
 
  • #107
TMT said:
Think on a case a machine having 16 register (as IBM) ...
Once again Mark has beat me to it in responding and again, I agree w/ him. You keep making valid points that are off the track of the thrust of this thread. I think we're going to have to just agree to disagree on this one.
 
  • Like
Likes jim mcnamara
  • #108
TMT said:
Most people think assembly is speedy than high level languages. But I'm telling if high level language is configured more intelligently, it may be faster than assembler.
In the case where compilers can produce assembly code, the assembly code would be the same as the high level language. In some cases, assembly programmers will have a compiler produce assembly code to look for "clever" code, typically when working with a processor new to the programmer. As posted by others here, the point of the thread isn't about intelligent compilers versus dumb assembly programmers.

See post #21 for example cases where assembly code is still being used today:

post #21
 
Last edited:
  • #109
Is it possible to know whether your program (written in a high-level language) is slow due to the compiler's reinterpretation of your input (i.e. the assembler output could be improved by human intelligence) or if you screwed up with the algorithm and you have to look for a better one?

For example the code below could be improved in speed I guess by doing the multiplication in the end:
Code:
int sum = 0.0;
for(int i=1; i<=10; i++){
    sum+= 2*i;
}

improved:
Code:
int sum = 0.0;
for(int i=0; i<10; i++){
    sum+=i;
}
sum *= 2;
or even better use the bitwise operations (sum<<1 ??)... at which point any delay would reach the innefficiency of the compiler vs human input?
 
  • #110
With the exception of fairly specialized circumstances, it's unlikely that a compiler will generate code that could be really significantly improved by twiddling the machine code but it's very easy to code an algorithm in a way that is very inefficient. Just as a trivial example, you could use a bubble sort instead of a quick sort.
 
  • Like
Likes ChrisVer
  • #111
It's rarely compiler's fault.
A colleague of mine loves to build long strings one character at a time, e.g.
C:
std::string toBeLong="";
for (int i=0; i<300; i++)
  toBeLong+=getc();
Depending on implementation, this could mean 300 reallocs are performed, plus the memory gets fragmented. I would allocate some memory in advance, but it's a few lines longer, and he argues that shorter code is better for maintenance.

He also uses a HashTable where I would use simple array with a lookup function - again, more coding on my side.

He uses Exceptions a lot, I catch them at first possible place and try not to raise any.

It is choices like this that you face most of the time. You'll use the best algorithm anyway, so not much space for improvement here.
And rewriting a piece of code into another language is pretty rare, kind of a "desperate measure", and often not even possible (JavaScript & co.)

Knowing assembly can help you estimate how fast/slow a piece of code will be, even if you never write assembly code.
 
  • Like
Likes ChrisVer
  • #112
Well moving for example the multiplication of 2 outside the for loop is both an algorithmic process as well as an improvement to the output assembler... I tried this simple example I gave above and the contents of the for loop in the two cases are:
Code:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
   f:   c7 45 f8 01 00 00 00    movl   $0x1,-0x8(%rbp)
  16:   eb 0c                   jmp    24 <main+0x24>
  18:   8b 45 f8                mov    -0x8(%rbp),%eax
  1b:   01 c0                   add    %eax,%eax       <<<<<<<<<<<<<<<<<<<<
  1d:   01 45 fc                add    %eax,-0x4(%rbp)
  20:   83 45 f8 01             addl   $0x1,-0x8(%rbp)
  24:   83 7d f8 0a             cmpl   $0xa,-0x8(%rbp)
  28:   7e ee                   jle    18 <main+0x18>

Improved:

Code:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
   f:   c7 45 f8 01 00 00 00    movl   $0x1,-0x8(%rbp)
  16:   eb 0a                   jmp    22 <main+0x22>
  18:   8b 45 f8                mov    -0x8(%rbp),%eax
  1b:   01 45 fc                add    %eax,-0x4(%rbp)
  1e:   83 45 f8 01             addl   $0x1,-0x8(%rbp)
  22:   83 7d f8 0a             cmpl   $0xa,-0x8(%rbp)
  26:   7e f0                   jle    18 <main+0x18>

I multiarrowed the line that is removed (which is doubling what was in the eax)
and then I may say that the first jump to 22 is unnecessary, which I think is a feature of the for loop - to make sure it should be entered... but I trust it will enter since I manually wrote for i=1 and not i=11 or 40 or ...
Also one interesting thing is that when the multiplication is done within the for loop, the assembler code does the doubling by add ... when it happens outside the for loop it does it with shifting left (and so *=2 and <<=2 in my case are equivalent).
 
Last edited:
  • #113
What compiler flags (and compiler) did you use?
 
  • #114
glappkaeft said:
What compiler flags (and compiler) did you use?
hmm... so I wrote a program in AStester.cxx
then used gcc -c AStester.cxx to produce the .o file (so I think no flags?)
and looked in the contents by objdump -D AStester.o
 
  • #115
ChrisVer said:
Is it possible to know whether your program (written in a high-level language) is slow due to the compiler's reinterpretation of your input (i.e. the assembler output could be improved by human intelligence) or if you screwed up with the algorithm and you have to look for a better one?

For example the code below could be improved in speed I guess by doing the multiplication in the end:
Code:
int sum = 0.0;
for(int i=1; i<=10; i++){
    sum+= 2*i;
}

improved:
Code:
int sum = 0.0;
for(int i=0; i<10; i++){
    sum+=i;
}
sum *= 2;
or even better use the bitwise operations (sum<<1 ??)... at which point any delay would reach the innefficiency of the compiler vs human input?
The second example is quite a bit better, as it takes the multiplication out of the loop. Multiplication is a lot more expensive than addition in terms of processor time, although an optimizing compiler would probably replace 2 * i with a shift.
 
  • #116
Mark44 said:
The second example is quite a bit better, as it takes the multiplication out of the loop. Multiplication is a lot more expensive than addition in terms of processor time, although an optimizing compiler would probably replace 2 * i with a shift.
Actually only the weakest CPUs have slow multiplication. Pretty much any ARM or Pentium and above only take 1 cycle per nonzero bit (or even less), that is, multiplying by 1001001 (binary) only takes 3 cycles.
And, pretty much any compiler does indeed replace multiplication by powers of 2 with shifts.
 
  • #117
SlowThinker said:
Actually only the weakest CPUs have slow multiplication. Pretty much any ARM or Pentium and above only take 1 cycle per nonzero bit (or even less), that is, multiplying by 1001001 (binary) only takes 3 cycles.
And, pretty much any compiler does indeed replace multiplication by powers of 2 with shifts
Well when I tested the above 2 code snippnets and compared times the "slow" one took ~120,000 and the "optimized" one took ~42,000 (tests : 10M iterations)... One extra interesting part was that I also tried the bitwise operation instead of the multiplication, and for up to 10M iterations, the bit-shifting operation was faster, above 10M the two became comparable (couldn't tell the difference).
 
  • #118
ChrisVer said:
Well when I tested the above 2 code snippnets and compared times the "slow" one took ~120,000 and the "optimized" one took ~42,000 (tests : 10M iterations)...
It's interesting that shortening a cycle from 6 to 5 instructions (and taking out the fastest one), the time was cut to 1/3.
This tells me
1) Speed of short loops depends on things like the actual address where it lands,
2) Too much optimization is a waste of time because you can't predict that
You can try -O3 flag or Microsoft or Intel compiler, optimized for speed. They include NOPs at various places to fix the alignment; then the results might be more comparable.
 
  • #119
Think on a case a machine having 16 register (as IBM), In program; you branch into a subroutine, you will going to save registers before starting subroutine and restore them before return back to caller

Reference https://www.physicsforums.com/threa...gramming-languages.912679/page-6#post-5772249

Smart hardware guys can help too.
There's the venerable TMS9900
where program counter defines the start of your stack
and can be any location in memory
so you can context switch with just one save...
 
  • #120
ChrisVer said:
hmm... so I wrote a program in AStester.cxx
then used gcc -c AStester.cxx to produce the .o file (so I think no flags?)
and looked in the contents by objdump -D AStester.o

Then the code is likely entirely unoptimized. An optimizing compiler would probably remove the code entirely if sum is not used elsewhere later (dead code elimination) or replace your code with sum = 110 (constant folding)

Edit: Note that is is considered bad practice to initialize an int with a double value.
 

Similar threads

Replies
6
Views
3K
  • · Replies 397 ·
14
Replies
397
Views
19K
Replies
6
Views
2K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 29 ·
Replies
29
Views
3K
  • · Replies 4 ·
Replies
4
Views
15K
Replies
4
Views
2K
  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 2 ·
Replies
2
Views
2K
Replies
59
Views
8K