r/computerscience • u/ShadowGuyinRealLife • 11d ago
Discussion Is C an "Assembly-like" Language?
I know C is programing language. It is not architecture specific. One writes the source code and a compiler turns it into an executable depending on what settings you tell it. So the same source code would output different executables depending on what you want to run it on and what optimization options are on. Assembly languages on the other hand are architecture specific. Is C "Assembly-like"? To be honest I'm not sure what would be Assembly-like. I guess if a program written in multiple languages that have the same behavior, if the C version (using something like GNU C Compiler) looked closer to its assembly than, say its Java version (GraalVM), then that counts.
48
u/MistakeIndividual690 11d ago
It is not assembly-like. However, because of its portability and excellent compilers that can compile it down to code that is at least as good (on average) as hand-written assembly, it is sometimes used as a target language for other, higher level language compilers, such as Haskell or Scheme.
This is the reason it is sometimes called a portable assembly language—not because it bears any actual resemblance to assembly language
5
48
u/DTux5249 11d ago edited 11d ago
As someone who has done assembly and C: no. Just no. Not in anyway. C is nothing like assembly in any way shape or form beyond like, the concept of a programming language.
Like, try writing assembly. It's a different beast all together.
4
u/Physical_Dare8553 10d ago
I don't think anyone ever actually means this. Like the idea of a portable assembly in itself is contradictory so clearly they're talking about something else
18
u/mredding 11d ago
Is C an "Assembly-like" Language?
Actually: No. It's a high level language that targets an abstract machine.
The definition of an assembly language is a 1:1 correspondence between a mnemonic and a platform specific op-code. x86 uses mov, but there's over 100 move instructions to choose from - depending on your parameters. You CAN get to a specific op-code by using a more specific mnemonic if you want or need to.
High level assemblers offer macros. I don't write enough assembly to discuss whether this offers any unique features over an external macro engine like m4, jinja, etc. It's not like even assemblies for the same platform are portable - NASM, WASM, FASM, and GAS are not inter-compatible, their syntaxes vary.
There are no platform independent assembly languages. The next best thing you can get in this capacity is an Intermediate Representation language of a virtual instruction set. See JVM, CLR, CIR, etc.
C offers absolutely nothing in this regard.
I would say assemblers are inherently low level since they target instruction sets; any language that abstracts away the machine entirely with a virtual one - WITHOUT an instruction set, is high level.
Pragmatically: projects transpile to C all the damn time, so people certainly have used it like one. See Go, Cython. The principle benefit is there's a C compiler for practically every piece of hardware ever made.
I would argue it causes more harm and confusion to think of it or call it a high level assembly (which it's not) or assembly-like.
11
u/Snatchematician 11d ago
x86 assembly also targets an abstract machine.
5
u/max123246 11d ago
Yup, the micro architecture is what actually runs on hardware at this point because CISC is insane to actually choose as the hardware ISA
1
1
u/Dusty_Coder 11d ago
one of the things a macro assembler can do is produce the current byte offset within the module that is being assembled as it is being assembled, perform mathy-stuff with it, and then emit it
preprocessors dont give you that
1
u/mredding 11d ago
That helps. I'm so drenched in C I sometimes forget that macros don't always mean preprocessing.
61
u/high_throughput 11d ago
Just call it "low level" like a normal person.
61
u/zenidam 11d ago
Classically, C is a prototypical example of a high level language.
28
u/-jp- 11d ago
Technically right but language design has evolved to the point where HLL means something very different than it did fifty years ago. It’s going to call something like Python to most people’s minds.
12
u/CrackerJackKittyCat 11d ago edited 11d ago
We're going to need levels of HLLs like we gots 'long long' integers nowadays.
But hopefully with better nomenclature.
14
10
1
6
u/not-just-yeti 11d ago edited 7d ago
I'd argue that "low-level" means "to understand the full meaning of the program, you must understand the hardware it runs on".
Clearly for assembly this is required, since register-names are part of the language (and whether you can do things like loading "half" a register, etc).
For C, the hardware-dependent issues include "when does integer overflow occur, on the machine you're running on". (And
registeris an official keyword in the language, though it has no meaning beyond being a hint about how to use the hardware.)Other parts of C that "make sense" only when you really know the notion of a RAM machine model, is the mental model of pointers and 'address-of' and how arrays are the address of the first element, and how one calculates indices of multi-dimensional arrays. Though those parts are all standard across the standard machine-architecture in use today [excluding GPUs]. Hence "portable assembly language".
Compare with Java: numeric behavior is fully defined, and nowhere does the language-spec talk about memory-addresses or pointers (but they use the language "references", which of course works the same way).
Compare with Lisp that avoids side-effects — e.g. the lambda calculus. There are only expressions and simplification-rules, plus substitutions and associating names with values. No "memory cell" is part of the mental model.
(Similarly, I find it likely that R and SQL don't talk about memory-locations in the language-spec.)
4
u/Pale_Height_1251 11d ago
Not much has changed in terms of high level language design since C. Bear in mind Smalltalk is the same age as C and Lisp is older than C.
5
u/Snatchematician 11d ago
No, high level does not mean anything different from what it meant fifty years ago.
3
2
u/Temporary_Pie2733 11d ago
C is significantly closer to assembly than other high-level languages. It was jokingly referred to as a medium-level language when I learned it in college 30+ years ago.
3
u/throwawaygaydude69 11d ago
It's classified as a middle level language because it's good for writing both system and application level programs. More so, you can do low-level tasks and it is also portable.
1
u/ShadowGuyinRealLife 8d ago
I guess something like this makes me confused enough to ask a question like the original post.
On one hand it's clearly not assembly. You don't worry about what registers you have and you can declare local variables in a function without worrying about how to handle the stack. The compiler handles functions.
On the other hand, other langauges seem more "abstract."
0
u/lkangaroo 11d ago edited 11d ago
I’d call it intermediate-level, given e.g. it doesn’t have a standard “wait for any of" idiom.
6
u/kombiwombi 10d ago
C is a high level language.
However it is very easy to see how C compiles down to PDP-11 assembler. Which was one of its strengths as a systems programming language. You can write with knowledge of what the assembler looks like, without the fiddliness of assembler stack management, loops, etc.
The same research group wrote many other languages not for systems programming. Notably Awk, which has real strings, richer inbuilt data structures and implicit loops.
1
u/ShadowGuyinRealLife 8d ago
However it is very easy to see how C compiles down to PDP-11 assembler. Which was one of its strengths as a systems programming language.
Huh that's an interesting history. I saw a video guy showing some C and its corresponding x86 assembly. Some of the simple stuff like adding constants or a loop which counted down before exiting looked like I could almost see a relation between them. Then he moved to some other stuff like insertion sort of an array and the x86 looked very different. The next 30 examples were... quite different. So C was never meant to resemble x86, but it was meant to resemble PDP-11, without stuff like stack management.
I guess when he was doing his "loop that runs 7 times and then exits" only looked close by coincidence.
Thanks for sharing me the history. Also while I am not a CS major, I am glad that when I watch a video about bug of (insert program here), a C or C++ source code means the compiler handles the stack and anyone following the code doesn't need to worry about it.
3
u/bj_civ 8d ago
It's not limited to PDP-11 assembler. And I guess the insertion sort wasn't really different. The point is not that the C insertion sort and the assembly insertion sort look the same, but that it's easy to look at the single C statements and see what what each one translates to in assembly. At least without optimisations turned on, most C statements have simple straight forward and short assembly translations on most processor architectures.
1
u/superpet9000 8d ago
The straightforward translation is usually very obvious regardless of ISA. The examples that did not translate clearly were probably due to optimizations from the compiler. Modern architectures require a fair amount of work by the compiler to make sure the instructions are arranged efficiently.
1
u/ShadowGuyinRealLife 8d ago
Funny thing he used an example of 2 different C codes that would generate code that corresponds to the same assembly and said that the two source codes were logically the same but one used constants and the other declared magic numbers. To paraphrase "you can type Deck Size +1 instead of 53 since the compiler knows Deck Size is a constant and therefore the compiled program won't actually do this addition at runtime"
1
u/superpet9000 8d ago
Yes, if the compiler knows that the value is "constant" at compile-time it will use an immediate instruction (encode the data in the instruction itself instead of allocating/initializing a stack variable).
9
u/Temporary_Pie2733 11d ago
No. It’s has significant abstractions like loops and conditional statements that have to be implemented using jumps (of both the conditional and unconditional varieties) in assembly. It also has built-in function-call semantics that, again, have to be implemented explicitly in assembly language. It is distinguished from even higher-level languages in that most of its constructs map fairly closely to assembly code without resorting to an extensive pre-compiled runtime that needs to be linked to the compiled code to run. C used to be called a medium-level language for its position between assembly and “true” high-level languages.
2
u/Snatchematician 11d ago
MASM is assembly and has conditionals.
Actual x86 has a loop instruction.
3
u/Temporary_Pie2733 11d ago edited 10d ago
The loop instruction is just a conditional branch with an implicit decrement of a specific register.
Edit: aren't things like `.IF` in MASM closer to C preprocessor directives like `#if`, rather than actual runtime instructions?
1
u/ShadowGuyinRealLife 8d ago
Conditional GOTO just become various versions of conditions JMP instructions
2
u/bothunter 11d ago
x86 has a lot of weird shit in it. Most instruction sets don't have 50+ years of baggage driven by poor marketing decisions and an unwavering commitment to backwards compatibility.
2
u/Snatchematician 11d ago
Doesn’t make it not an assembly language
1
u/bothunter 11d ago
True. But loops are typically not part of an assembly language. x86 is kind of the exception here.
2
u/AmusingVegetable 11d ago
Most people don’t realize that one of the reasons for some of the x86 weirdness was to allow the automatic translation of 8080 assembler.
2
u/bothunter 10d ago
Yup. At this point it should no longer be considered "weirdness" but insanity. While it's cool that you can run 8080 assembly on a modern Core i9 CPU, I doubt there are very many people actually doing that.
1
u/AmusingVegetable 10d ago
The x86 was trying to be a successor to the 8080, mostly because they were eyeing the CP/M market, then IBM picked it for the PC instead of the 68000 (I’m still salty about that one), then Windows came out, by the time PC servers came out they had to be compatible with Windows… by the time x86_64 came along, it was already impossible for it to be a 32 bit CISC and a 64 bit RISC.
Now we have a 64 bit CISC on top of a microachitectue built to run a 32 bit CISC that nobody uses anymore.
1
u/ShadowGuyinRealLife 8d ago
Any instructions made after 1989 you have in mind Intel thought "I wish we made that a NOP instead of this dumb thing?"
3
u/hesusruiz 11d ago
I can not find any formal definition of "assembly-like" language, and if I try to make one I find always grey areas where the boundaries are now strictly defined. So I would refer to this sentence from Wikipedia:
"In the early decades of electronic computing, programs were usually written in machine code or assembly language, which closely reflected the instruction set of a particular machine. High-level programming languages developed as a way to express algorithms in forms closer to mathematics, business rules, or human-readable procedure, while a compiler or interpreter translated the program into machine-executable instructions."
I would also consider "portability" as an important property to distinguish "assembly-like" from the rest. In C you can write programs which are portable across different processor architectures with different machine instructions like x86, ARM, Telum, Risk-V, etc. This is virtually impossible if you use Assembler (which maps directly to the processor instruction set).
So I would say that C is NOT an "assembly-like" language. Having said that, C can be used to define very low-level instructions, closer to the machine than other "higher level" languages.
This is why C has been very popular for writing operating systems. By the way, Rust is entering the space, and I don't think this makes Rust "assembly-like".
1
u/ShadowGuyinRealLife 8d ago
formal definition of "assembly-like" language
To be honest, after rereading my own post I'm not sure what I would have meant when I wrote it. I guess I thought in my head that natural languages are in a tree with all the Romance languages being "Latin-like" as opposed to something like German, English, or Danish. But assembly language definition on Wikipedia seems cut and dry that this would be a binary definition and no room for anything like that.
3
u/JGhostThing 9d ago
Some people have called the C language a universal assembly language. This is because there are features in C that are easy to compile to machine code.
It isn't anything like assembly language. It is just another language. It was one of the earlier programming languages. I learned it in the 70's from both my college and from magazines (I loved Dr. Dobbs). C is decidedly not assembly language. It doesn't look like assembly language.
1
u/ShadowGuyinRealLife 8d ago
Some people have called the C language a universal assembly language. This is because there are features in C that are easy to compile to machine code.
I have heard of that, but it's a bit of an oxymoron since an assembly language has things like "managing the stack" and "being specific to a platform" so I wondered where the term came from.
C is decidedly not assembly language.
Yeah I know that.
It doesn't look like assembly language.
Oh. Not knowing much assembly myself, I thought the "universal assembly language" term came from "looking like assembly" in key cases. I guess not.
1
u/Alex_1A 7d ago
If you want to compare C (or other languages) to Assembly (of different types), see https://www.godbolt.org.
3
u/DanKegel 11d ago
C is like assembler in that you have to think about memory pretty hard, just like in assembly. Both use pointers heavily, and allow pointer arithmetic. The classic string copy loop in C models assembly rather closely.
Other languages with pointers, like Pascal or go, forbid pointers arithmetic or at least make it hard.
0
u/max123246 11d ago
Pointer arithmetic isn't really a pre-requisite for thinking about memory. Maybe this is pendantic but maybe you mean thinking about memory bugs such as buffer overflows?
Ideally, you always think about memory, because that's most of programming, is thinking about data and how it's structured and how to format it to be performant on the machine you run on for the operations you care about
1
u/DanKegel 11d ago
Well ... people who program in languages like Python and JavaScript hardly need to think about memory in detail at all; everything is taken care of for them. All they have to think about is their data.
Not so in C and assembler!
1
u/max123246 11d ago
Except it's very popular in python to think about using numpy to optimize your data layouts to be more compact compared to python objects
1
u/DanKegel 11d ago
Yup, that's thinking about data and how it's packed together in memory, which is fine. It's also not something beginners are faced with, and it's a performance optimization.
Thinking about memory and pointers in the wider sense is harder, and is replete with footguns that you simply don't have to face in languages like python.
2
u/max123246 11d ago
To be honest, python has one of the most common issues which is pointer aliasing changing data underneath you. It gives you very little tools to manage it and because it doesn't make references explicit, it's a common footgun for beginners copying everything blindly because they don't understand references
Beats segfaults and clobbering data but still not great
2
2
u/feinorgh 11d ago
Assembly language consist of explicit instructions to the processor (put this value into register X, put that value into register Y, execute the FOO instruction and put the result into register Z.
C language is on one or two levels above assembly language, in the sense that a C compiler turns the C code into assembly instructions (that you can inspect), or in some cases into an intermediate representation that can be further processed into assembly language, and then the assembler instructions are turned into machine-specific binary code.
Example (C):
int add(int a, int b) {
return a + b;
}
Example (x86_64 assembly):
add:
mov eax, edi ; Move first parameter (a) into register eax
add eax, esi ; Add second parameter (b) to eax
ret ; Return from function (result stored in eax)
2
u/ConcreteExist 10d ago
If by "Assembly-like", you mean that it in any way resembles writing Assembly code, then no, not at all.
2
u/Dry_Couple8852 10d ago
C is a low level language but to compare with Assembly, it is on a higher level language.
2
u/bj_civ 8d ago
I've never heard anyone calling C an „assembly like“ language. What I've heard, and said myself, that C is somewhat like a portable macro assembler.
C statements are pretty straight forward translatable into assembly. Some statements are a single assembly instruction, most are just a short sequence, only a few are more complex for most target architectures.
Then there are assembly instructions that can't be expressed with C code, like a special return instruction from interrupt service routines. For those there are usually special extensions like an interrupt or isr keyword to declare a function as interrupt handler. And/or intrinsic functions to insert specific instructions into the code.
3
u/AdreKiseque 11d ago
C is very low-level to the point that the structure of C source often maps relatively closely to that of the compiled assembly. But it is still a whole level of abstraction removed.
1
u/Dusty_Coder 11d ago
Please explain, specifically, what is low level about C.
Remember, even BASIC had peek and poke. Pointers aint it.
So what, specifically, is low level about C?
1
1
u/bj_civ 8d ago
Does BASIC have PEEK and POKE? Sure some dialects have them, some don't. Same for IN and OUT in dialects for Z80, 8080, or x86. And some dialects have a command to call machine code routines. The keywords vary.
Turbo Pascal has MEM and MEMW arrays to access any byte/word in conventional memory. Or ABSOLUTE placement of variables at memory addresses. Doesn't mean the Pascal language has this.
2
u/FluffusMaximus 11d ago
C was my second language. x86 assembly was my third. No, C is not “assembly-like.” I seriously question anyone who tells you that.
2
u/Illustrious-Tooth702 11d ago
Not really. C is a low level language but it's more readable than assembly.
And assembly is a really low programming language. It's still readable if you know the isa of the chip you want to program and how the register banks in it are structured.
The compiler makes a machine readable binary code out of the assembly code and then it get upload to the microcontroller chip's prom.
With C it does the same thing but with and added extra step. C code is converted to assembly then it's converted to machine code.
In the olde times where ram and rom space was limited assembly was preferred due to it's memory utilization capabilities. But now we don't have to worry about free memory space that much so C is the preferred language due to convenience.
2
u/landonr99 11d ago
I will say that once you get into really low level bare metal embedded systems, kernels, or bootloaders, C really isn't all that portable. Every architecture still requires specific register memory addresses, compiler flags, memory location declarations, integer widths, and not to mention just the very different peripherals, timers, interrupts, clocks, etc that each architecture implements. At the lowest level, C is just a more readable representation of assembly that becomes architecture specific. Higher level software relies on firmware, drivers, kernels, system calls, and hardware abstraction layers that tie the software to the specific hardware. In that aspect, the lowest level C is similar to assembly in that it becomes hardware specific at a certain layer. However C is designed so that far more layers can be built on top of that so it's only a specific section of the program or software that is hardware specific
2
u/JollyJuniper1993 11d ago edited 11d ago
No, not in the slightest. C is arguable much closer to even something like Python or JS than it is to assembly. C is great for cases where you need to work with memory and generally with precise operations, but that doesn’t make it assembly-like.
Assembly languages gives direct instructions to the CPU. C does not do that, it’s still high level. Maybe you can, I don’t know, but the point is that generally that’s not how computing is done in C.
4
u/Pale_Height_1251 11d ago
I wouldn't even qualify this with "arguably", C is absolutely closer to other high level languages than assembly.
1
u/nitkonigdje 11d ago edited 11d ago
No.
C abstracts call sites. Code layout is pretty big issue in assembly, and C fully abstracts that. Although it fucks it up badly (a code layout) by having headers and consequently compile units and objects files etc.
However C is very good proxy for some forms of assembly as with experience you can get a reasonable intuition for the generated assembly code. For example, it is possible to think about a code of particular function in "assembly like" constructs. Being able to inline assembly actually is natural progression of that.
1
u/RibozymeR 11d ago
It kinda used to be on the PDP-11, maybe. On today's systems, it's basically the same level of abstraction as any procedural language.
1
1
u/GenericFoodService 10d ago
Not really, no. In assembly languages, you explicitly control the branching of a program, you explicitly control the stack, you specifically tell the computer what instructions it executes to perform any given task. You are nowhere near that verbose or specific in C. You work in abstractions, functions and types and whatnot. C has far more in common with Python or Rust than it does with Assembly languages.
1
u/TarsTarkas_Thark 9d ago
C is not Assembly-Like. It is a high level language that was designed to be very efficient, have modern control structures, and data structures. When you write in C you have a pretty good idea what the generated Assembly code will look like.
I have also used a high level language that was assembly like. SPL on the HP-3000 minicomputer. The HP-3000 was a stack-architecture machine, similar to an HP RPN calculator. Most instructions operated off operands that had been pushed onto the stack, rather than specifically purposed registers. Anyway, SPL had some statements that compiled out to a single instruction, or a single instruction after the operands had been pushed onto the stack. Examples were the move and scan instructions, for moving and scanning bytes. Both of those statements had a stack decrement that could be specified to clean 1 - 3 words off of TOS after execution.
It was entirely possible for a good SPL programer to write out on a notepad the exact assembly code that would be generated by a program that he had written.
1
u/donewithdoing 9d ago edited 9d ago
No. The whole point of a language like C is to not be Assembly-like, because writing in Assembly is tedious.
Actually, I shouldn’t say “the whole point,” because another big feature of C is for the code to be portable to other architectures, unlike Assembly. As long as a system has a C compiler written for it, you can feed in the same code and it should produce a result that runs on that system (unless you use platform-specific code in the program).
1
u/Ill-Accountant-9941 8d ago
No. The entire point of C is to be categorically one abstraction away from assembly.
1
u/Stock_Sugar3707 7d ago
If you take pointers, malloc, free, realloc, etc. away from C, you get the most generic high-level syntax that C#, Java, JavaScript, etc. share. C is nothing like Assembly. Try writing a hello world program in 6502 Assembly for an NES emulator, and you'll change your mind quickly about C being "Assembly-like". I wanted to pull my hair out, and I was just following a tutorial.
1
u/FrancineTaffyQueen 7d ago
C was the first widely accepted object oriented programming language, which in of itself is important. And the need to be able to express more complex syntax in a language like C had more to do with the limitations of assembler code. Which is pointed out in this thread.
There was eventually a need to be able to express more complex operations than assembler was able to easily accommodate.
the main reason for that is because assembler code is microprocessor specific.
And from a functional standpoint assembler is not sufficient or appropriate to express such things as data objects. C allows for the expression of direct memory allocation, for example. Which was very important in terms of efficiency back in the day.
Most of its core functions are complex syntactical expressions of assembler. So you needed to understand ASM at a fundamental level in order to make the most out of programming in C.
Is it " like Java" ? The answer to that is no, and also the question itself is not useful to ask.
Much in the same way attempting to delineate C and ASM is fundamentally not a useful question.
I read in another comment that, it's a simply stack management but then again everything is stack management when it comes to programming.
The stack is the most fundamental data object in the field. Everything is a derivational of a stack. Because a stack itself is a representation of a register. And the register is simply a conceptual portrayal of address space.
Everything is a stack. Objects are stacks, arrays are stacks, variable types are stacks, etc. They are stacks of data that have beginning and end addresses.
At some point you need to be able to expand your vocabulary to be able to write more complex essays for example. That's not to say that sticking to the most basic of grammar, syntax, kind of vocabulary insufficient express any idea.
That analogy is the same when applied to ASM versus C for example
1
u/More-Explanation2788 11d ago edited 11d ago
C is assembly-like in the sense that it has functions and operators that are designed to work the way a computer works at a low level. All languages do, but when C is presented with a choice to function like a computer, or function in a way humans find easily comprehended, it is far more likely to lean towards the computer than most languages. So examples:
All computers have registers that can be incremented with a single assembly command - so C has variable++ and variable—. Many languages do not.
All computers function with registers that hold the address of data and code. So C has pointers to variables and to functions. Function pointers, I remember using a function pointer two dimensional array once to get a 500% increase in performance, but most languages simply do not have them at all because if you are not intimately familiar with the code, function pointers will make it incomprehensible.
C is not close to assembly in the sense that every line of code will correspond to a line of assembly or that the program will be as convoluted as an assembly program. C is a full powered functional programming language very much unlike assembly with respect to syntax.
Having programmed in Assembly, C, C++, Perl, VB and Java, of those, when I programmed in C, I felt like I knew what the assembly would look like. In the other languages, I would not have a clue. (Incidentally, I hate VB from the bottom of my soul).
That same quality of C is why you can write such horrifically bad C. The other languages protect you from yourself a lot more.
1
u/Responsible_Sea78 11d ago
While C is far from assembly like, there is a fairly close correspondence between the source code statements and the emitted machine code. Some C compilers have actually emitted assembler source code that is then assembled in a separate stage. That allows for some fine tuning at the assembler level (which is rarely worth the time and costs.) Higher level languages may not emit anything you can really read and understand. You have to trust the compiler, a LOT. That's an interesting and difficult security problem, but one with few real world examples of actual hacks.
1
u/Several_Version4298 11d ago
C is not assembly language but it can handle simple inline assembly code.
1
1
u/sceadwian 11d ago
No, plenty of assemblers came before that were not C friendly.
C is a pretty clear abstraction from assembly I don't understand why someone would try to cross the terms like that.
1
u/rupertavery64 11d ago
It's sometimes called a "bare-metal" language, because it has less abstractions.
1
u/ee_control_z 11d ago edited 11d ago
With C you can perform bit wise register manipulation where you're changing bit values by way of boolean algebra operations. However, assembly language implies that you're explicitly programming with a device's instruction set. Instructions like MOV, ADD, SUB, etc.
1
1
u/zhivago 11d ago
Every language is assembly-like for some value of like.
Personally, I don't think that C is particular assembly-like.
There is no access to registers or op-codes for a start.
Flow is structured -- longjmp doesn't really give you a generalized jmp.
The only real aspect might be that C is kind of primitive.
0
0
u/QueefInMyKisser 11d ago
I would say that Java is closer to JVM bytecode than C is to assembly
1
0
u/drgrd 11d ago
The key idea to keep in mind is abstraction. Assembly is not abstract. Each assembly instruction is a 1-to-1 mapping of a machine instruction. Assemblers do some simple math to help humans fill in the literals needed to specify addresses and jump targets and such, but everything is written relating to the movement of data on the machine itself. Which register goes where, which operations to invoke, which hardware to enable. Higher-level languages like C are abstract. You don’t specify anything about the hardware, you specify abstract ideas that the compiler converts into sequences of machine instructions and data allocations. You define a variable, and the compiler decides what memory address that variable will live in, when and how to bring it into a register, etc. You establish a conditional comparison, and the compiler decides how to move data around to accomplish that comparison and decide what to do next. C is only “low level” in comparison to languages with more abstract abstractions.
0
u/ern0plus4 11d ago
C-like means how the program is structured: blocks, functions, global and local variables, flow control instructions (if-then-else, while-break-continue etc.), linear, continous execution.
BASIC is not C-like, because it has no blocks.
Assembly has no C-like control flow.
2
u/AmusingVegetable 11d ago
What blocks? {}?
1
u/ern0plus4 10d ago
Yes, but syntax is not important, see Python.
1
u/AmusingVegetable 10d ago
Not seeing what you can do with {} in C that you can’t do in BASIC.
1
u/bj_civ 8d ago
It's a local namespace in C.
1
u/AmusingVegetable 8d ago
Ok,that’s useful if you need a variable inside a macro, other than that, the block doesn’t introduce a semantic difference between C and BASIC.
1
u/GenericFoodService 10d ago
BASIC has blocks, it just doesn't have block-scoped namespacing.
0
u/ern0plus4 10d ago
Not VB, original BASIC, e.g. Commodore 64.
1
u/GenericFoodService 10d ago edited 10d ago
ANSI BASIC has blocks, C64_Commands) and C128 have blocks. Dartmouth BASIC has blocks. BASIC dialects generally lack scope-level lexical namespacing, but that doesn't mean they lack blocks entirely.
2
u/ern0plus4 9d ago
Could you tell me an example?
For/next is not a block, you can miss any of them, and the program is still syntactically correct.
Afaik only ABC80 BASIC checks for/next pair before execution (right after "run" command).
1
u/GenericFoodService 9d ago
Validation is implementation specific. Many implementations allow syntactically incorrect code to be run until the syntax error itself occurs (which sometimes is many lines later and may never actually be reached). If I remember right Dartmouth is one such example.
I guess whether or not FOR/NEXT counts as a "block" depends on your specific understanding of what a block is. Some people use "block" specifically to refer to the feature of scope-level lexical namespacing, which is why I was explicit. My understanding of what a block is comes from compiler and language design, where a "block" refers to a type of related continuous statements.
Comparing C and Assembly and adding BASIC to the conversation, C is still far more like BASIC than Assembly because how they handle control flow, and because we are telling the machine what we want it to do as opposed to what instructions to execute. BASIC uses blocking control flow, even if it's clunky and "rudimentary"#Examples).
0
u/No-Onion8029 11d ago
Doesn't exactly answer your question, but could add context. Back in the 90s, on speed-sensitive applications, you might start with c code like:
``` int sum(int *a, int n) { int total = 0;
for (int i = 0; i < n; i++) total += a[i];
return total; } ```
Then compile it assembly:
gcc -O2 -S sum.c -o sum-opt.s
And try to hand-optimize any garbage in the assembly:
``` xorl %eax, %eax # total = 0 xorl %edx, %edx # i = 0
.Lloop: addl (%edi,%edx,4), %eax incl %edx cmpl %esi, %edx jl .Lloop ```
-1
0
u/huuaaang 11d ago edited 11d ago
C is considered a "high level" language. While it might be easy-ish to see what assembly it would generate in many cases, it's not assembly-like. You compile C to assembly and that then gets assembled into machine code. Also, the C compiler can make optimizations that actually make the generated assembly significantly different than what the C literally said. For example, a small loop might be unrolled when the assembly is generated. Or a short function might be inlined because calling it as a function would be slower.
If you want an example of something that's assembly like, look at LLVM IR code. Or Java bytecode. Or WASM
0
u/MagicalPizza21 Software Engineer 11d ago
If you're used to very high-level scripting languages, it might seem conceptually similar. But they're actually far too different for C to be considered "assembly-like". Try reading/writing both languages.
0
u/Distinct-Question-16 11d ago
no the compiler at its end stages will compile to assembly targeting some architecture
0
u/MasterGeekMX Bachelors in CS 11d ago
Assembly is not only dependent on hardware, it is also the most basic kind of instructions you have. This means that every code you want to make must be sliced into these instructions by yourself, which can be tedious.
C and other high level languages make coding easier as you can express common operation in a more readable way, and the compiler is the one making the translation into assembly.
Say for example a classic in any programming language: increasing a variable in 1. C and most languages derived from it have the synrax x = x+1, but they also allow you to write x++ as a shorthand. Python is a common outlier as you need to do x += 1, but the end result is the same. A one line comprised of 3 to 5 characters.
Meanwhile doing that in assembly will require several instructions, depending on the instruction set of the CPU you have. I for example know RISC-V, which will work like this:
lw x11 0(x10) #load the word (4 Bytes) that are located at the address resulting in adding 0 to whatever is stored in register x10, and store it's value in register x11
addi x11, x11, 1 #add 1 to whatever is stored in register x11, and store the result in register x11
sw x11 0(x10) #store the contents of register x11 at the Word (4 Bytes) starting at the address result of adding 0 to the contents of register x10
Not only that is more cumbersome, you also need to make sure many things, such as the address in memory of where x lives is already present in register x10, not to mention make sure x11 is not storing something important, otherwise you will be overwrting it. If not, you either load it with previous insructions, or put a close enough value and change that 0 to another number that added to the contents of x10 offsets the address of RAM where the variable x is actually stored.
0
u/kevleyski 11d ago
No - but it’s closer in that direction and extremely well integrated for mixing C and assembler together
Assembly is for utilising particular hardware features or specific workarounds and other extreme optimisations that are easier to add as asm than modifying the compiler
0
u/CounterSilly3999 11d ago
No. Assembler doesn't support a structured paradigm. Branches and jumps (goto's) are main mean used for execution control in assembler. In C goto is unwanted.
0
u/wolfkeeper 11d ago
Assembly language characteristically has one statement per instruction (but not one instruction per statement because you can have comments), plus macros and things. C characteristically allows far more than one instruction per statement so no, C is definitely not a high level assembler.
0
u/smallproton 11d ago
C has never been Assembly-like.
BUT:
The Gods used to be able to program much closer to bare metal ("assembly"), e.g. in things like memory management. Pointers, malloc(), file descriptors, casts, pointers to arrays of pointers, you name it.
Until these pesky engineers invented stuff like caches, several levels deep, out-of-order execution and such, to speed up stuff that was programmed by mortals.
0
u/Pale_Height_1251 11d ago
No, I work a lot in C and have done a little assembly and they are very, very different. C is very clearly a high level language that feels practically like a scripting language compared with assembly.
0
0
0
u/michaelpaoli 11d ago
Eh, no, not so much. C is sufficiently high-level as to be independent of specific CPU, and can be compiled to run on a huge variety of CPUs.
At the same time, C, is "low level" enough to be quite good at doing things very efficiently, notably at or very close to assembly level performance, and a fair bit of what C implements it does so in manner that often closely mimic behavior in many assembly languages.
So, not very "assembly-like", but given how C is designed, it has a fair bit of stuff that's at least roughly similar-ish, to many assembly languages ... not necessarily in the particular syntax, but more so in rather common functionalities. E.g. dealing with pointers or similar references, pointer arithmetic, the various types of integers C has and how they behave, and how they behave in various math and logic operations, etc.
0
u/gwenbeth 11d ago
So first you have to compare to the right assembly. Not x86 whatever but pdp-11. C was designed to be easy to compile into pdp-11 assembly. Now one fun thing is that the pdp had pre decrement and post increment access modes built in. This is why these exist in c.
147
u/TheBetterProrogation 11d ago
C is portable assembly in the same way a pickup truck is a freight train, the comparison only works if you squint hard enough