OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 4:40 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Accessing a extern declared variable in assembly file
PostPosted: Thu Jun 08, 2017 5:34 am 
Offline
Member
Member

Joined: Sat Apr 29, 2017 6:56 am
Posts: 26
Hello

I am trying to access a variable declared in .c file from .S file . Pls look at the following code .

Assembly File (NASM)
bits 32

global print
extern a
segment .text
print:
mov dword[a],10

ret

C File
extern void print();
extern int a;
void kern() {

int a;

print();

}

The following complied with -S of main.c, no extern a was @ .globl , so the erro was
main.c: In function 'kern':
main.c:5:9: warning: unused variable 'a' [-Wunused-variable]
int a;
^
i686-elf-gcc -T linker.ld -o run -ffreestanding -O2 -nostdlib main.o asm.o -lgcc
asm.o: In function `print':
asm.S:(.text+0x2): undefined reference to `a'
collect2: error: ld returned 1 exit status
Makefile:8: recipe for target 'elf' failed
make: *** [elf] Error 1


.file "main.c"
.text
.globl kern
.type kern, @function
kern:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $8, %esp
call print
nop
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size kern, .-kern
.ident "GCC: (GNU) 7.1.0"


Top
 Profile  
 
 Post subject: Re: Accessing a extern declared variable in assembly file
PostPosted: Thu Jun 08, 2017 6:22 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
Try putting an underscore before the variable name (in the assembler file).


Top
 Profile  
 
 Post subject: Re: Accessing a extern declared variable in assembly file
PostPosted: Thu Jun 08, 2017 6:24 am 
Offline

Joined: Sat Feb 22, 2014 6:42 am
Posts: 5
1. By declaring a variable as extern, you tell the compiler that the variable is defined in a separate module. You may either want to remove the extern keyword or define the variable in the assembly file.

Code:
segment .data
global a
a:
    dd 0


(or something like that, it's been a while since I've used nasm).

2. By defining your variable inside function kern() you actually do not define the global variable a but instead a whole new local variable a, which is only valid within the scope of kern().


Top
 Profile  
 
 Post subject: Re: Accessing a extern declared variable in assembly file
PostPosted: Thu Jun 08, 2017 6:39 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
Oops! I didn't notice that a was declared inside a function. No wonder it's not visible to the assembler file.


Top
 Profile  
 
 Post subject: Re: Accessing a extern declared variable in assembly file
PostPosted: Fri Jun 09, 2017 11:12 pm 
Offline
Member
Member
User avatar

Joined: Sun Oct 18, 2009 5:47 pm
Posts: 208
Location: Alexandria, Egypt | Ottawa, Canada
yerri07 wrote:
Hello

I am trying to access a variable declared in .c file from .S file . Pls look at the following code .

Assembly File (NASM)
bits 32

global print
extern a
segment .text
print:
mov dword[a],10

ret

C File
extern void print();
extern int a;
void kern() {

int a;

print();

}

The following complied with -S of main.c, no extern a was @ .globl , so the erro was
main.c: In function 'kern':
main.c:5:9: warning: unused variable 'a' [-Wunused-variable]
int a;
^
i686-elf-gcc -T linker.ld -o run -ffreestanding -O2 -nostdlib main.o asm.o -lgcc
asm.o: In function `print':
asm.S:(.text+0x2): undefined reference to `a'
collect2: error: ld returned 1 exit status
Makefile:8: recipe for target 'elf' failed
make: *** [elf] Error 1


.file "main.c"
.text
.globl kern
.type kern, @function
kern:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $8, %esp
call print
nop
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size kern, .-kern
.ident "GCC: (GNU) 7.1.0"

There is a difference between declaration and definition. This big difference is not clear enough to novice C programmers, and that's why I had to invent a new programming language with more meaningful keywords and unified behavior for language constructs.

If C tends to give the programmer more details about how it works, then it needs to be more 'explicit'. The word 'extern' might be meaningful in this context, but it doesn't actually tell you how the compiler would process it. You just found it somewhere on the internet and you thought that it helps you make your variable shared among various components. Why? because the word is misleading. You just thought that it is simply a keyword that tells more information about the storage class of the type (like static). Here is the pitfall: static is a 'definition', while extern is just a 'declaration'.

Both 'static' and 'extern' belong to a class of C keywords called 'storage-class specifiers'. 'typedef', 'register', and 'auto' also belong to the same class. However, 'extern' is the only one of them that is just declarative and is not considered as definition. I don't like this kind of non-uniformity. It is not cool.

OK So what is the difference between declaration and definition?

TFM wrote:
3.5 DECLARATIONS

Syntax

declaration:
declaration-specifiers init-declarator-list<opt> ;

declaration-specifiers:
storage-class-specifier declaration-specifiers<opt>
type-specifier declaration-specifiers<opt>
type-qualifier declaration-specifiers<opt>

init-declarator-list:
init-declarator
init-declarator-list , init-declarator

init-declarator:
declarator
declarator = initializer

Constraints

A declaration shall declare at least a declarator, a tag, or the
members of an enumeration.

If an identifier has no linkage, there shall be no more than one
declaration of the identifier (in a declarator or type specifier) with
the same scope and in the same name space, except for tags as
specified in $3.5.2.3.

All declarations in the same scope that refer to the same object or
function shall specify compatible types.

Semantics

A declaration specifies the interpretation and attributes of a set
of identifiers
. A declaration that also causes storage to be reserved
for an object or function named by an identifier is a definition
./47/

The declaration specifiers consist of a sequence of specifiers that
indicate the linkage, storage duration, and part of the type of the
entities that the declarators denote. The init-declarator-list is a
comma-separated sequence of declarators, each of which may have
additional type information, or an initializer, or both. The
declarators contain the identifiers (if any) being declared.

If an identifier for an object is declared with no linkage, the
type for the object shall be complete by the end of its declarator, or
by the end of its init-declarator if it has an initializer.

Forward references: declarators ($3.5.4), enumeration specifiers
($3.5.2.2), initialization ($3.5.7), tags ($3.5.2.3).


3.5.1 Storage-class specifiers

Syntax

storage-class-specifier:
typedef
extern
static
auto
register

Constraints

At most one storage-class specifier may be given in the declaration
specifiers in a declaration./48/

Semantics

The typedef specifier is called a ``storage-class specifier'' for
syntactic convenience only; it is discussed in $3.5.6. The meanings
of the various linkages and storage durations were discussed in
$3.1.2.2 and $3.1.2.4.

A declaration of an identifier for an object with storage-class
specifier register suggests that access to the object be as fast as
possible. The extent to which such suggestions are effective is
implementation-defined./49/

The declaration of an identifier for a function that has block
scope shall have no explicit storage-class specifier other than extern.

Forward references: type definitions ($3.5.6).


So here is 3.1.2.2:
Quote:
3.1.2.2 Linkages of identifiers

An identifier declared in different scopes or in the same scope
more than once can be made to refer to the same object or function by
a process called linkage . There are three kinds of linkage: external,
internal, and none.

In the set of translation units and libraries that constitutes an
entire program, each instance of a particular identifier with external
linkage denotes the same object or function. Within one translation
unit, each instance of an identifier with internal linkage denotes the
same object or function. Identifiers with no linkage denote unique
entities.

If the declaration of an identifier for an object or a function has
file scope and contains the storage-class specifier static, the
identifier has internal linkage.

If the declaration of an identifier for an object or a function
contains the storage-class specifier extern , the identifier has the
same linkage as any visible declaration of the identifier with file
scope. If there is no visible declaration with file scope, the
identifier has external linkage.


If the declaration of an identifier for a function has no
storage-class specifier, its linkage is determined exactly as if it
were declared with the storage-class specifier extern . If the
declaration of an identifier for an object has file scope and no
storage-class specifier, its linkage is external.

The following identifiers have no linkage: an identifier declared
to be anything other than an object or a function; an identifier
declared to be a function parameter; an identifier declared to be an
object inside a block without the storage-class specifier extern.

If, within a translation unit, the same identifier appears with
both internal and external linkage, the behavior is undefined.

Forward references: compound statement, or block ($3.6.2),
declarations ($3.5), expressions ($3.3), external definitions ($3.7).

So we jump to 3.7:
Quote:
3.7 EXTERNAL DEFINITIONS

Syntax

translation-unit:
external-declaration
translation-unit external-declaration

external-declaration:
function-definition
declaration

Constraints

The storage-class specifiers auto and register shall not appear in
the declaration specifiers in an external declaration.

There shall be no more than one external definition for each
identifier declared with internal linkage in a translation unit.
Moreover, if an identifier declared with internal linkage is used in
an expression (other than as a part of the operand of a sizeof
operator), there shall be exactly one external definition for the
identifier in the translation unit.

Semantics

As discussed in $2.1.1.1, the unit of program text after
preprocessing is a translation unit, which consists of a sequence of
external declarations. These are described as ``external'' because
they appear outside any function (and hence have file scope). As
discussed in $3.5, a declaration that also causes storage to be
reserved for an object or a function named by the identifier is a
definition.




This simply means that the term 'externa declarationl' means 'a declaration that is external to function scope', while the term 'external linkage' means 'a variable which is linked through the entire translation units of the program'

Wikipedia wrote:
In the C programming language, an external variable is a variable defined outside any function block. On the other hand, a local (automatic) variable is a variable defined inside a function block.


Wikipedia wrote:
To understand how external variables relate to the extern keyword, it is necessary to know the difference between defining and declaring a variable. When a variable is defined, the compiler allocates memory for that variable and possibly also initializes its contents to some value. When a variable is declared, the compiler requires that the variable be defined elsewhere. The declaration informs the compiler that a variable by that name and type exists, but the compiler does not need to allocate memory for it since it is allocated elsewhere. The extern keyword means "declare without defining". In other words, it is a way to explicitly declare a variable, or to force a declaration without a definition. It is also possible to explicitly define a variable, i.e. to force a definition. It is done by assigning an initialization value to a variable. If neither the extern keyword nor an initialization value are present, the statement can be either a declaration or a definition. It is up to the compiler to analyse the modules of the program and decide.

A variable must be defined exactly once in one of the modules of the program. If there is no definition or more than one, an error is produced, possibly in the linking stage. A variable may be declared many times, as long as the declarations are consistent with each other and with the definition (something which header files facilitate greatly). It may be declared in many modules, including the module where it was defined, and even many times in the same module. But it is usually pointless to declare it more than once in a module.

An external variable may also be declared inside a function. In this case the extern keyword must be used, otherwise the compiler will consider it a definition of a local (automatic) variable, which has a different scope, lifetime and initial value. This declaration will only be visible inside the function instead of throughout the function's module.

The extern keyword applied to a function prototype does absolutely nothing (the extern keyword applied to a function definition is, of course, non-sensical). A function prototype is always a declaration and never a definition. Also, in standard C, a function is always external, but some compiler extensions allow a function to be defined inside a function.



Now back to the manual:

Code:
   An external definition is an external declaration that is also a
definition of a function or an object.  If an identifier declared with
external linkage is used in an expression (other than as part of the
operand of a sizeof operator), somewhere in the entire program there
shall be exactly one external definition for the identifier./69/

Simply put. If I write something like (int x;) outside a function block, it is an external tentative definition. The misleading 'extern' keywords forces the compiler to deal with it as a declaration statement. I don't know what "/69/" refers to at the end of text.


Top
 Profile  
 
 Post subject: Re: Accessing a extern declared variable in assembly file
PostPosted: Fri Jun 09, 2017 11:53 pm 
Offline
Member
Member

Joined: Wed Jul 10, 2013 9:11 am
Posts: 51
Quote:
Simply put. If I write something like (int x;) outside a function block, it is an external tentative definition.


An "external tentative definition" is an oxymoron. See 6.9.2/2:

Quote:
A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.


In short:

- A tentative definition can either have the static or no storage-class specifier (this excludes extern)
- It can either have internal or external linkage
- It can act like a declaration (if no external definition exists)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 87 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group