
Introduction to Computer Organization: ARM Assembly Language on the Raspberry Pi - ingve
http://bob.cs.sonoma.edu/IntroCompOrg-RPi/intro-co-rpi.html
======
leggomylibro
Awesome! Personally, I think that ARM assembly has a TON of potential for
teaching people how to code and/or work with electronics hardware from a state
of almost no background knowledge.

\- They teach the concept of a computer program as a bunch of single small
logical 'steps'.

\- They make it easier to keep new students interested without plying them
with pages and pages of 'magic code' \- not only can you make a zero-
dependencies program (in the case of simple mobile chips), your 'hello world'
is actually in the physical world. An LED, a motor, what-have-you.

\- The core instruction set for a Cortex-M0+ processor has what, 60
instructions? It's not very complicated.

On the con side of things, the whole idea of registers controlling hardware
peripherals can be a little weird, and you have to get people comfortable with
command-line debugging utilities. The _concepts_ are simple, but GDB isn't.
And many of the available IDEs aren't very cross-platform.

And I guess application processors also probably introduce their own extra
complexities, compared to a Cortex-M line which is more comparable to an
Arduino than a RasPi or Chromebook. But hey, there's also less hardware
available with the sort of support that a Raspberry Pi has; the closest you'd
probably get is a cheap generic $3-5 STM32F103C8 dev board.

If anyone else is interested in this sort of thing, the reference manuals
provided by ARM are also very readable, for example:
[http://infocenter.arm.com/help/topic/com.arm.doc.ddi0484c/DD...](http://infocenter.arm.com/help/topic/com.arm.doc.ddi0484c/DDI0484C_cortex_m0p_r0p1_trm.pdf)

~~~
userbinator
Maybe it's just me, but I don't think basing a whole book on a sparsely-
documented SoC from a notoriously proprietary company is a great idea at all.
There are plenty of other ARM processors with far more documentation
available, and if your goal is to teach how computers work from the hardware
up, also plenty of other much simpler and equally well-documented
microcontrollers.

~~~
cmrdporcupine
I also don't like that the Pi is not fully open, but it is also extremely
available and cheap, so an ideal system for people starting out. And ARM
assembly is a much nicer first assembly language than x86. A microcontroller
is a possibility, but has its own barriers to entry (not a standalone computer
in itself, can't be attached easily to display, etc.).

Maybe someday the lowrisc project will become a reality, and they can use
that, and teach RISC-V instead.

~~~
AnIdiotOnTheNet
6502s are cheap (though probably not as widely available as a complete system)
and have an even simpler assembly language.

------
indescions_2017
Very clearly written. Thanks for posting. Would recommend to anyone wishing to
dive deep into architectures. And I love that you are teaching undergrads with
the RP3 ;)

Anyone wanting more, the MIT Computational Structures courses are always
available via EDX:

[https://www.edx.org/course/computation-
structures-3-computer...](https://www.edx.org/course/computation-
structures-3-computer-mitx-6-004-3x-0)

------
PuffinBlue
Wow, this is absolutely amazing. I'm just starting out and this is actually
pretty inspirational, especially as I have a few Pi's already.

I hear stories about the 'good old days' when everyone was hacking on some
amazing open hardware and earning their chops knee deep in assembler etc etc.

This kind of feels like I might get a little taste of that by following this
book.

Awesome!

PS - Is there a hardcopy or pdf available too?

------
red_admiral
I've had a quick look through and I really like this. Bookmarked for future
reading.

As a security person, I have just one request - in 2.9 you explain/recall how
functions look in C, then you explain printf, then the first C statement you
execute is

printf("Enter an unsigned decimal integer: ");

Please, please can this kind of thing be printf("%s", "Enter an unsigned
decimal integer: ");

I know this string is a compile-time constant, so it's not going to hurt
anyone, but you're teaching people the old myth that printf(string) is the way
to print a string and at some point they'll try this with a user-supplied
string.

In my opinion, a printf with only one argument is always a code smell.

EDIT: also, the solutions to exercises 1 and 2 in 2.16 are vulnerable to
buffer overflows.

~~~
wolfgke
> I know this string is a compile-time constant, so it's not going to hurt
> anyone, but you're teaching people the old myth that printf(string) is the
> way to print a string and at some point they'll try this with a user-
> supplied string.

I am also very security-conscious in my programming, but the rule that I apply
is

    
    
       printf(string);
    

is the way to use if string is some compile-time constant that visibly
contains no '%' character and

    
    
      printf("%s", string);
    

is the way to go otherwise. In this sense I consider the rule

> In my opinion, a printf with only one argument is always a code smell.

as cargo-cult coding.

~~~
red_admiral
Your answer is correct, secure and has fewer false positives than mine. But I
interpret cargo cult to mean doing something with no unserstanding why it
should work (and in the original example, ending up with "it doesn't work").
That's not the case here.

"Code smell" to me means code that should make you feel bad when
reading/writing it, as opposed to code that's wrong - a psychological device
to make code that often is wrong, always look wrong. The classic example is
if(a = b) which is sometimes really what you want - but I'd write this if((a =
b)) in this case to make it clear it's deliberate. printf("%s", str) is the
same kind of thing, and it means when I'm reviewing code I don't have to go
and check whether str really is a compile-time constant or not. Better still,
it's also a sign to the human reader that there's no fancy formatting going on
here - you're really just printing a string.

"Always use 2+ arguments to printf" is a rule for humans that has the
advantage of being really easy to follow and to teach and avoids the most
common version of the vulnerability. I don't mind people who know what they're
doing breaking this rule (sometimes breaking a rule when you know it's ok is
pretty much a definition of being an expert) but I do include the rule
whenever I'm teaching printf to beginners.

~~~
boomlinde
From a security perspective I would be more concerned with using printf at all
when puts/fputs would have been fine and less susceptible to possible run-time
errors. If you're not really using a formatting template for anything
meaningful, you shouldn't be using a string formatting function. So the point
that you should "always use 2+ arguments to printf" holds, but the solution
isn't to make the first argument "%s".

~~~
wolfgke
I accept your reasoning, but I am a little bit divided on this advice. On the
one hand your reasoning is sound. On the other hand, in particular in an
embedded or security field one wants to keep the code footprint really small
if possible (fewer lines of code mean fewer lines of code that might contain a
bug - of course under the assumption that the bug rate is constant in both
code bases). So if one does not even have puts/fputs in the codebase, there
trivially cannot be any obscure corner case bug in the used puts/fputs
implementation.

~~~
boomlinde
From a security standpoint, if your standard I/O implementation has a bug in
its `fputs`, it is broken on such a fundamental level that you should print
it, delete it and burn the printed copy. Better to find this out with
something relatively trivial with a minimal surface for errors like puts than
through an obscure format string.

`printf` gives the caller more opportunities to accidentally cause bugs. The
difference in LOC when comparing for example FreeBSD `puts` to `printf`
variants is so great that if you had any reason to doubt the implementation of
the standard library you would be better off writing your own formatting
functions and print everything with puts/putc because that would likely be
easier to test and verify than identifying all the edge cases in `printf` flag
parsing.

Personally, I think either way to do it is fine, but since we're seemingly all
in the mood to be picky about code smell, security and such, I thought I'd
join in. In reality the examples mentioned are not production code, and they
are likely to be used with GNU libc, not Cheap Chip Factory libc 0.0.1 alpha.
In most cases, the standard library is well exercised because its use is
ubiquitous. If that can not be assumed, and you're somehow stuck with a broken
standard library, I'd rather go ahead and verify puts, and let _you_ dig into
the `vsprintf` parser and make sure it works in all the cases it gives the
caller an opportunity to create :)

------
filereaper
Massive upvote, the standard text book for Computer Organization is Patterson
and Hennesy's "Computer Organization and Design: The Hardware/Software
Interface"

Its a lovely book, but its hard to get hold of MIPS processors these days.
Hopefully this creates a new generation of devs which can tinker with real
hardware and are armed with proper education behind how it all works.

Super happy, wish I had this during mys schooling. :)

~~~
CalChris
There are now ARMv8 and RISC-V editions of COAD. I’m sort of waiting for the
second edition of the ARMv8 version. However at this point I prefer COAD to
CAAQA which is bloated with IMHO non CA stuff.

------
mhd
Back in the 8/16 bit days, ARM assembly was said to be one of the best
features of Acorns — even compared with 68k asm. Maybe it’s finally time to
look at this...

~~~
jlarcombe
Yes, although the new instruction set in ARMv8 removes several of the things
that made programming in 'classic' ARM assembly such fun on the Acorn, such as
the free barrel shifter on most arithmetic ops, conditional execution on all
instructions and fast multiple loads/stores with groups of registers. These
have gone for various reasons; the fully-flexible barrel shifter is awkward at
high frequencies with deep pipelines, the conditional execution flags became a
waste of opcode space as branch prediction improved and the load/store
multiples required microcode on modern implementations and so increased
complexity.

------
knowThySelfx
Superb. This is so neatly and thoughtfully organized. Presented in simple
terms and covers a lot of ground. Great stuff to build upon.

------
grandalf
This looks like a superbly designed curriculum.

------
probinso
Thanks for posting!

