Another approach is based on the way kids seem to learn languages. They hear it all the time, and begin to relate the words they hear to the things around them. This is called immersion.
For example, in such an approach, you'd have a teacher speaking Finnish, and nothing else, perhaps pointing to objects to give you an idea of what's going on. You'd mimic the words, and hopefully, figure out intuitively what it means.
Would such an approach work in programming languages? Since programming languages are artificial languages (as opposed to spoken languages, which are said to be natural languages), and the languages are meant to perform some computation, we usually use the approach of teaching features of the language, the syntax, etc.
When learning a second programming langauge, some people simply teach how to translate one language to another. For example, I knew a proficient C programmer, who insisted on writing C-like code in Lisp.
There's some sense to this approach. If your expertise is in one language, you want to maximize your skill as much as possible in another language. However, in making Lisp look like C, this person was writing code that would not be very clear to a Lisp programmer.
In order to learn a new language properly, you need to see what the good programmers in that language write. Otherwise, you will fall in the trap of translating features in the language you're familiar with to the new language. While this isn't inherently bad, it creates many problems.
First, you end up writing code that doesn't look like code written by most people who use the language. Second, you'll end up ignoring the features of the language that make it powerful. For example, Scheme supports continuations. ML supports higher-order functions. Perl has pattern-matching. If you code in these languages like you do in C, you will miss out on the most important features of the language.
So, it's funny that, having said all that, the way you're going to learn how to program in assembly is to learn to translate short C programs into MIPS.
There's one big reason to pick C. It's a simple language. It doesn't do too many unexpected things like C++ does (C++ uses constructors and destructors, often without the programmer being fully aware that it's happening). C++ has complicated features like dynamic dispatch, and object representation, that make it difficult to use as a way to learn assembly.
The other reason is that most people are familiar with C, or C-like programming constructs. Even if you program in Java or C++, there's some core features that are in common with C.
One reason for not trying to "immerse" ourselves in MIPS programming and instead, to translate C code, is because you are familiar with C programming, and we want to leverage off that strength. You're not expected to become fantastic assembly language programmers.
The point is to translate the code much like a C compiler would.
A lot of the code we write is meant to make it easy to translate.
Occasionally, a so-called clever student actually tries to understand
what the program does, and then says "it can't be translated". Here's
an example:
for ( i = 31 ; i >= 0 ; i++ )
A[ i ] = A[ i + 1 ] ;
Several things are "wrong". The i++ should be an i--,
otherwise, you go into an infinite loop. However, even if you
replace it with an i--, the code merely copies A[32]
to all array elements.
As a proficient programmer, you see this while you write the code. However, the goal is merely to translate. When's the last time a compiler had an error message "this is an infinite loop, correcting your code?". It never says that. It translates the code as faithfully as you type it.
So, when we do these exercises, keep in mind that you are acting like a compiler. You are converting the code as accurately as you can, without thinking about "what does this code really do?"
One simple reason is that this is the language that CPUs understand. In order to understand how a computer works, it helps to see how it processes instructions, and in order to do that, you need to write some code.
So, the idea is to give you a flavor of what a compiler might produce, and to see what the CPU is processing. While programming languages can isolate you from the details of what the CPU does, a good CS major should know what's "underneath the hood".