0

I am trying copy some words from memory and saving it to another memory address using assembly. I am trying to write the code for it but I am not sure about some of the parts. I will briefly describe what I want to do.

The source address, destination address and the number of words to copy are input arguments of the function.

Nitesh
  • 2,286
  • 2
  • 43
  • 65
Bic B
  • 201
  • 2
  • 6
  • 18
  • So sorry to bother you guys. I appreciate all the help I am getting xx – Bic B Aug 02 '12 at 09:20
  • For the Exception 4 you're getting, see the EDIT I made to my answer. – Michael Aug 02 '12 at 09:34
  • @Michael check my comment below your answer please xx – Bic B Aug 02 '12 at 09:42
  • From which address are you executing the code? Also, it would help to know which exact line is causing the exception. – Michael Aug 02 '12 at 09:50
  • I am using PCSpim to run the code. All I do is click the run button and then a small pop-up window comes up asking for starting address in which I put in 0x00400000 and error occurs so I try different addresses, even 0x10000000 and over. When I do that then the error I get is Exception 6 – Bic B Aug 02 '12 at 10:01
  • The console prints out Exception 4 and exception 6 at runtime. The program compiles is what I tried to say! sorry – Bic B Aug 02 '12 at 10:05
  • You've got two consecutive branch instructions in your code; `J` and `JR`. The behaviour of that is undefined. It's possible that your assembler is reordering the instructions for you, but to be sure you should move the `SUB` instruction into the delay slot (i.e. right after the `J` instruction). – Michael Aug 02 '12 at 11:27
  • @Michael I tried that too but its still giving exception 4 unaligned addresses – Bic B Aug 03 '12 at 01:04

2 Answers2

0

From your description it sounds like a regular memcpy, except that you specify the number of words to copy rather than the number of bytes. Not sure where the whole stack buffer idea comes from(?).

Something like this would copy the words from the source to the destination address:

sll $a2,$a2,2
addu $a2,$a1,$a2  ; $a2 = address of first byte past the dest buffer
Loop:
    lw $t0,0($a0)
    sw $t0,0($a1)
    addiu $a0,$a0,4
    addiu $a1,$a1,4
    bne $a1,$a2,Loop
    nop

EDIT: If your source and destination buffers are not aligned on word boundaries you need to use lb/sb instead to avoid data alignment exceptions.

Michael
  • 57,169
  • 9
  • 80
  • 125
  • NOP = No Operation. It does nothing (technically it's implemented as SLL $0,$0,0). MIPS uses delayed branching - which means that the instruction following the branch is executed before the branch is actually taken - so to avoid having an instruction there that could risk messing up the copy loop I put a NOP there. – Michael Aug 02 '12 at 08:54
  • Hi, both the codes are giving me Arithmetic error at memory addresses. I am uploading the code in my question area so please have a look and tell me if I have done something wrong. – Bic B Aug 02 '12 at 09:00
  • Hi Mic xx so if I use lb and sb, would the addition operations be as follows: addiu $a0,$a0,1 and addiu $a1,$a1,1 – Bic B Aug 02 '12 at 09:41
  • Oh I tried sb and lb with both the addition operations and still gives the same error – Bic B Aug 02 '12 at 09:43
  • =( I am sorry to be such a hassle – Bic B Aug 02 '12 at 09:48
0

EDIT: added nops after branches

So think about how you would do this in C...At a low level.

unsigned int *src,*dst;
unsigned int len;
unsigned int temp;
...
//assume *src, and *dst and len are filled in by this point
top:
  temp=*src;
  *dst=temp;
  src++;
  dst++;
  len--;
  if(len) goto top;

you are mixing too many things, focus on one plan. First off you said you had a source and destination address in two registers, why is the stack involved? you are not copying or using the stack, you are using the two addresses.

it is correct to multiply by 4 to get the number of bytes, but if you copy one word at a time you dont need to count bytes, just words. This is assuming the source and destination addresses are aligned and or you dont have to be aligned. (if unaligned then do everything a byte at a time).

so what does this look like in assembly, you can convert to mips, this is pseudocode: rs is the source register $a0, rd is the destination register $a1 and rx is the length register $a2, rt the temp register. Now if you want to load a word from memory use the load word (lw) instruction, if you want to load a byte do an lb (load byte).

top:
branch_if_equal rx,0,done
nop
load_word rt,(rs)
store_word rt,(rd)
add rs,rs,4
add rd,rd,4
subtract rx,rx,1
branch top
nop
done:

Now if you copy bytes at a time instead of words then

shift_left rx,2
top:
branch_if_equal rx,0,done
nop
load_byte rt,(rs)
store_byte rt,(rd)
add rs,rs,1
add rd,rd,1
subtract rx,rx,1
branch top
nop
done:
old_timer
  • 69,149
  • 8
  • 89
  • 168
  • Thanks, let me try and implement that in MIPS, will accept your answer if it works – Bic B Aug 02 '12 at 08:47
  • Hi, both the codes are giving me Arithmetic error at memory addresses. I am uploading the code in my question area so please have a look and tell me if I have done something wrong. – Bic B Aug 02 '12 at 09:00
  • for now, for every branch or jump in mips put a nop after, the instruction after the branch is executed. Until you hand tune the code put a nop. If using gnu assembler you probably need something like .set_reorder or some such directive, otherwise the assembler swaps the branch with the instruction before it when assembling, or worse, to get it to do what you tell it to do gnu assembler requires a directive. – old_timer Aug 02 '12 at 13:54
  • I am not sure how to do that yet =( we have not been taught that in class – Bic B Aug 03 '12 at 01:04
  • We learnt branch yesterday but i dont know what you mean when u want me to include .set_reorder – Bic B Aug 03 '12 at 23:07
  • http://stackoverflow.com/questions/3807480/weird-mips-assembler-behavior-with-jump-and-link-instruction – old_timer Aug 04 '12 at 03:57