1

I am a beginner of assembly language, so I hope anyone who give me a answer could explain be more specific.

Question is converting from C to assembly language.

C code is:

while(save[i] == k)
    i += 1;

i and k are in $s3 and $s5 and base of array save[] is in $s6

The answer is in the figure.

figure

What I misunderstand is that why $S3 multiple 2^2(==4), and then store into $t1.

I check on stackoverflow for similar questions, some people said "You should add the base and index together, and remember to scale by 4 for the word size. "

But because I am a beginner, I am still confused.

For example,

  1. after a one cycle, i == 2 (in $S3).

  2. and then start over, i == 2 in $S3 multiple by 4, we get 8 here, and then writes into $t1.

So there is a question, why is 8? I think what we need is save[2] not save[8].

I thought I might confused about value and address.

An another question is: how many bits are those register like $S1, $t1? I think is 32 bits, so it should be 1 word.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
lbrobinho
  • 143
  • 1
  • 11
  • 2
    C uses typed indexing, it automatically scales by item size. Assembly (mips) uses byte indexing, it's your job to account for that. – Jester Feb 26 '18 at 00:06
  • When you increment the array index in C, the next element at offset 4(assuming array is of type 'int' and 'int' is 4 bytes on your target) is accessed. That is why in assembly the array 'save' address is offset by 4 to access next element. – hafeez Feb 26 '18 at 00:09

2 Answers2

4

lw is to be provided the address of the first byte of the word to load.

If each element of save is 32 bits or 4 bytes in size, then

  • save[0] is found 0 bytes beyond the start of save.
  • save[1] is found 4 bytes beyond the start of save.
  • save[2] is found 8 bytes beyond the start of save.
  • ...
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Thank you @ikegami ! I think I almost got it, but why it multiple 4 bytes not 32 bits? I mean why 4 is byte not bits? Thanks! – lbrobinho Feb 26 '18 at 04:19
  • 4 bytes and 32 bits are the same amount. 4 bytes = 4 bytes * 8 bits/byte = 32 bits. Since the instructions can only address bytes, it only makes sense to do the arithmetic in bytes. – ikegami Feb 26 '18 at 04:26
  • Yes, I know that. what I really want to ask is, "sll" means shift left N bits, each elements is 32 bits, so I should shift 32 bits left to get next value(for example, save[2]), so why is not"sll, $t1, $s3, 5", 2^5 is 32. Thank you! – lbrobinho Feb 26 '18 at 04:38
  • I already answered that. It makes no sense to calculate an offset in bits when you want an offset in bytes. The offset in bytes that you want is `i * 4` = `i * 2^2` = `i << 2` – ikegami Feb 26 '18 at 04:40
  • After long time thinking, I seems got the point. For example, i = 2, which is 0000 0000 0000 0000 0000 0000 0000 0010. First 0000 0000 store in memory 0x00000000, and so on, last 0000 0010 stores in memory 0x00000003. So every 32 bits store one value of i, and every 8 bit (i.e. 1 byte) is one block in memory, So every value of i takes 4 blocks. Am I correct? – lbrobinho Feb 26 '18 at 05:52
  • No. The size of `i` is irrelevant; you're trying to load an element of `save`. **Each *element of `save`* takes 32 bits, so every *element of `save`* takes 4 bytes.** (It's simple unit conversion 32 bits = 4 bytes just like 12 feet = 4 yards.) I'm not sure what the rest of what you said means, but it sounds wrong. – ikegami Feb 26 '18 at 06:01
  • @lbrobinho MIPS platforms are usually configured to be little-endian, so 0x12345678 is stored in memory as bytes (hexa): `78 56 34 12` (top bits are at offset+3, least significant bits are in first byte at +0). Or in binary that would look like `0111_1000 0101_0110 0011_0100 0001_0010`. When the little-endian CPU loads those 4 bytes from memory as word, it will shuffle it internally into original `0x12345678` value. And nobody so far wrote the "obvious" (for us) thing, the memory chip is addressable by bytes, you can't single-fetch bits 3-35 as word, as those are not aligned to byte boundaries – Ped7g Feb 26 '18 at 10:13
  • @lbrobinho actually on MIPS the `lw` has even stricter requirement, the address must be word-aligned (bottom two bits must be zero). The `lb` is capable to operate on single bytes, also on any byte-offset. But that's more like limitation of CPU + memory-manager-unit, I believe the memory chip itself is fine operating on unaligned addresses with words, it's the CPU+MMU combination which can't then properly internally handle all the things, like cache (if any), etc. – Ped7g Feb 26 '18 at 10:17
  • @Ped7g Exactly, what you answer is really what I want to ask, but like you said, nobody so far wrote the "obvious" thing. But when I check the structure of memory, I am quite clear now. Thanks, bro. – lbrobinho Feb 26 '18 at 16:59
  • @Ped7g, Re "*And nobody so far wrote the "obvious" (for us) thing, the memory chip is addressable by bytes*", Actually, I did. Twice. It's the very first line/paragraph of my answer. ("`lw` is to be provided the address of the first byte of the word to load.") It's also in my first comment ("the instructions can only address bytes"). – ikegami Feb 26 '18 at 17:23
  • @ikegami your answer is definitely nice and would help *me*. But the first comment you highlight is not the same thing, it's about where the `lw` will start, but doesn't explain why word occupies 4 bytes or why addressing is working with bytes (it's more like step 2 comment, after you understand that step 1). The second from comment is basically almost the same thing, just in other words. In my wording I tried to point out where that thing comes from, that it's the HW memory chip design, which is using per-byte addressing, looks like that wording helped the OP to put it all together. :) – Ped7g Feb 26 '18 at 18:22
  • Re "*doesn't explain why word occupies 4 bytes*", I explained that in details. 32 bits is 4 bytes because there are 8 bits per byte. /// Re "*doesn't explain [...] why addressing is working with bytes*", Correct, but neither did you. Just like you, I just said that it was byte addressable, not why. – ikegami Feb 26 '18 at 18:32
1

Each entry in save is 32 Bit long. This means, that the i-entry has an offset of i * 32 Bit = i * 4 Byte starting with the base address $s6 C is actual very smart and calculates this for you internally. So in C-Code writing save[i] is the same as *(save + i). An Addition to an pointer will be multipled by its size, so C will translate it into save + 4 * i

The Register size depends in your local architecture, but is generally speaking mostly 32 Bit for examples/exercises.

Domso
  • 970
  • 1
  • 10
  • 22