Thread: Accessing C global variable from assembly file

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    26

    Question Accessing C global variable from assembly file

    Hi all,

    I am trying to access a C variable from an assembly file but I am getting an "undefined reference" error in the assembly file's line in which I am trying to access the variable. I am using GCC and GAS by the way.

    Code:
    test.c
    
    uint8_t test_variable=0;
    extern uint8_t test_variable;
    Code:
    test.S
    
    ...
    ...
    
    movb $0xA5,%al
    movb %al,($test_variable)
    
    ...
    ...
    The error received is the following:
    Code:
    undefined reference to `$test_variable'
    Any help will be really appreciated as I struggle with this for days.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Why do you define the variable then redefine it as extern on the very next line? Most likely the assembler doesn't know where to look...

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    26
    Hi,

    Quote Originally Posted by CommonTater View Post
    Why do you define the variable then redefine it as extern on the very next line? Most likely the assembler doesn't know where to look...
    You're right on that, I was just testing one at a time and accidentally posted them both.

    I tried to use only

    Code:
    uint8_t test_variable=0;
    and then I tried with

    Code:
    extern uint8_t test_variable;
    but still got the same error in both cases...

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    I would start with gcc -S prog.c to see how the assembler actually names (and refers to) global variables.

    Then do the same in your ASM file.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    $ is for constants, isn't it?

    Anyway, to give an idea, I took this source:
    Code:
    int main(void) {
        extern int bob;
        bob = 5;
        return 0;
    }
    compiled it with -S to give assembler, and got back
    Code:
            .file   "ext.c"
            .text
    .globl main
            .type   main, @function
    main:
    .LFB0:
            .cfi_startproc
            pushq   %rbp
            .cfi_def_cfa_offset 16
            movq    %rsp, %rbp
            .cfi_offset 6, -16
            .cfi_def_cfa_register 6
            movl    $5, bob(%rip)
            movl    $0, %eax
            leave
            ret
            .cfi_endproc
    .LFE0:
            .size   main, .-main
            .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
            .section        .note.GNU-stack,"",@progbits
    I have to admit I hadn't heard of RIP until two minutes ago.

  6. #6
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    I really dont like GAS syntax, but...

    Code:
    .globl funcy
    .type funcy, @function
    funcy:
    	push %ebx
    	movl foo, %ebx
    	addl $10, %ebx
    	movl %ebx, foo
    	pop %ebx
    	ret
    Code:
    #include <stdio.h>
    
    int foo;
    
    void funcy();
    
    int main()
    {
    	funcy();
    	printf("foo - %d\n", foo);
    	return 0;
    }
    Build with "gcc -o <whatever_your_app_is_called> <asm_file_name>.S <c_file_name>.c"

  7. #7
    Registered User
    Join Date
    Jun 2009
    Posts
    26
    Hi guys,

    Compiling the following C snippet with gcc -S....

    Code:
    unsigned char test_variable=0;
    
    int main()
    {
      test_variable=0xFF;
      return 0;
    }
    ...gave me that:

    Code:
    	.file	"test_1.c"
    .globl _test_variable
    	.bss
    _test_variable:
    	.space 1
    	.def	___main;	.scl	2;	.type	32;	.endef
    	.text
    .globl _main
    	.def	_main;	.scl	2;	.type	32;	.endef
    _main:
    	leal	4(%esp), %ecx
    	andl	$-16, %esp
    	pushl	-4(%ecx)
    	pushl	%ebp
    	movl	%esp, %ebp
    	pushl	%ecx
    	subl	$4, %esp
    	call	___main
    	movb	$-1, _test_variable
    	movl	$0, %eax
    	addl	$4, %esp
    	popl	%ecx
    	popl	%ebp
    	leal	-4(%ecx), %esp
    	ret
    Does this help at all?

    Thanks.

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    It doesn't help us much. It should, however, help you immensely, what with it literally telling you how to use the name of your variable right there in the output.

    (ETA: And if you want to be extra secure, change your global to an extern (and get rid of the =0 at the end) and see if the assembly is different.)
    Last edited by tabstop; 08-03-2011 at 01:21 PM.

  9. #9
    Registered User
    Join Date
    Jun 2009
    Posts
    26
    Quote Originally Posted by tabstop View Post
    (ETA: And if you want to be extra secure, change your global to an extern (and get rid of the =0 at the end) and see if the assembly is different.)
    Thanks for the advice. I did that and I got:

    Code:
    	.file	"test.c"
    	.def	___main;	.scl	2;	.type	32;	.endef
    	.text
    .globl _main
    	.def	_main;	.scl	2;	.type	32;	.endef
    _main:
    	leal	4(%esp), %ecx
    	andl	$-16, %esp
    	pushl	-4(%ecx)
    	pushl	%ebp
    	movl	%esp, %ebp
    	pushl	%ecx
    	subl	$4, %esp
    	call	___main
    	movb	$-1, _test_variable
    	movl	$0, %eax
    	addl	$4, %esp
    	popl	%ecx
    	popl	%ebp
    	leal	-4(%ecx), %esp
    	ret
    So basically the only difference is that the "test_variable" variable is not declared in the bss but nothing else really...In my assembly code under which section should I declare the "test_variable"?

    Thanks for all the help!

  10. #10
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    Didn't Fordy post a solution for this? Did that not help you?
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by limp View Post
    Thanks for the advice. I did that and I got:

    Code:
    	.file	"test.c"
    	.def	___main;	.scl	2;	.type	32;	.endef
    	.text
    .globl _main
    	.def	_main;	.scl	2;	.type	32;	.endef
    _main:
    	leal	4(%esp), %ecx
    	andl	$-16, %esp
    	pushl	-4(%ecx)
    	pushl	%ebp
    	movl	%esp, %ebp
    	pushl	%ecx
    	subl	$4, %esp
    	call	___main
    	movb	$-1, _test_variable
    	movl	$0, %eax
    	addl	$4, %esp
    	popl	%ecx
    	popl	%ebp
    	leal	-4(%ecx), %esp
    	ret
    So basically the only difference is that the "test_variable" variable is not declared in the bss but nothing else really...In my assembly code under which section should I declare the "test_variable"?

    Thanks for all the help!
    If it's really and truly external, then you shouldn't declare it anywhere I wouldn't think.

  12. #12
    Registered User
    Join Date
    Jun 2009
    Posts
    26
    Hi,

    Quote Originally Posted by tabstop View Post
    If it's really and truly external, then you shouldn't declare it anywhere I wouldn't think.
    The fact that it is external doesn't mean that it is not declared. In fact, "extern" keyword is used only into previously declared variables. If you use "extern" in the definition that it is both defined and declared as external at the same time.

    What I changed compared to the first version for getting the above assembly code is that I put "extern unsigned char test_variable;" in place of "unsigned char test_variable=0;".

    Now, for the generated assembly code I concluded that I need to do something like that:

    Code:
    test.c
    
    uint8_t test_variable=0;

    Code:
    test.s
    
    _test_variable:
    	.byte test_variable
    
    .text
    .code16
    ...
    ...
    
    movb $0xA5,%al
    movb %al,($_test_variable)
    
    ...
    ...
    However this gives me again that:

    Code:
    undefined reference to `$_test_variable'
    and if I try without the "$" I get (although I don't want to write to the address of the "_test_variable" but to the value it points, that's why I use "$"):

    Code:
    relocation truncated to fit: R_386_16 against `.text' (in the "movb %al,(_test_variable)" line)
    Thanks
    Last edited by limp; 08-03-2011 at 02:02 PM.

  13. #13
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    You don't declare it anywhere in your assembly program. Note the difference is the underscore "_" in front of the variable name. My guess is that for GAS you need to identify C variables as _variable. Then just define your C variable in the global namespace of your c program.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by limp View Post
    Hi,



    The fact that it is external doesn't mean that it is not declared. In fact, "extern" keyword is used only into previously declared variables. If you use "extern" in the definition that it is both defined and declared as external at the same time.
    I meant in the assembly file. When you declared it external in your C program and had your compiler write the assembly, where did it declare the variable in the assembler? Nowhere.

    Quote Originally Posted by limp View Post
    What I changed compared to the first version for getting the above assembly code is that I put "extern unsigned char test_variable;" in place of "unsigned char test_variable=0;".

    and if I try without the "$" I get (although I don't want to write to the address of the "_test_variable" but to the value it points, that's why I use "$"):
    I'm not quite sure where you're going with "address of the _test_variable_ but to the value it points". All a variable is, is a piece of memory. You want to take the value 0, and put it in that piece of memory.
    Quote Originally Posted by limp View Post
    Code:
    relocation truncated to fit: R_386_16 against `.text' (in the "movb %al,(_test_variable)" line)
    Thanks
    I think that means you defined _test_variable to be .text.
    Last edited by tabstop; 08-03-2011 at 02:15 PM. Reason: fixed quote

  15. #15
    Registered User
    Join Date
    Jun 2009
    Posts
    26
    Hi,

    Quote Originally Posted by AndrewHunter View Post
    You don't declare it anywhere in your assembly program. Note the difference is the underscore "_" in front of the variable name. My guess is that for GAS you need to identify C variables as _variable. Then just define your C variable in the global namespace of your c program.
    So you mean having something like that?

    Code:
    test.c
    
    uint8_t test_variable=0;
    Code:
    test.s
    
    .extern test_variable
    
    .text
    .code16
    ...
    ...
    
    movb $0xA5,%al
    movb %al,($_test_variable)
    
    ...
    ...
    Because I tried that and it also gave "undefined reference to `$_test_variable"

    Quote Originally Posted by tabstop View Post
    I meant in the assembly file. When you declared it external in your C program and had your compiler write the assembly, where did it declare the variable in the assembler? Nowhere.
    From what I understand is that you're saying that in any case I need to put a ".extern test_variable" in the assembly file, right? Please correct me if I understood it wrong.

    Thank you both guys.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Refering to a global variable in a different object file
    By Canadian0469 in forum C Programming
    Replies: 1
    Last Post: 11-11-2007, 08:53 PM
  2. Global Assembly Cache
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 07-22-2007, 12:08 AM
  3. Initializomg a global variable from a data file
    By cybernike in forum C++ Programming
    Replies: 4
    Last Post: 06-27-2007, 01:07 AM
  4. accessing a variable from another C file
    By cblix in forum C Programming
    Replies: 3
    Last Post: 12-05-2005, 06:16 AM
  5. Static global variable acting as global variable?
    By Visu in forum C Programming
    Replies: 2
    Last Post: 07-20-2004, 08:46 AM