22
$\begingroup$

I would like to ask a few questions about Assembly language. My understanding is that it's very close to machine language, making it faster and more efficient.

Since we have different computer architectures that exist, does that mean I have to write different code in Assembly for different architectures? If so, why isn't Assembly, write once - run everywhere type of language? Wouldn't be easier to simply make it universal, so that you write it only once and can run it on virtually any machine with different configurations? (I think that it would be impossible, but I would like to have some concrete, in-depth answers)

Some people might say C is the language I'm looking for. I haven't used C before but I think it's still a high-level language, although probably faster than Java, for example. I might be wrong here.

$\endgroup$
  • 10
    $\begingroup$ What research have you done? We expect you to do research before asking, to help you ask a better question. There's lots written on assembly language. $\endgroup$ – D.W. Sep 7 '15 at 16:56
  • 4
    $\begingroup$ We expect you to do a significant amount of research/self-study before asking, and to tell us in the question what research you have done. In this case, research might include reading relevant Wikipedia articles (e.g., on assembly language and computer architecture) and reading a computer architecture textbook. To make this a better question: do that research, if you haven't already, and then edit the question to explain the research you've done. Often that kind of research helps you formulate a better question; and in any case it helps answerers avoid repeating what you already know. $\endgroup$ – D.W. Sep 7 '15 at 17:02
  • 15
    $\begingroup$ Start with understanding that/why there is no language called Assembly. $\endgroup$ – Raphael Sep 7 '15 at 18:41
  • 2
    $\begingroup$ one "classic" problem with C portability is different primitives (eg integer) sizes on different hardware & there are some others cited. $\endgroup$ – vzn Sep 7 '15 at 22:57
  • 3
    $\begingroup$ This is more of a social problem than a technical one - you need to convince all CPU manufacturers to make their CPUs accept the same machine language. (Actually, x86 was almost going to be this, by chance - then smartphones took off) $\endgroup$ – immibis Sep 8 '15 at 0:38

10 Answers 10

45
$\begingroup$

Assembly language is a way to write instructions for the computer's instruction set, in a way that's slightly more understandable to human programmers.

Different architectures have different instruction sets: the set of allowed instructions is different on each architecture. Therefore, you can't hope to have a write-once-run-everywhere assembly program. For instance, the set of instructions supported by x86 processors looks very different from the set of instructions supported by ARM processors. If you wrote an assembly program for an x86 processor, it'd have lots of instructions that are not supported on the ARM processor, and vice versa.

The core reason to use assembly language is that it allows very low-level control over your program, and to take advantage of all of the instructions of the processor: by customizing the program to take advantage of features that are unique to the particular processor it will run on, sometimes you can speed up the program. The write-once-run-everywhere philosophy is fundamentally at odds with that.

$\endgroup$
  • 1
    $\begingroup$ I think that question is already answered by the 3rd paragraph of my answer. As you said, such a scheme would not be efficient, so it'd be fundamentally at odds with the core reason to use assembly language. $\endgroup$ – D.W. Sep 7 '15 at 17:17
  • 26
    $\begingroup$ @nTuply As soon as you modify your assembly language to cater for different machines, it's become a high-level language with horribly assembly-style syntax. Once you've decided to use a high-level language, you may as well use one with friendlier syntax and let the compiler do the hard work. $\endgroup$ – David Richerby Sep 7 '15 at 18:01
  • 15
    $\begingroup$ It's not a completely stupid idea to have an "assembly language" that is translated for different machines, because that's basically what LLVM's "IR" is. However, for the reasons David gives, you don't normally write LLVM assembly. Also because 99 times out of 100 you'd do a worse job of writing it than clang does of translating your C to LLVM. Assembly languages are potentially more efficient than high-level languages, but in the hands of most actual programmers with a typical amount of time available to optimise, they don't reach their potential anyway. $\endgroup$ – Steve Jessop Sep 7 '15 at 19:10
  • 9
    $\begingroup$ @nTuply, that exists. The process of going from that extra-assembly language to machine instructions is called compilation. $\endgroup$ – Paul Draper Sep 7 '15 at 20:39
  • 3
    $\begingroup$ @PJTraill There is no reason whatsoever to write a compiler in assembler on a modern system, except for the very first bootstrapping step (and most of the time, not even then). Compilers written in a high-level language are vastly more likely to actually be maintainable. Also compare How can a language whose compiler is written in C ever be faster than C?. The purpose of a compiler is to translate from one language (the source language) to another (usually machine language for a specific architecture and OS); this can be written in any language. $\endgroup$ – a CVn Sep 8 '15 at 19:36
13
$\begingroup$

The DEFINITION of assembly language is that it is a language that can be translated directly to machine code. Each operation code in assembly language translates to exactly one operation on the target computer. (Well, it's a little more complicated than that: some assemblers automatically determine an "addressing mode" based on arguments to an op-code. But still, the principle is that one line of assembly translates to one machine-language instruction.)

You could, no doubt, invent a language that would look like assembly language but would be translated to different machine codes on different computers. But by definition, that wouldn't be assembly language. It would be a higher-level language that resembles assembly language.

Your question is a little like asking, "Is it possible to make a boat that doesn't float or have any other way to travel across water, but has wheels and a motor and can travel on land?" The answer would be that by definition, such a vehicle would not be a boat. It sounds more like a car.

$\endgroup$
  • 1
    $\begingroup$ C has often been described as "portable assembly language." $\endgroup$ – Larry Gritz Sep 9 '15 at 20:20
  • 2
    $\begingroup$ @LarryGritz Sure. And when C was invented, it was groundbreaking: It offered much of the power of assembly language with the ease of use a compiled. But by definition, it's still a compiled language $\endgroup$ – Jay Sep 10 '15 at 6:53
8
$\begingroup$

There is no conceptual (I daresay, no computer science) reason against having one assembly language for all computers in the world. In fact, that would make many things much easier. As far as theory is concerned, they are all the same, anyway, up to some funky bijection.

In practice, however, there are different chips for different purposes, with different operations and design principles (e.g. RISC vs CISC) that serve different goals, and the instruction sets that operate them and therewith the assembly languages differ. In the end, the answer is the same as when asking why there are so many different programming languages: different goals, different design decisions.

That said, you can of course introduce levels of abstraction to get to some shared interface. x86, for instance, has been done away with on chip level for quite some time; there's a little piece of hardware that translates x86 instructions to whatever your processor really works with. Languages like C would be another step away from the hardware (if an arguably tiny one), all the way up to languages like Haskell, Java or Ruby. Yes, compiler are one of the main achievements of computer science because they make it possible to separate concerns in this fashion.

$\endgroup$
  • 6
    $\begingroup$ "if an arguably tiny one" -- there's your two kinds of programmer right there. Those who consider C a low-level language because its basic operations look a lot like the kinds of things that appear in CPU instruction sets, and those who consider C a high-level language because it's not the same instruction set as the machine. $\endgroup$ – Steve Jessop Sep 7 '15 at 19:17
  • $\begingroup$ If by assembly language you mean one giving complete control over the machine code generated for a specific type (or family) of hardware, it would be possible to define one language ”for all computers” in our world at a given moment, but it would have to keep changing. It would admittedly (if well designed) shorten the learning curve for coding for a new architecture, but I expect any job you would want to do with it rather than a compiler would only apply to a tiny fraction of architectures. That computers are the same at an abstract level is a red herring, it is about machine code. $\endgroup$ – PJTraill Sep 9 '15 at 10:54
7
$\begingroup$

You mention the phrase "write once run anywhere" without seeming to notice its significance. That is the marketing slogan for Sun Microsystems that commercially invented the concept of a "virtual machine" and "bytecodes" for Java, although possibly the idea may have originated in academia 1st. The idea was later copied by Microsoft for .Net after they were successfully sued by Sun for breach of infringement of Java licensing. Java bytecodes are an implementation of the idea of cross-machine assembly or machine language. They are used for several other languages than Java and can theoretically be used to compile any language. After many years of very advanced optimization, Java comes close in performance to compiled languages showing the goal of high performance platform-agnostic virtual machine technology is achievable in general.

Another new idea in early stages/ circulating related to your requirements is called the recomputation project and is for scientific research although could be used for other purposes. The idea is to make computational experiments replicable via virtual machine technology. This is mainly the idea of simulating different machine architectures on arbitrary hardware.

$\endgroup$
  • 8
    $\begingroup$ Sun did not invent either virtual machines or byte code, they weren't even the first group to make money off them. Look up p-code. $\endgroup$ – jmoreno Sep 8 '15 at 0:09
  • $\begingroup$ @jmoreno: he might also want to look up Smalltalk. $\endgroup$ – Bob Jarvis Sep 8 '15 at 2:47
  • $\begingroup$ the article does not claim sun invented virtual machines/ byte code. there is other history not cited but alluded to. btw another key technology very relevant here: google native client (chrome feature) $\endgroup$ – vzn Sep 10 '15 at 3:54
5
$\begingroup$

High level reasons

When you think about it, a microprocessor does an amazing thing: it lets you take a machine (such as a washing machine or an elevator), and replace a whole chunk of custom-designed mechanisms or circuits with a cheap, mass-produced silicon chip. You save a lot of money on parts, and a lot of time on design.

But hang on, a standard chip, replacing countless custom designs? There can't be a single, perfect microprocessor that is perfect for every application. Some applications need to minimise power usage but don't need to be fast; others need to be fast but don't need to be easy to program, others need to be low cost, etc.

So, we have many different "flavours" of microprocessor, each with its own strengths and weaknesses. It is desirable for them to all use a compatible instruction set, because this allows code reuse and makes it easier to find people with the right skills. However, the instruction set does affect the cost, complexity, speed, ease-of-use, and physical constraints of the processor, and so we have a compromise: there a few "mainstream" instruction sets (and many minor ones), and within each instruction set there are many processors with different characteristics.

Oh, and as technology changes, all these trade-offs change, so instruction sets evolve, new ones emerge, and old ones die. Even if there was a "best" instruction set of today, it might not be in 20 years.

Hardware details

Probably the biggest design decision in an instruction set is the word size, i.e. how large a number the processor can "naturally" manipulate. 8-bit processors deal with numbers from 0-255, whereas 32-bit processors deal with numbers from 0 to 4,294,967,295. Code designed for one needs to be completely rethought for another.

It is not just a matter of translating instructions from one instruction set to another. A completely different approach may be preferable in a different instruction set. For example, on an 8-bit processor a lookup table may be ideal, while on a 32-bit processor an arithmetic operation would be better for the same purpose.

There are other major differences between instruction sets. Most instructions fall into four categories:

  • Computation (Arithmetic and logic)
  • Control Flow
  • Data Transfer
  • Processor configuration

Processors differ in what sort of computations they can perform, as well as how they approach control flow, data transfer, and processor configuration.

For example, some AVR processors can neither multiply nor divide; whereas all x86 processors can. As you may imagine, eliminating the circuitry required for tasks like multiplication and division can make a processor simpler and cheaper; these operations can still be performed using software routines if they are needed.

x86 allows arithmetic instructions to load their operands from memory and/or save their results to memory; ARM is a load-store architecture and thus only has a few dedicated instructions for accessing memory. Meanwhile x86 has dedicated conditional-branch instructions, while ARM allows practically all instructions to be conditionally executed. Also, ARM allows bit-shifts to be performed as part of most arithmetic instructions. These differences lead to different performance characteristics, differences in internal design and cost of the chips, and differences in programming techniques at the assembly language level.

Conclusion

The reason it is impossible to have a universal assembly language is that, to properly convert assembly code from one instruction set to another, one must design the code all over again—something computers cannot yet do.

$\endgroup$
  • $\begingroup$ Excellent answer! People do not understand well enough that computing things that need to be programmed are everywhere among us. It's not just the applications we see running on our screens. How many billions of chips are manufactured each year? $\endgroup$ – phs Sep 11 '15 at 9:17
4
$\begingroup$

Adding to marvelous answer by D.W.: if you would like to have one assembler it would need to maintain all architectures, perfect translator among them and fully understand what are you doing.
Some heavily optimized codes per one architecture would need to be deoptimized, understood at more abstract level and optimized per another.
But if this was possible we would have perfect C compiler, and writting in pure assembly would not be beneficial at all.
The main point of using assembler is performance, which cannot be squeezed from recent compilers.
Writing such program would be even harder than existing compilers and maintaining all new architectures that are being created would make it even harder.
And for "one only" program, it would also mean full backwards compatibility.

$\endgroup$
  • $\begingroup$ For the vast majority of cases, gcc performs better optimization than a programmer can. The main point of using assembler is to do stuff you can't do in C like accessing registers. If you look at the Linux source tree that's pretty much what they use assembly for. $\endgroup$ – slebetman Sep 8 '15 at 5:58
  • $\begingroup$ @slebetman - gcc allows you to put a variable into a register without resorting to assembly. $\endgroup$ – Jirka Hanika Sep 8 '15 at 6:42
  • $\begingroup$ @JirkaHanika: are you talking about CPU registers or special purpose hardware registers addressed with special instructions? I suspect slebetman means the latter. $\endgroup$ – PJTraill Sep 8 '15 at 8:38
  • $\begingroup$ "All codes" - "GCC does better" = "you use assembler". Yes you can access registers without assembler insertions. $\endgroup$ – Evil Sep 8 '15 at 8:47
  • $\begingroup$ @PJTraill - Slebetman's comment is generally excellent and should perhaps be incorporated into the answer. But, both of his examples (register access and Linux source tree) are likely to feed common misconceptions rather than that they would be excellent examples of what one cannot do in C with gcc extensions; those should be replaced or omitted. (If there's a HW instruction to do something today, you'll have the corresponding gcc extension a year from now. Not always, but very often. Examples age.) $\endgroup$ – Jirka Hanika Sep 8 '15 at 9:15
3
$\begingroup$

Microsoft invented MSIL to be an intermediate assembly language. Programs would compile from C# or VB.Net to MSIL. At run time, the MSIL was compiled to machine code for the machine that was running it using a JIT compiler. The file containing the MSIL was an .EXE file with a few instructions at the beginning in X86 to start the program. On an ARM processor, you'd type the word mono in front of the program name to run it.

$\endgroup$
  • $\begingroup$ What's the difference between "intermediate assembly language" and "virtual machine"? $\endgroup$ – Bob Jarvis Sep 8 '15 at 2:49
  • $\begingroup$ @BobJarvis: One is code while the other is an interpreter. You should have asked what's the difference between intermediate assembly and bytecode $\endgroup$ – slebetman Sep 8 '15 at 5:55
  • $\begingroup$ This does not seem to answer the question. As long as each machine compiles/assembles MSIL differently, there is nothing universal about it, and the purpose of such compilation is porting of generic functionality, and not exploitation of a particular instruction set, which, as D.W. points out, is the (or a) reason for using assembler. $\endgroup$ – PJTraill Sep 8 '15 at 8:43
3
$\begingroup$

As noted, LLVM is the closest thing to this so far. A big barrier to a really universal language is going to be fundamental differences related to implicit tradeoffs: concurrency, memory use, throughput, latency, and power consumption. If you write in an explicitly SIMD style, you could be using too much memory. If you write in an explicitly SISD style, you would get suboptimal parallelization. If you optimize for throughput, you hurt latency. If you maximize single-threaded throughput (ie: clock speed), you hurt battery life.

At the very least, the code would need to be annotated with the trade-offs. What may be most important is for the language to have good algebraic/type properties that give the compiler a lot of wiggle room to optimize and detect logical inconsistency.

Then there is the question of undefined behavior. Much of the speed of C and assembly languages come from undefined behavior. If you admit undefined behavior that actually does happen, then you end up handling them as special cases (ie: architecture and context specific hacks).

$\endgroup$
0
$\begingroup$

Perhaps what you are looking for is a Universal Turning Machine notation where everyone agrees on the symbols for the commands. (https://en.wikipedia.org/wiki/Universal_Turing_machine)

An 'assembler' that translates a Turning Acceptable language to the underlying vendor specific machine code and be build for any of those things we call computers.

In The Art of Computer Programming the there is a example of what this might look like.

But consider the question "why isn't their a commercially available universal language that can be used with all computers" I'd suggest the most dominiant influances are (1) convenience, not all assembly languages are the most convienent to use; (2) economics, providing, incompatibility between machines of different brands and vendors is a business strategy as well as the result of limited resources (time/money) to design machines.

$\endgroup$
  • $\begingroup$ The question is asking about an assembly language that can be used to program any computer, not an assembly language that's universal in the sense of "universal Turing machine". $\endgroup$ – David Richerby Sep 8 '15 at 19:53
  • 1
    $\begingroup$ Church-Turing tells us the UTC can do what any programmable computer can do. Aside from finite physical storage issues. An assembly language for a UTC is quite feasible. But as i said cultural and economic practicality may limit actual implementation and adoption in the marketplace. $\endgroup$ – Chris Sep 8 '15 at 20:06
  • $\begingroup$ You're missing the biggest problem, which is performance! Why use a language 1000s of times slower just for some lofty goal of being hardware-agnostic? The Turing Machine is a terrible model for practical computing. $\endgroup$ – Artelius Sep 9 '15 at 12:02
  • 1
    $\begingroup$ Would the commenters care to offer any computer science to back their claims? This is after all the computer science forum. $\endgroup$ – Chris Sep 9 '15 at 14:14
  • 1
    $\begingroup$ I'm not a CS expert. But what I believe is that the von Neumann architecture is a brilliant piece of engineering that strikes a balance between programmability and performance, whilst the Turing machine's purpose is to show that even the most basic machine can compute anything that a more complex machine could. Sure, you can keep adding more and more features to a Turing machine (more tapes, arithmetic), but then you get the same problem you had in the first place, namely people not agreeing on an instruction set. Plus, the lack of random-access creates big overheads in many algorithms. $\endgroup$ – Artelius Sep 12 '15 at 12:19
0
$\begingroup$

assumption: compiling and optimising a high-level language L1 to a lower-level language L0 is easier than compiling and optimising a high-level language L2 (higher than L1) to L0; easier in the sense that you supposedly can generate more optimised code when compiling L1 to L0 than L2 to L0.

I think the assumption is probably correct, that is why probably most compilers use a low-level intermediate language (IR/LLVM).

if this is true than use any low-level language L0 and write compilers to translate L0 to other low-level languages. For example, use MIPS instruction set, and compile it to x86, arm, power, ...

-Taoufik

$\endgroup$
  • $\begingroup$ So you do not know whether your answer is true? And cannot support it? $\endgroup$ – Evil Nov 19 '16 at 11:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.