Writing C code first and using it as pseudo code for the mips assembly is a fine way to do this.
Then, reduce the C code to what I call "simple C". No while
, for
, or complicated expressions. No local variables. Only globals that are either things you define with .word
like myvar: .word 23
or variables that correspond to the mips registers. Only very simple if (expr) goto label;
See my answer here for an example: Struggling with the logic in if statement
See my answer here: MIPS linked list This also has a bunch of tips about how to write clean asm code and an example of how to use C/pseudo code to construct asm code.
So, for part a, we're talking about unsigned char
. Once the values have been fetched into register variables, apply a standard swap that you would do in C.
For part b, note that the addresses are aligned to 4 byte boundaries, so you can fetch/store them with 32 bit access. So, we're talking unsigned int
. The wrinkle is that when the swap is done, proper masking/shifting/splitting has to be done to swap the bytes but not swap the remainder of the 32 bit words, using only unsigned int
So, write the C code first. You can fake the 100/200 with:
typedef union {
unsigned int ival;
unsigned char bval[4];
} membuf_t;
membuf_t adr100;
membuf_t adr200;
This is just to allow you to write real C code and test it first. For the asm, you can just reference the [hardwired] addresses (e.g. 0x100($zero)
).
But, the 100/200 assumes you're just going to do this as a thought experiment and not try to actually debug your asm code using a simulator like mars
or spim
[because they really don't like you use these memory addresses in code they simulate].
If it were me, I'd use mars
and write code that can be single stepped. For that, once again, adjust slightly:
adr100: .word 0x01020304
adr200: .word 0x05060708
Then, after everything is working, just replace the adr*
references by hand.
UPDATE:
One thing I forgot to mention is that you have to be aware of endian issues. That is, for the C code when you do a 32 bit fetch from adrXXX.ival is the adrXXX.bval[0] in bits 0-7 (little endian) or bits 24-31 (big endian)?
Assuming you do the C code on an x86 PC, it's little endian. IIRC, mips is little endian as well, but, honestly, I forget [and some models can be big endian or can switch dynamically]. The simulators are [probably] little endian, so, maybe, no worries.
One way to test on mips (or C as well) is to use an extra test cell (i.e. create a 3-4 line throwaway test program): test: .word 0
. Get a register filled with 0x00000001. Then, do a byte store to test
. Then do a 32 bit load from test
. The non-zero byte within the register gives you the endian for the machine (i.e. it's either in bits 0-7 or bits 24-31).