Like x86, PowerPC machine code consists of bytes, with addresses, that represent assembly instructions and operands. PowerPC machine code also spends most of its time manipulating values in registers.
Add, like most arithmetic on PowerPC, takes *three* registers: two sources, and a destination.
There's a separate instruction named "addi" (add immediate) to add a constant; plain "add" only works on registers.
PowerPC machine code always uses four bytes for every instruction (it's RISC), while x86 uses from one to a dozen bytes per instruction (it's CISC). Here's a good but long retrospective article on the RISC-vs-CISC war, which got pretty intense during the 1990's. Nowadays, RISC machines compress their instructions (like CISC), while CISC machines decode their instructions into fixed-size blocks (like RISC), so the war ended in the best possible way--both sides have basically joined forces!
One effect of fixed-size instructions is you can't load a 32-bit constant in a single instruction:
Instead, you break the 32-bit constant into two 16-bit pieces. They have a dedicated load-and-shift instruction "lis":
Memory is accessed with the "lwz" (load word) and "stw" (store word) instructions. Unlike x86, these are the *only* instructions that access memory; you can't do an "add" with one operand in memory!
lwz r3, 0(r1) ; load register r3 from the stackHere I'm writing an integer out to the stack, then reading it in again.
There are "updating" variants of load and store called "lwzu" and "stwu". These actually change the value of the pointer used as an address. For example,this code does two things:
stwu r7, -4(r1)
Here's an example:
Array indexing mostly has to be done manually. If r5 is the start of the array, and r6 is the index, you have to do something like this:
You can combine the add and lwz with a "lwzx":
ori r5,r1,0 ; array pointer==stack pointerHere, _print_int will end with its own "blr", which will jump straight back to main, skipping us. Getting control back from a function is much trickier. The problem is a function will end with "blr" (Branch to the Link Register); the Link Register can only hold one value at a time. So if you just overwrite the Link Register with your own value, you can't return to main!
So this "bl" (Branch and Link) will return control back to you, but then *keep* returning control back to you, in an infinite loop:
The sequence of events here is:
OK! Everybody returns correctly now, but main complains we overwrote its preserved data (r28 is preserved).
So now we save the old link register onto the stack:
Whew! The x86 "call" and "ret" are looking a lot better now!
The IBM 32-Bit PowerPC Programming Environment gives all the instructions in chapter 8.1 and a good overview in chapter 4. The IBM Compiler Writer's Guide gives the calling conventions.