2

This is my C code:

#include <stdio.h>

    void sum();
    int newAlphabet;
    int main(void)
    {
        sum();
        printf("%d\n",newAlphabet);
    }

And this is my assembler code:

.globl _sum

_sum:
    movq $1, %rax
    movq %rax, _newAlphabet
    ret

I'm trying to call the sum function, from my main function, to set newAlphabet equal to 1, but when I compile it (gcc -o test assembler.c assembler.s, compiled on a 64-bit OSX laptop) I get the following errors:

32-bit absolute addressing is not supported for x86-64

cannot do signed 4 byte relocation

both caused by the line "movq %rax, _newAlphabet"

I'm sure I'm making a very basic mistake. Can anyone help? Thanks in advance.

EDIT:

Here are the relevant portions of the C code once it has been translated to assembler:

.comm   _newAlphabet,4,2
...
movq    _newAlphabet@GOTPCREL(%rip), %rax
7
  • 2
    Where is the declaration of _newAlphabet in the assembler? Also, I'm pretty sure that int is 32-bits on OSX (even in x86-64). Commented Dec 13, 2014 at 22:49
  • I was under the possibly mistaken impression that the int newAlphabet from the c code would be recognized by the assembler. If this is wrong, how do I need to go about fixing that? And should i use movl instead? Commented Dec 13, 2014 at 22:51
  • I get the same errors, if I use movl or mov with %eax Commented Dec 13, 2014 at 23:01
  • @SimonMeans: What if you try newAlphabet (i.e. without underscore)? If this does not help I would advice to compile some simple program that use this external variable with -S option to see its assembly instructions (that is, to recognize how this variable is referenced). Commented Dec 13, 2014 at 23:04
  • 1
    See stackoverflow.com/questions/25799551/… I think it may answer your issue with mov instruction (seems to be duplicate of it if I am reading correctly). Commented Dec 13, 2014 at 23:16

1 Answer 1

5

Mac OS X uses position-independent executables by default, which means your code can't use constant global addresses for variables. Instead you'll need to access globals in an IP-relative way. Just change:

movq %rax, _newAlphabet

to:

mov %eax, _newAlphabet(%rip)

and you'll be set (I changed from 64 to 32 bit registers to match sizeof(int) on Mac OS X. Note that you also need a .globl _newAlphabet in there somewhere. Here's an example I just made based on your code (note that I initialized newAlphabet to prove it works):

example.c:

#include <stdio.h>

void sum(void);
int newAlphabet = 2;
int main(void)
{
    printf("%d\n",newAlphabet);
    sum();
    printf("%d\n",newAlphabet);
    return 0;
}

assembly.s:

.globl _sum
.globl _newAlphabet

_sum:
    movl $1, _newAlphabet(%rip)
    ret

Build & run:

$ cc -c -o example.o example.c
$ cc -c -o assembly.o assembly.s
$ cc -o example example.o assembly.o
$ ./example
2
1
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.