MIPS Arithmetic is 32 bits MIPS arithmetic instructions that use registers always use full registers, regardless of how data was loaded into the register. For example, an addu instruction does a full 32-bit addition even if one of the operand registers was loaded with lh (or lb) MIPS has no instructions for byte arithmetic nor for halfword arithmetic.
Arithmetic less than 32 bits seems correct For a single operation (such as above), the results in the low-order bytes are the same. The carry out of the high-order bit (of the byte or halfword) is part of the 32-bit result. Further operations may increasingly involve high-order bits. The result after several operations will be a correct result, but may not fit into the original size of the operands.
Low-order Result not always Correct In general the low order byte after several 32-bit operations is not the same as would result from several true 8-bit arithmetic operations. For example, divide the above results by four (by shifting right twice). The low-order bytes are different. These are problems that compilers face. Several extra machine operations must be inserted between each arithmetic operation when the operands are shorter than 32 bits to detect the errors.
Setting up the Base Register lui t,const # upper two bytes # of $t <-- two byte const # lower two bytes of $t <-- 0x0000 After the lui instruction $13 contains 0x 0004 0000 lui $13, 0x0004 0 0 0 4 3 2 1 0
Setting up the Base Register example Form the address 0x0060500C and access the memory: lui $13, 0x0060 ori $13, $13, 0x5000 lw $12, 0xC($13) $13 0 0 6 0 $13 0 0 6 0 5 0 Address 0 0 6 0 5 0 0 C
Data Section Directive .data means: "here is the start of the data section of memory". .word means: "put a 32-bit two's complement integer here". The integer is specified using base 10 (by default). .halfword means: "put a 16-bit two's complement integer here". .byte means: "put an 8-bit two's complement or unsigned integer here". .space n Allocate n bytes of space
Data Section Address The assembler in SPIM automatically assembles the .data section starting at address 0x 1000 0000. .data word1: .word 0x12FA1511 word3: .word -10, 10, -9 In assembly language it is convenient to use names for memory locations. These names are called symbolic addresses.
Data Section Examples ? ? .data word1: .word 0x11111111 hword1: .half 0x3333 byte1: .byte 0x77 hword2: .half 0xEEEE word2: .word 0xBBBBBBBB justspace: .space 16 word3: .word -10, 10, -9 hword3: .half -11, 12, -13 byte3: .byte -12 byte4: .byte 128, 0, 1, -128 , 256, 257 hword4: .half -13 byte5: .byte 255, 256, 511 ? ?
Endianness Portability. Data in the same computer-OK When a word is loaded from memory, the electronics puts the bytes into the register in the correct order. Operations (such as addition) inside the processor use the same order. When the register is stored to memory the bytes are written in correct order. As long as the electronics is consistent in which order is used, either order works. Usually you don't need to think about which order is used. register register 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 memory memory The Most Significant byte The Most Significant byte Lowest Address Lowest Address
Endianness Portability. In different computers - problems Say that you have a file of "integer data" that was written by an old mainframe computer. To read it correctly, you need to know (among other things): The number of bits used to represent each integer. The representational scheme used to represent integers (two's complement or other). The byte ordering (little or big endian) used. [0x10000000] 1 2 3 4 5 6 7 8 1 F A B C 6 7 A D 2 E 4 5 F 9 8 0 2 7 4 5 D 7 F
Porting Example A particular data tape requires big-endian integers. The I/O buffer for the tape starts at address 0x1000 0000. Write a program so that the integer in register $9 is stored in the four bytes starting at address Put the most significant byte at the starting address. $9 1 2 3 4 5 6 7 8 [0x10000000] 1 2 3 4 5 6 7 8
Copy to memory in Big Endian order $9 1 2 3 4 5 6 7 8 main: lui $9,0x1234 # put data in $9 ori $9,0x5678 lui $8,0x1000 # $8 is base register sb $9,3($8) # least significant byte srl $9,$9,8 # move next byte to low order sb $9,2($8) # bits 8-15 sb $9,1($8) # bits 16-23 sb $9,0($8) # most significant byte .data tape: # base register points here .space 1024 # tape buffer (1K bytes) Why we start to write to the 0x10000003 addresses the first? [0x10000000] 1 2 3 4 5 6 7 8
Data Section Addresses. Alignment problems word1: .word 0x11111111 hword1: .half 0x3333 byte1: .byte 0x77 hword2: .half 0xEEEE word2: .word 0xBBBBBBBB justspace: .space 16 Why the gaps appear? Could they be avoided ? DATA [0x10000000] 0x11111111 0x00773333 0x0000eeee 0xbbbbbbbb [0x10000010]...[0x10000020] 0x00000000 [0x10000020] 0xfffffff6 0x0000000a 0xfffffff7 0x000cfff5 [0x10000030] 0x80f4fff3 0x00800100 0xfff30001 0x00ff00ff [0x10000040]...[0x10040000] 0x00000000
Data Section Addresses. Second part word3: .word -10, 10, -9 hword3: .half -11, 12, -13 byte3: .byte -12 byte4: .byte 128, 0, 1, -128 , 256, 257 hword4: .half -13 byte5: .byte 255, 256, 511 DATA [0x10000000] 0x11111111 0x00773333 0x0000eeee 0xbbbbbbbb [0x10000010]...[0x10000020] 0x00000000 [0x10000020] 0xfffffff6 0x0000000a 0xfffffff7 0x000cfff5 [0x10000030] 0x80f4fff3 0x00800100 0xfff30001 0x00ff00ff [0x10000040]...[0x10040000] 0x00000000