External variables

  • Follow


Environment: linux, gcc + nasm.

I have an asm file containing a global data label, eg (NASM syntax):

section .data
global my_data
.....
my_data: times 8 dd 0


So, the label "my_data" identifies a 32 byte (8 * 4) memory area.

I have a C file where I want to use this data, so I did:

.....
extern unsigned int *my_data;
.....

and thought I could legally do (in C)

my_data[0] = 33;
my_data[5] = 44;
etc.

But this results in a segfault.
Instead, if I put this in the C file:

extern unsigned int my_data[8];

everything works fine.
After a few tests, it turns out that, if my_data is declared as a
pointer, it is actually a nil pointer, so --> segfault.
But, shouldn't it point to the actual 32-byte memory area of the asm
file?

Another question that seems to be related: if I have in the asm file

global int_var
int_var: dd 5

in the C file I have to declare it as

extern int int_var;

and not as

extern int *int_var;  /* segfaults when used */

In both cases (and in the previous one also), the compiler never
complains.

So, do I have to deduce that an external data label (that, after all,
_is_ a pointer, since it represents a memory address) can never be
treated like a pointer?

Maybe this is a newbie question, but, since this is the first time I
try to link together asm and C files, I never had this issue before.

Thanks

0
Reply sunglo 2/17/2004 10:49:38 PM

On Tue, 17 Feb 2004 22:49:38 +0000 (UTC), sunglo@katamail.com (subnet)
wrote in comp.lang.asm.x86:

> Environment: linux, gcc + nasm.
> 
> I have an asm file containing a global data label, eg (NASM syntax):
> 
> section .data
> global my_data
> ....
> my_data: times 8 dd 0
> 
> 
> So, the label "my_data" identifies a 32 byte (8 * 4) memory area.

Yes, my_data is an ARRAY of 32 8-bit character types, or 16 16-bit
short int types, or 8 32-bit int or long int types.  It is an ARRAY.

> I have a C file where I want to use this data, so I did:
> 
> ....
> extern unsigned int *my_data;

But my_data is not a pointer to int.  It is an ARRAY.  An array is not
a pointer, a pointer is not an array.  In many circumstances in C,
when you use the name of an array in an expression it gets converted
to a pointer, but an ARRAY IS NOT A POINTER.

> ....
> 
> and thought I could legally do (in C)
> 
> my_data[0] = 33;
> my_data[5] = 44;
> etc.
> 
> But this results in a segfault.
> Instead, if I put this in the C file:
> 
> extern unsigned int my_data[8];
> 
> everything works fine.
> After a few tests, it turns out that, if my_data is declared as a
> pointer, it is actually a nil pointer, so --> segfault.
> But, shouldn't it point to the actual 32-byte memory area of the asm
> file?

No, because an array is not a pointer, it does not point to anything.

> Another question that seems to be related: if I have in the asm file
> 
> global int_var
> int_var: dd 5
> 
> in the C file I have to declare it as
> 
> extern int int_var;
> 
> and not as
> 
> extern int *int_var;  /* segfaults when used */
> 
> In both cases (and in the previous one also), the compiler never
> complains.
> 
> So, do I have to deduce that an external data label (that, after all,
> _is_ a pointer, since it represents a memory address) can never be
> treated like a pointer?

An external data label is NOT a pointer, it is an address.  If you put
the address of something in a variable type designed to store
addresses, it becomes a pointer.

> Maybe this is a newbie question, but, since this is the first time I
> try to link together asm and C files, I never had this issue before.
> 
> Thanks

Your problem is not about linking assembly language with C, it is a
misunderstanding of C pointers and arrays.  See the FAQ for
comp.lang.c, especially section 6, which is all about pointers and
arrays.

http://www.eskimo.com/~scs/C-faq/s6.html

The very first question will show you that you can have the same
misunderstanding, and write the same incorrect code, entirely in C
without needing assembly language at all.

-- 
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

0
Reply Jack 2/18/2004 2:09:10 AM


> Environment: linux, gcc + nasm.
> 
> I have an asm file containing a global data label, eg (NASM syntax):
> 
> section .data
> global my_data
> ....
> my_data: times 8 dd 0
> 
> I have a C file where I want to use this data, so I did:
> 
> extern unsigned int *my_data;

This is indeed wrong.

> and thought I could legally do (in C)
> 
> my_data[0] = 33;
> my_data[5] = 44;
> etc.
> 
> But this results in a segfault.

Lots of things are legal in C :-)

> Instead, if I put this in the C file:
> 
> extern unsigned int my_data[8];
> 
> everything works fine.
> After a few tests, it turns out that, if my_data is declared as a
> pointer, it is actually a nil pointer, so --> segfault.
> But, shouldn't it point to the actual 32-byte memory area of the asm
> file?

my_data is a symbol, which has an associated address in the data 
section. At that address, you will find the 8 zeros. When you write 
extern unsigned int my_data[8], you tell the compiler that there is 
already a symbol my_data addressing 8 ints defined elsewhere, and you 
are going to use that symbol. This means the C compiler will not 
generate a new symbol, and reserve no space. If you write extern 
unsigned int *my_data, you tell the compiler that there is a symbol 
my_data elsewhere, which addresses an int * that has been defined. The 
names of variables in C are themselves pointers, and the values of those 
pointers are what you get with the & operator.

> Another question that seems to be related: if I have in the asm file
> 
> global int_var
> int_var: dd 5
> 
> in the C file I have to declare it as
> 
> extern int int_var;
> 
> and not as
> 
> extern int *int_var;  /* segfaults when used */

You have to declare it as extern int, because it is an external integer. 
You have, in your assembly file, created an integer and called it 
int_var. extern int int_var tells the compiler that you want to use an 
int int_var, but it has been created somewhere else, so the compiler 
need not bother to create it again. If you put extern int *int_var 
instead, the int *int_var will contain 5 as specified in your assembly, 
and if you dereference 5 you are likely to segfault. This is equivalent 
to doing *(int *)5.

> In both cases (and in the previous one also), the compiler never
> complains.

The compiler has nothing to complain about. You have just told it that 
there is no need to generate space and a symbol for int_var, so it 
doesn't, and it's perfectly happy with that.

> So, do I have to deduce that an external data label (that, after all,
> _is_ a pointer, since it represents a memory address) can never be
> treated like a pointer?

If you like to call a variable in an external assembly file a pointer, 
you should also call the variables in your C file pointers. The names 
all have associated addresses, but in assembly the address is more 
clearly used as a value than in C, where you must use the & operator to 
get it. The value of the int int_var in C is the value of [int_var] in 
assembly. That this is an int is something you have to make sure of 
yourself in assembly though.

> Maybe this is a newbie question, but, since this is the first time I
> try to link together asm and C files, I never had this issue before.

This is a newbie question, but one that is quite understandable. It is 
just a matter of seeing how the pieces come together and what a C 
program actually represents, and this can be hard even for a good 
programmer. Remember that it is by asking questions that you get answers.


-- 
Remove the furry animal from my address to send email:

   bjarni.ferret@update.ferret.uu.se

0
Reply Bjarni 2/18/2004 3:31:49 AM

Ok, thanks Jack and Bjarni, very clear now.
The FAQ are very good and comprehensive, I read them all.
But, while the case in section 6.1 of the FAQ is very obvious and
easily understood, since arrays are not pointers (yes I know that),
and I could never did that mistake in straight C, I never used them in
asm, so I didn't notice the difference.
What got me wrong is maybe code like the following

in C
----------------------------
void my_function(char *str)
{ .. do something with str .. }
----------------------------
and in asm
----------------------------
msg: db "Hello", 0
......
extern my_function
....
push msg
call my_function
-----------------------------

This code actually works, but not because "msg" is a pointer to char
(as I erroneously thought), but (if I understood correctly) because
it's an array of chars and, in function formal arguments, arrays can
be substituted by pointers.

To summarize (assuming that both ints and pointers are 4 bytes wide):

if I do (in asm)
-----------------------
global var
var:    dd 0
-----------------------

in C I can do:

extern int var

and treat var like an int,

or 

extern int *var

and treat var like a pointer (and it will be an invalid nil pointer at
the beginning, since it contains 0).

Similarly, if the label identifies some larger area (say, 32 bytes):

var:  times 8 dd 0

I can say

extern int var[8];
extern short int var[16];
extern char var[32];

and go as usual with arrays, or

extern <some data type> *var; 

But in the latter case I'm really working only with the first 4 bytes
of the area identified by var, and, for the same reason as before,
this will be a nil pointer, and chances are this is probably not what
I intended anyway, or, even worse, I can do

extern <some data type> *var[8];

and I'll end up with an array of 8 nil pointers (like before, probably
wrong).

I think this is correct now, because it makes sense.

Thanks again.

0
Reply sunglo 2/19/2004 9:26:24 AM

> Ok, thanks Jack and Bjarni, very clear now.

Ah! A job well done. Time to sleep now.

[...]
> var:  times 8 dd 0
> 
> I can say
> 
> extern int var[8];
> extern short int var[16];
> extern char var[32];
> 
> and go as usual with arrays, or
> 
> extern <some data type> *var; 
[...]
> I think this is correct now, because it makes sense.

It does seem to make a whole lot of sense.


-- 
Remove the furry animal from my address to send email:

   bjarni.ferret@update.ferret.uu.se

0
Reply Bjarni 2/21/2004 7:12:03 PM

Bjarni Juliusson <bjarni.ferret@update.ferret.uu.se> writes:

> > Ok, thanks Jack and Bjarni, very clear now.
> 
> Ah! A job well done. Time to sleep now.
> 
> [...]
> > var:  times 8 dd 0
> > I can say
> > extern int var[8];
> > extern short int var[16];
> > extern char var[32];
> > and go as usual with arrays, or

Yup, yup, yup,

> > extern <some data type> *var;
> [...]

Nooooooo!

> > I think this is correct now, because it makes sense.
> It does seem to make a whole lot of sense.

The latter doesn't. A pointer is (typically) a 32-bit area of 
storage that contains the either the machine address of data
or NULL. An array is a contiguous block of memory that contains
the data itself. Do not confuse the two.

Read K&R again.

Phil
-- 
1st bug in MS win2k source code found after 20 minutes: scanline.cpp
2nd and 3rd bug found after 10 more minutes: gethost.c
Both non-exploitable. (The 2nd/3rd ones might be, depending on the CRTL)

0
Reply Phil 2/22/2004 7:50:17 AM

>>>var:  times 8 dd 0
>>>I can say
>>>extern int var[8];
>>>extern short int var[16];
>>>extern char var[32];
>>>and go as usual with arrays, or
> 
> Yup, yup, yup,
> 
>>>extern <some data type> *var;
> 
> Nooooooo!
> 
>>I think this is correct now, because it makes sense.
>
>> It does seem to make a whole lot of sense.
 >
> The latter doesn't. A pointer is (typically) a 32-bit area of 
> storage that contains the either the machine address of data
> or NULL. An array is a contiguous block of memory that contains
> the data itself. Do not confuse the two.

That post also contained:

--begin
But in the latter case I'm really working only with the first 4 bytes
of the area identified by var, and, for the same reason as before,
this will be a nil pointer, and chances are this is probably not what
I intended anyway, or, even worse, I can do

extern <some data type> *var[8];

and I'll end up with an array of 8 nil pointers (like before, probably
wrong).
--end

The point being that the OP has understood how the symbols and the 
linking work; data types and the use of data are a different matter. You 
may have been confused into thinking I passed a misunderstanding because 
I cut out some stuff from that post I didn't think was necessary to repeat.



-- 
Remove the furry animal from my address to send email:

   bjarni.ferret@update.ferret.uu.se

0
Reply Bjarni 2/22/2004 6:03:17 PM

6 Replies
251 Views

(page loaded in 0.115 seconds)

Similiar Articles:













7/17/2012 9:48:24 PM


Reply: