Since I didnt find anything that helped me fixing my problem Im just going to ask myself, I have the following assembly(mips) code for example:
.data
.text
main:
li $t2, 'S'
sb $t2, 0($t3)
li $v0, 10
syscall
In my "original" program Im reading a String character for character, saving each one into a register until a " " (Space) appears, to get single words. Now loading byte for byte into a register $t1 works, checking if the read character is a "Space" (to stop loop) works too, but when I then want to store that byte as written above into another register (which should at the end contain the whole word) produces that error. Whats wrong? As far as I understood, the code above should store the byte contained in "$t2" into $t3 + 0" ? Thats at least what definitions and literature say.. and since a character is 1 byte, this should work? But I seem to misunderstand something and would be really happy about any hints or explanations
The error is Exception occured at ...
and then the position of the line with sb $t2, 0($t3)
Then another error with Bad address in data Stack read 0x0000...
It works when I do this:
.data
word: .space 10
.text
main:
la $t1, word
li $t2, 'S'
sb $t2, 0($t1)
li $v0, 10
syscall
But how do I get what I want without declaring something in the data segment? Error seems to appear because I want to store something into the adress $t3 + 0 while $t3 doesnt even have a valid adress
sb $t2, 0($t3)
the code above should store the byte contained in "$t2" into $t3 + 0
That's a bit weird usage of those terms, I'm not sure whether you are just using them in confusing way, or you even understand them wrongly, but I will try to explain what is IMO correct way to describe what this does.
That code line takes value of t2
register, and stores it into computer memory at address t3 + 0
. "storing it into $t3 + 0" description sounds to me like modifying the content of t3
register, which it does NOT.
You can imagine it in head as two distinct chips (HW chips, not food), one being MIPS CPU. This one has 32 general(1) purpose registers, each being 32 bits wide, that's 1024 bits of information, stored directly in the CPU chip. When you use wording "storing into register", I imagine writing the information into one of the slots inside this 1024 bit array on CPU, being "addressed" by register name, like $14
(having alias name $t6
).
The other chip is the memory chip, which has only few transistors dedicated to some "logic" (picking up signals from address and data-bus-wires, and reading/storing value from correct memory bit cells according to the bus state), and 99% of it's transistors/cells are just memory cells storing one bit value (0 or 1, encoded in different electricity current). These are grouped by words (32 together forming single unit), and addressable by bytes (four 8 bit subpart of word element), i.e. each byte has distinct address in the memory chip.
To store value into memory with instruction sb
you have to provide the byte value (the low 8 bits of t2
register in your case), and memory address (whole 32 bits of t3
register used as address value), then the CPU will set t3
content to "address" part of bus, t2
content to "data" part of bus, and signal the memory chip to do "store" operation with those. But you don't provide in your example t3
with any value, so it will address some random computer memory (probably zero address, which is often used as NULL
in higher languages, and thus by default it is often mapped as invalid memory address by the OS), which is off limits to you, and the sb
instruction does crash on writing into illegal part of computer memory.
To remedy you have to specify where in memory you want to store the newly generated data, like you can reserve some space in .data
segment (to have some memory for writing):
.data
word_buffer: .space 1000 # maximum possible word length is 1000 (including terminator value)
# if you will overwrite 1001 bytes, you will overwrite following memory
Then you can set up t3
to contain address of the first of the reserved 1000 bytes as:
la $t3, word_buffer # la = "load address" pseudo instruction
# this will modify the "t3" content on the CPU chip, not memory
When using simulator like MARS/SPIM, you can check after compilation the symbol table to see where in memory the buffer is located, i.e. word_buffer
symbol will have value like 0x00401000
or similar, that's the memory address which will used to modify memory content by sb
instruction (also it means that la
is basically alias of li $t3, 0x00401000
, but using "la" has more readability for anyone reviewing your source about your original intent).
*1) I don't find them completely general-purpose, as $0
aka $zero
will always read as zero (even when you write other value into it), and few more have a bit special implicit usage, like $sp
, but about ~28-29 of them are general and equal in any usage you wish.
EDIT: about your question edit
Still not clear what you mean, as you now realize yourself the t3 + 0
is invalid memory address. So you must either to decide which part of memory you will use:
two common choices are .data
segment, and stack memory, you can also pick up the video memory (MARS simulator has plugin for bitmap display, can be configured to use some shared general memory around $gp
address, which is provided by the MARS "OS"), or you can use "OS" API to reserve some memory dynamically from the "heap" memory reserve the OS is managing.
or you may use the register storage itself (bits stored inside CPU, not in memory), then the answer to your question is simple move $t3, $t2
, which will copy value of t2
into t3
(whole 32 bits).
If you want to operate with bytes only (8 bits) in registers, you have to apply correct masks (by andi
usually, or shifting old values in desired way to make space for new bits), and merge register bits with or
(in some cases also add
and similar may be desirable for value merging, if you know, what you are doing), to build up the 32 bit content of register in a way you desire (like for example having four different 8 bit sub-parts stored in single register).