0

I am very new to assembly language, and fairly new to C. I have looked at an example that creates a calls a function from the c code and the assembly code has a function that does the calculation and return the value (This is an assignment) C code:

#include <stdio.h>

int Func(int);

int main() 
{
int Arg;
Arg = 5;
printf("Value returned is %d when %d sent\n",Func(Arg), Arg);
}

Assembly Code:

.global Func
Func:    save  %sp,-800, %sp
add  %i0, -45 , %l0  
mov %l0, %i0 
ret 
restore

It takes the value from the C code, adds the value to the number in the assembly code, and outputs the new number. I understand this instance for the most part. Our assignment (Modifying the code): "Write a C source file that calls Func1 with 2 parameters A and B, and and assembly source file which contains two methods, Func1 and Func2. Have Func1 call Func2 as though it were Func2(Q). Func2 should double its input argument and send that doubled value back to Func1. Func1 should return to the C main the value 2*A + 2*B." I have attempted this, and came out with this solution (Please forgive me I am new to this as of today)

#include <stdio.h>

int Func1(int, int);
void Func2(int, int);
int main() 
{
int Arg1 = 20;
int Arg2 = 4;
printf("Value returned is %d ",Func1(Arg1,Arg2));

}

Assembly:

.global Func1
Func1: save %sp,-800, %sp 
mov %l0, %i0
mov %l1, %i1
call Func2
nop
ret
restore

Func2: save %sp,-800, %sp
umul %i0, 2 , %l0
umul %i1, 2 , %l1
call Func1
nop

It is not working, and I'm not surprised one bit. I'm sure there are many things wrong with this code, but a thorough explanation of what is going on here or what I am doing wrong would really help.

nrz
  • 10,435
  • 4
  • 39
  • 71
Dillon Burton
  • 363
  • 6
  • 16
  • @thelaws yes, worked well and when 5 is given returns me a value of -40 – Dillon Burton Jan 29 '13 at 03:31
  • Assembly, OK, but for what CPU? Could you tag it? – Alexey Frunze Jan 29 '13 at 03:32
  • I'm not positive, all that I know is we are running through the schools SPARC machines via ssh. – Dillon Burton Jan 29 '13 at 03:35
  • What doesn't work about the code? Does it not compile, or not return the correct value? – thelaws Jan 29 '13 at 03:36
  • It gives me this error: Segmentation fault (core dumped) – Dillon Burton Jan 29 '13 at 03:38
  • 2
    You need to know/find the calling conventions for your architecture and, well, some documentation on writing assembly code for it. You could cheat to some extent and use the gcc's `-S` option to convert C code into assembly code and learn something from there. – Alexey Frunze Jan 29 '13 at 03:41
  • Yah I actually tried that. It gave me a pretty crazy code but it's starting to look like that's how i'm going to have to solve this. – Dillon Burton Jan 29 '13 at 03:43
  • 2
    I suggest you to compile with `gcc -Wall -S -fverbose-asm` (and perhaps also some optimization option like `-O2`). The generated `.s` assembly file then contains some helpful generated comments. – Basile Starynkevitch Jan 29 '13 at 06:05
  • Here's a [link](http://www.cs.princeton.edu/courses/archive/spr08/cos217/reading/ProgrammingGroundUp-1-0-lettersize.pdf) to a fantastic book that goes into great details about computer architecture and how to write assembly. Although this talks about the x86 architecture it could give you some pointers that you need to adapt to the SPARC architecture. – dinesh Jan 29 '13 at 06:37

2 Answers2

1

Do I see this correctly:

In Func1, you call Func2
   which calls Func1 again
      which calls Func2 again
         which calls Func1 again
             which calls Func2 again
                 ...
Stack overflow, resulting in bad memory access and segmentation fault

Obviously, don't do that :). What do you want to do, exactly? Return result of multiplication from Func2? Then return it, just like you return result of addition from Func1.

Then the assignment clearly says:

call Func2 as though it were Func2(Q). Func2 should double its input argument and send that doubled value back

So why do you give Func2 two arguments? If we assume valid assignment, then you can work on it small pieces, like this piece I quoted. It says Func2 needs 1 argument, so trust that and make Func2 with one argument, and you have one piece of assigment done (then if it turns out assignemnt is invalid or tries to trick you, you need to get back to it, of course, but above is pretty clear).


But to help you, you have working code, right?

.global Func
Func:    save  %sp,-800, %sp
add  %i0, -45 , %l0  
mov %l0, %i0 
ret 
restore

And for Func2, you need to change that code so it multiplies by two, instead of adding -45? Have you tried changing the add instruction to:

imul  %i0, 2 , %l0  

(or umul, but in your C code you specify int and not unsigned int, so I presume it is signed...).


I'm not going to write your Func1 for you, but you see how you get your inputs, which I assume is right. Then you need to produce result in %i0 before returning. Work in small steps: first make Func1 which returns just %i0 + %i1 without calling Func2 at all. Then try 2 * %i0 + %i1, calling Func2 once. Then finally write requested version of 2 * %i0 + 2 * %i1 calling Func2 twice (or for less and simpler code, extract the common factor so you still need to call Func2 just once).

hyde
  • 60,639
  • 21
  • 115
  • 176
1

To pass the value to back to func1, func2 shouldn't be calling func1 again. Have function return a value to func1. A function's return value should be saved in register i0, which is the ABI for most processors.

  1. main calls func1 with value
  2. func1 reads the argument form i0
  3. func1 calls func2 with argument in i0
  4. func2 multiplies the argument and saves in %l0
  5. Move the value back to i0 and return
Santosh
  • 799
  • 7
  • 14