BASIC is one way. But you can also start with 'How to Design Programs' approach and start with Racket (http://www.ccs.neu.edu/home/matthias/HtDP2e/Draft/index.html).
Could you expand? Obviously some processors reorder instructions and try to do things in parallel, although this isn't true everywhere and the model of sequential instructions is still valid.
"Lie" might be too strong of a word, but "simplification" would be accurate. And sometimes that abstraction is leaky.
And probably more importantly, they're implementation details: you can't feed a modern processor out of order instructions, the entire system is built and optimised to efficiently execute sequential programs (but possibly several of them concurrently).
> And probably more importantly, they're implementation details
Well, right, programming languages are abstractions built on top of the actual implementation.
I agree that flow control with GOTOs, GOSUB and CALL is the closest to assembler, as well as line numbers slightly resemble how you place machine language code in memory (sequentially), however there are things in which BASIC (the classic line-number basic) deviates significantly:
1. Memory management is automatic in BASIC; in particular strings; string variables have automatic memory management; they can grow or shrink with no problem, you don't need to manage the memory.
2. The only way of allocating memory in basic is when you DIM an array; and then this memory block can't be FREE'd, because there's no "free" instuction, nor the option to DIM another array in the same memory location. (Typical BASIC gives no pointer manipulation facilities).
3. BASIC is often implemented as a strongly typed language. Even the syntax requires differentiating strings from numeric variables by virtue of the first character ($). There's no option to do declare a (void * ) variable and thus operate with total freedom from type checks, as it's possible in C. C is notoriously weakly typed, just as machine language is!
4. BASIC data types are higher level: Strings aren't really a data type in K&R C language -- what you have is character arrays that with some functions can be interpreted as null-terminated strings. Then you have integers and floats whose length (bit-width) or sign (unsigned, signed) you can't specify at all in BASIC.
There's also another significant deviation, if only for theorical considerations:
5. Machine language is arguably homoiconic: It is concerned with manipulating binary data (words), yet the language itself is made of such data (words). So machine language allows, for example, writing self-modifying code, code introspection, etc. BASIC is far from homoiconic.
I, personally, find C much closer to machine language (and thus, Assembler) than BASIC, for the reasons above, basically: manual memory management (via pointers), weakly typed and optionally untyped (via void* pointers and implicit casts), and it is geared towards manipulating data in the format that the CPU likes to (i.e. 32 or 64-bit integers, floats supported directly by the CPU, etc.)
... which, by the way, i enjoyed using a lot when I was a kid.
It might be snobbery, but it seems as if amongst computer programmers, there are those who "get" pointers, and those who do not. For whatever reason - I surely have not figured out how to explain pointers to those who do not "get" them. But I have found that this divide does simplify the software developer interviewing process down to only a couple of short technical questions.
Years later, I started doing things like writing an NES emulator and reading disassemblies of DOS games. Function calls, their relation to the stack, and pointers in general became much clearer after having contact with that much assembly.
> I surely have not figured out how to explain pointers to those who do not "get" them.
Makes me think about the difference between the data being represented and the method of representation. Sure, an exe's a binary, but it's also a data file if I choose to interpret it that way.
Heh, in some ways llvm ssa is the closest you get to a natural programming language for the modern processor.