Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

MIPS Assembly - lui $t0, 4097?

Writer Sophia Terry

Can someone explain me how does lui works, what does "4097" stand for, what does adding 8 to $t0 mean?

.data 0x10010000 blank: .asciiz " " # 4097 newline: .asciiz "\n" # 4097 + 2 #input_start Alength: .word 13 Aarray: .word 130, 202, 30, 4440, 530, 532, 33, 204, 8, 524, 8933, 92, 10 #input_end
.text lui $t0, 4097 ori $a0, $t0, 8 # address of A[] lw $a1, 4($t0) # load length

4 Answers

4097 = 1001 hex

so, the first instruction puts 0x10010000 into register t0. lui is "load upper immediate", with "upper" meaning the upper 16 bits, and "immediate" meaning that you are giving it a literal value (4097). 4097 as an "upper" value becomes 0x10010000.

ori is "or immediate", with 8 being the immediate value, so the resulting address in a0 is 0x10010008, which is the address where Aarray lives.

The final instruction lw is "load word" which loads from the memory address in t0 (which at this point is still just 0x10010000) plus 4 bytes (the 4 is an offset from t0 and results in an address where ALength lives) 4 bytes of data into a1.

lui $t0, 4097 is the load upper immediate instruction. The immediate value(4097) is shifted left 16 bits and stored in the $t0 register. The lower 16 bits are zeroes.

This is "doing it manually" to generate static addresses, as a workaround for the MARS assembler lacking %hi(symbol) and %lo(symbol) to get the linker to fill in the 4097 (0x1001) from the high half of the address of Alength and Aarray, and the 4 and 8 from the low half of those addresses.

This code assumes that MARS will put the .data section at 0x10010000, like it says on the line with the .data directive.

The two strings happen to add up to 4 bytes total, so the word values are already word-aligned. This code leaves out a .align directive, even though it would have ended up being zero bytes (until you add another string and your word load breaks).


If you compile this C on the Godbolt compiler explorer:

int x = 1; // with no initializer it goes in the .bss as .space 4
int foo() { return x; }

MIPS gcc5.4 -O3 gives you this asm (some noise is stripped away):

foo(): lui $2,%hi(x) lw $2,%lo(x)($2) j $31 nop # IDK why it didn't put the load in the branch-delay slot; clang does .data .p2align 2 # actually gcc uses .align 2 but I disambiguated
x: .word 1

$2 is $v0, the return value in the standard MIPS calling convention.

Just wanted to add a more accessible explanation of lui $t0, 4097:

  • 4097 in decimal is equal to 1000000000001 in binary
  • lui loads the value in the first 16 bits of the register

So lui $t0, 4097 will store 10000000000010000000000000000 in $t0 which is equal to 268500992 in decimal

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy