Understanding MIPS Instruction Formats & Pointer Arithmetic - Prof. Craig Zilles, Study notes of Computer Architecture and Organization

An introduction to machine language, the binary representation of instructions, and mips machine language specifically. It covers the design of mips machine language, including its fixed-length instructions and limited-sized immediate fields. The document also discusses the use of pointers and pointer arithmetic, and how they are represented in machine language. Students will gain a better understanding of machine language and its role in computer programming.

Typology: Study notes

Pre 2010

Uploaded on 03/16/2009

koofers-user-h28
koofers-user-h28 🇺🇸

10 documents

1 / 18

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
January 30, 2008 Machine Language and Pointers 1
What does this C code do?
int foo(char *s) {
int L = 0;
while (*s++) {
++L;
}
return L;
}
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12

Partial preview of the text

Download Understanding MIPS Instruction Formats & Pointer Arithmetic - Prof. Craig Zilles and more Study notes Computer Architecture and Organization in PDF only on Docsity!

What does this C code do?

int foo(char *s) {

int L = 0;

while (*s++) {

++L;

return L;

Machine Language and Pointers

 Today we’ll discuss machine language, the binary representation for instructions. — We’ll see how it is designed for the common case

  • Fixed-sized (32-bit) instructions
  • Only 3 instruction formats
  • Limited-sized immediate fields  Array Indexing vs. Pointers — Pointer arithmetic, in particular

R-type format

 Register-to-register arithmetic instructions use the R-type format.  This format includes six different fields. — op is an operation code or opcode that selects a specific operation. — rs and rt are the first and second source registers. — rd is the destination register. — shamt is only used for shift instructions. — func is used together with op to select an arithmetic instruction.  The inside back cover of the textbook lists opcodes and function codes for all of the MIPS instructions. 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits op rs rt rd shamt func

About the registers

 We have to encode register names as 5-bit numbers from 00000 to 11111. — For example, $t8 is register $24, which is represented as 11000. — The complete mapping is given on page A-23 in the book.  The number of registers available affects the instruction length. — Each R-type instruction references 3 registers, which requires a total of 15 bits in the instruction word. — We can’t add more registers without either making instructions longer than 32 bits, or shortening other fields like op and possibly reducing the number of available operations.

 Larger constants can be loaded into a register 16 bits at a time. — The load upper immediate instruction lui loads the highest 16 bits of a register with a constant, and clears the lowest 16 bits to 0s. — An immediate logical OR, ori, then sets the lower 16 bits.  To load the 32-bit value 0000 0000 0011 1101 0000 1001 0000 0000: lui $s0, 0x003D # $s0 = 003D 0000 (in hex) ori $s0, $s0, 0x0900 # $s0 = 003D 0900  This illustrates the principle of making the common case fast. — Most of the time, 16-bit constants are enough. — It’s still possible to load 32-bit constants, but at the cost of two instructions and one temporary register.  Pseudo-instructions may contain large constants. Assemblers including SPIM will translate such instructions correctly. — Yay, SPIM!!

Larger constants

 The limited 16-bit constant can present problems for accesses to global data. — As we saw in our memory example, the assembler put our result variable at address 0x10010004. — 0x10010004 is bigger than 32,  In these situations, the assembler breaks the immediate into two pieces. lui $at, 0x1001 # 0x 1001 0000 lw $t1, 0x0004($at) # Read from Mem[0x1001 0004 ]

Loads and stores

 Empirical studies of real programs show that most branches go to targets less than 32,767 instructions away—branches are mostly used in loops and conditionals, and programmers are taught to make code bodies short.  If you do need to branch further, you can use a jump with a branch. For example, if “Far” is very far away, then the effect of: beq $s0, $s1, Far ... can be simulated with the following actual code. bne $s0, $s1, Next j Far Next: ...  Again, the MIPS designers have taken care of the common case first.

Larger branch constants

J-type format

 Finally, the jump instruction uses the J-type instruction format.  The jump instruction contains a word address, not an offset — Remember that each MIPS instruction is one word long, and word addresses must be divisible by four. — So instead of saying “jump to address 4000,” it’s enough to just say “jump to instruction 1000.” — A 26-bit address field lets you jump to any address from 0 to 2 28 .

  • your MP solutions had better be smaller than 256MB  For even longer jumps, the jump register, or jr, instruction can be used. jr $ra # Jump to 32-bit address in register $ra 6 bits 26 bits op address

Null-terminated Strings

 For example, “Harry Potter” can be stored as a 13-byte array.  Since strings can vary in length, we put a 0, or null, at the end of the string. — This is called a null-terminated string  Computing string length — We’ll look at two ways. H a r r y P o t t e r \

Array Indexing Implementation of strlen

int strlen(char *string) { int len = 0; while (string[len] != 0) { len ++; } return len; }

What is a Pointer?

 A pointer is an address.  Two pointers that point to the same thing hold the same address  Dereferencing a pointer means loading from the pointer’s address  A pointer has a type; the type tells us what kind of load to do — Use load byte (lb) for char * — Use load half (lh) for short * — Use load word (lw) for int * — Use load single precision floating point (l.s) for float *  Pointer arithmetic is often used with pointers to arrays — Incrementing a pointer (i.e., ++) makes it point to the next element — The amount added to the point depends on the type of pointer

  • pointer = pointer + sizeof( pointer’s type)  1 for char *, 4 for int *, 4 for float *, 8 for double *

What is really going on here…

int strlen(char string) { int len = 0; while (string != 0) { string ++; len ++; } return len; }