1

I have main function in C that runs code in assembly. I just want to make simple sum:

main.c

#include <stdio.h>

extern int addByAssembly(int first_number, int second_number);

int main (int argc, char **argv)
{
    int sum=0;
    sum = addByAssembly(5,4);
    printf ("%d\n",sum);
    return 0;
}

addByAssembly.s

.data
SYSREAD = 0
SYSWRITE = 1
SYSEXIT = 60
STDOUT = 1
STDIN = 0
EXIT_SUCCESS = 0

.text
#.global main
#main:
#call write
#movq $SYSEXIT, %rax
#movq $EXIT_SUCCESS, %rdi
#syscall

#********
.globl addByAssembly
addByAssembly:
pushq %rbp
movq %rsp, %rbp
movq 16(%rsp), %rax
addq 24(%rsp), %rax

movq %rbp, %rsp
popq %rbp

But i got mess in my sum. It looks like i badly pass arguments, beause if I do this:

movq $123, %rax

return value is 123. I 've tried many ways, but cannot find how to make this properly to sum.

old_timer
  • 69,149
  • 8
  • 89
  • 168
user2678074
  • 768
  • 3
  • 9
  • 22
  • Have you tried stepping through with a debugger to verify that you are, in fact, capturing the arguments properly? – David Hoelzer Apr 13 '16 at 22:17
  • 3
    Did you read, understood and follow the ABI? I don't think the arguments are passed on the stack. In general, better use inline-assembler. – too honest for this site Apr 13 '16 at 22:20
  • Well, i didn't. There is barely any information in my language about it, and articses in english are, well, heavly technic. I assume that passing int from C to registry is smth i am doing wrong, but i don't know what it should be proper. I've found none example, so i am asking here. – user2678074 Apr 13 '16 at 22:26
  • in 32bit ass, int is just passed to registry 1:1, i don't know how to pass 64bit int :/ Unless it's not the issue here. – user2678074 Apr 13 '16 at 22:28
  • 2
    We can only explain it to you in english too. See also [wikipedia](https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI). TL;DR: you get the first argument in `rdi` the second in `rsi`. So all you need is `lea (%rdi, %rsi), %rax; ret`. Actually `int` is still 32 bit so you can use the 32 bit registers. – Jester Apr 13 '16 at 22:29
  • This I missed! I dodn't know, that arguments are passed to those registers! But what if I need to pass more arguments? List/string? – user2678074 Apr 13 '16 at 22:37
  • See the linked wikipedia and the ABI docs for all the registers used. Sorry, you will have to learn english. A string is a pointer, and is passed as usual. – Jester Apr 13 '16 at 22:42
  • Well, I see, that next parameter goes to rdx and so on. But if i try to add third parameter, it goes nuts. I don't understand this.Can you also show me, on example how to pass string? I know it's not very fair, but i really want to know, and example would be really helpfull. – user2678074 Apr 13 '16 at 22:55
  • Depends on what you want to do with the string. You will get the pointer in `rdx` as you say. – Jester Apr 13 '16 at 22:56
  • But in case i added third int and switched your line to "movq %rdx, %rax" - result is wrong! In 2nd case i want to pass string, and just print it to console. I promise, that is all I will be bothering you. I just cannot understand. If i knew how, to make this two, that'd be awesome! – user2678074 Apr 13 '16 at 23:04
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/109093/discussion-between-jester-and-user2678074). – Jester Apr 13 '16 at 23:07
  • 1
    Look under "Calling Conventions" in this article, [Introduction to x64 Assembly](https://software.intel.com/en-us/articles/introduction-to-x64-assembly). – lurker Apr 14 '16 at 01:20
  • http://stackoverflow.com/questions/2535989/what-are-the-calling-conventions-for-unix-linux-system-calls-on-x86-64 – Pierre Apr 14 '16 at 09:34

1 Answers1

1

Thanks 'Jester' for so much effort and time to get me this explained!

To sum up. Passing parameters from C to As ( and as well from As to C) has its own ABI convention. As you can see there, params are send on order: 1) rdi 2) rsi 3) rdx ... and so on...

In case you have more parameters than in convention, it will be pushed to stack.

So in my case:

.globl addByAssembly
addByAssembly:
pushq %rbp
movq %rsp, %rbp
--movq 16(%rsp), %rax    #this was wrong as my params are
--addq 24(%rsp), %rax    # first in %rdi, second in %rsi
++lea (%rdi, %rsi), %rax # in my case this line will do 
                         # %rdi+%rsi -> %rax (learn lea, usefull command)
                         # REMEMBER return value is always in %rax!
movq %rbp, %rsp
popq %rbp
user2678074
  • 768
  • 3
  • 9
  • 22