addi instruction을 이용해 12비트 상수를 만들 수 있다.
int a = -372;
int b = a + 6;
이것을 실행하려 한다면?
addi s0, zero, -372
addi s1, s0, 6
이것을 실행하면 된다.
그러나, addi instruction의 상수 부분은 12비트이다. 즉 12비트 상수만 위치할 수 있다. 그렇기에 12비트보다 큰 상수는 이 방식으로 만들 수 없다.
32비트 상수는 lui와 addi instruction을 사용해서 만든다.
int a = 0xFEDC8765;
이것을 실행하고 싶다면,
lui s0, 0xFEDC8 (1)
addi s0, s0, 0x765 (2)
이것을 실행하면 된다. lui instruction은 주어진 immediate(위의 예시에서는 0xFEDC8)을 destination register(s0)의 상위 20비트에 할당하고, 나머지 하위 12비트는 0으로 채우는 동작을 한다. 즉, s0에 32비트 상수를 넣기 위해서, 우선 lui instruction을 통해 s0의 상위 20비트에 우선 0xFEDC8이라는 값을 넣어준 후(1), 나머지 하위 12비트에 0x765를 마저 넣어주는 것이다(2).
이때, 32비트 상수의 하위 12비트의 MSB가 1일 경우는 조금 다르다.
가령, a에 할당하려는 값이 0xFEDC8EAB라고 하자.
int a = 0xFEDC8EAB;
이것의 하위 12비트는 0xEAB로, MSB가 1이다. 이럴 경우, 위의 (2) 부분에서 addi를 할 때, s0는 32비트 값이므로 0xEAB 역시 32비트로 sign extension이 일어나는데, 0xEAB는 MSB가 1이므로 비트 1이 왼쪽으로 20개 확장되어 버린다. 이러면 결과값이 달라진다.
이를 방지하기 위해, 하위 12비트의 MSB가 1일 경우, (1) 부분에서의 immediate에 1을 더해준다. 즉 다음을 실행하는 것이다.
lui s0, 0xFEDC9
addi s0, s0, -341(0xEAB가 sign extension된 값)

이렇게 원래의 0xFEDC8EAB가 잘 나오고, 이 값이 s0에 잘 할당된다.