-4

Load immediate loads a register with a value that is immediately available (without going to memory). My question is how can i load a register with a value without using load immediate ?

li $1,100 # i don't wanna use this method.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • Why can you not use `li`? That's literally the instruction for this purpose. Also, what architecture are you programming for? – fuz Apr 13 '21 at 22:57
  • its my homework actually :/ – Ata Akalın Apr 13 '21 at 23:01
  • 3
    `li` is a pseudoinstruction. You can write out the equivalent instructions the assembler would produce for you. For example, `ori $1, $0, 100` – Jester Apr 13 '21 at 23:02

1 Answers1

1

For any operation that accepts an immediate, you can set the other operand to be the identity element of that operation: x = op(x, I). Here are some options:

  • Add or subtract 0
  • Perform bitwise OR with 0
  • Perform bitwise AND with all 1s (-1 in 2's complement)
  • Multiply with or divide by 1
mkayaalp
  • 2,631
  • 10
  • 17
  • How are you doing to multiply or divide the constant you want by 1? MIPS mult and div instructions don't take immediate operands (https://uweb.engr.arizona.edu/~ece369/Resources/spim/MIPSReference.pdf), and even if they did (e.g. via pseudo-instructions) you'd already need one operand in a register so you have a chicken/egg problem. Same problem for AND with `-1`, although you can create that with `nor $dst, $zero, $zero` I guess. The only constant you have easy access to is `0` via the `$zero` register. Also, there's no immediate sub; you have to emulate that by adding a negative. – Peter Cordes Apr 14 '21 at 03:05
  • So your options are ADDIU for a -32768..36767 range, or a logical like ORI or XORI for a 0..65535 range. Or `lui` for multiples of 65536. I don't think there's much else that's truly viable. – Peter Cordes Apr 14 '21 at 03:08
  • @PeterCordes There was no MIPS tag before, so I wasn't referring to a particular ISA. You are right, zero is usually available as a hardwired register, or you can subtract something from itself or bitwise XOR with itself. But you could get to 1 or -1 from 0 with an `inc` or `dec` kind of instruction in CISC, or you could divide something by itself (1) or bitwise XNOR with itself (-1). – mkayaalp Apr 14 '21 at 03:24
  • I've never seen an ISA with a mul that could take *two* immediates because that would be pointless and something you should do at assemble time. And immediate division if it exists at all normally takes the divisor as an immediate (e.g. x86's AAM), so you'd already need your constant in a register. I think mul and div are so unlikely to be helpful (and so much worse for performance) that it's not even worth mentioning them. I see your point about finding the identity element for an operation, but maybe that's something you could mention in passing in the paragraph about identity elements. – Peter Cordes Apr 14 '21 at 03:31
  • IDK, maybe you're trying to expand on the the restricted-instruction-set aspect of the question by coming up with esoteric alternatives, even if that takes more instructions to construct constants for them. – Peter Cordes Apr 14 '21 at 03:32
  • Despite the lack of an ISA tag, `li $1, 100` is highly suggestive of MIPS (`$reg`), and the `li` mnemonic is typically only found in RISC load-store ISAs. So CISC arguments are not really relevant. If you want esoteric MIPS stuff, `sltiu` can create a `1`, but you need a register that's definitely not `0xFFFFFFFF`. So I guess `sltiu $dst, $zero, 1` would work, using the zero register. – Peter Cordes Apr 14 '21 at 03:38
  • @PeterCordes Yes, I am. But I wasn't suggesting the identity element would be an immediate. It would be the other operand, in the accumulator/register/memory/wherever. So you set `R1=R1/R1`, then say `R1=R1*imm`. – mkayaalp Apr 14 '21 at 03:42
  • You need a known value in R1 to avoid possible divide-by-zero so that's not a useful building block. (Unless you get it via `R1 |= immediate` to make division safe. But it would be a rare ISA indeed where you could do that but not just create a small integer constant in a register directly with a single instruction. I guess an ISA without a zero register if you were forbidden from using the normal `mov`-immediate.) – Peter Cordes Apr 14 '21 at 03:45
  • @PeterCordes It's all fiction anyway: "how do I load an immediate without loading an immediate?". You are right about divide-by-zero though, that's probably not a good example. But I did teach `SUB Xn, Xn, Xn; ADDI Xn, Xn, #imm` when introducing A64. It's easier than going into the weird logical immediates and XZR/XSP before you could do simple assembly exercises. – mkayaalp Apr 14 '21 at 04:01
  • No, it's ""how do I load an immediate without using the `li` pseudo-instruction?" Also, please don't teach people to zero registers with `sub reg,reg` on AArch64; the memory model prevents the CPU from breaking the dependency on the old instruction. I don't see how that's easier or better than `mov Xn, #0` (which you can introduce as a "we'll break this down later" opaque building block; disassemblers like objdump even decode the resulting OR or ADD as a MOV.) Some people get the impression (from x86) that in general one should avoid mov reg,0 on other ISAs, which of course isn't the case. – Peter Cordes Apr 14 '21 at 04:07
  • @PeterCordes They are not learning how to write compiler backends, they are learning the datapath and control (they learn MOVZ and aliases a little later). It was pretty much a quote from the question: "how can i load a register with a value without using load immediate?". – mkayaalp Apr 14 '21 at 04:17
  • Ok yes, they did expand the mnemonic, but it's clear from the code they specifically meant without the `li` instruction. And re: AArch64, yeah I guess if you have to understand the dataflow of every instruction, you need to avoid any opaque "we'll explain later" stuff. As long as you point out the false dependency of using SUB for zeroing at some point. – Peter Cordes Apr 14 '21 at 04:37