Recent

Author Topic: Printing a variable's address to the console [SOLVED]  (Read 1012 times)

YiannisKam

  • Jr. Member
  • **
  • Posts: 99
Printing a variable's address to the console [SOLVED]
« on: December 05, 2022, 07:37:23 pm »
In C language I can easily print a variable's address just by using the & operator.
Code: C  [Select][+][-]
  1. int x = 100;
  2. printf("Value of x: %d\n", x);
  3. printf("Address of x: %p\n", &x);
  4.  
with an output that looks like
Code: Text  [Select][+][-]
  1. Value of x: 100
  2. Address of x: 000000D83FEFFBE4

I'm trying to do the same in Pascal but the output I get doesn't look correct. Or is it?
Here is the code and the output
Code: Pascal  [Select][+][-]
  1. begin
  2.   x := 100;
  3.   writeln('Value of x: ', x);
  4.   writeln('Address of x: ', HexStr(@x));
  5.  
  6.   readln
  7. end.
Output:
Code: Text  [Select][+][-]
  1. Value of x: 100
  2. Address of x: 0000000100021010

I realized I can't just type something like @x with the writeln function. Is HexStr(@x) the right approach? And no matter how many times I run the program in Pascal I always get as an address numbers between 0,1,2s. That doesn't look ok when comparing with C's hex value.
« Last Edit: December 05, 2022, 08:34:49 pm by YiannisKam »

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Printing a variable's address to the console
« Reply #1 on: December 05, 2022, 07:47:35 pm »
I realized I can't just type something like @x with the writeln function. Is HexStr(@x) the right approach? And no matter how many times I run the program in Pascal I always get as an address numbers between 0,1,2s. That doesn't look ok when comparing with C's hex value.

Code: Pascal  [Select][+][-]
  1. program address;
  2. uses sysutils;
  3. var
  4.   x : integer;
  5. begin
  6.   x := 100;
  7.   writeln(format('Value of x: %d', [x]));
  8.   writeln(format('Address of x: %p', [@x]));
  9.   readln;
  10. end.
  11.  

Code: Text  [Select][+][-]
  1. $ fpc -g address.pas
  2. Free Pascal Compiler version 3.2.2 [2022/08/17] for x86_64
  3. Copyright (c) 1993-2021 by Florian Klaempfl and others
  4. Target OS: Linux for x86-64
  5. Compiling address.pas
  6. Linking address
  7. 10 lines compiled, 0.2 sec
  8.  

Code: Text  [Select][+][-]
  1. $ ./address
  2. Value of x: 100
  3. Address of x: 000000000047D530
  4.  

Code: Text  [Select][+][-]
  1. $ objdump -t ./address  | fgrep -i d530
  2. 000000000047d530 l     O .bss   0000000000000002 U_$P$ADDRESS_$$_X
  3. 000000000045c650 l     O .rodata        000000000000000f .Ld530
  4.  

Looks correct to me...

YiannisKam

  • Jr. Member
  • **
  • Posts: 99
Re: Printing a variable's address to the console
« Reply #2 on: December 05, 2022, 07:50:43 pm »
I've tried also with the format function with the same result. Maybe because I'm on windows.. I don't know if that's the case.

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Printing a variable's address to the console
« Reply #3 on: December 05, 2022, 07:58:29 pm »
I've tried also with the format function with the same result. Maybe because I'm on windows.. I don't know if that's the case.

I don't think that is the case (being on windows, though I'm on Linux).

For this:
Code: C  [Select][+][-]
  1. #include <stdio.h>
  2.  
  3. int x = 100;
  4.  
  5. int main() {
  6.     printf("Value of x: %d\n", x);
  7.     printf("Address of x: %p\n", &x);
  8.     return 0;
  9. }
  10.  

If outside of main I get a different address range than if inside main.

Code: Text  [Select][+][-]
  1. $ gcc -g -o address_c address.c
  2.  
  3. $ ./address_c
  4. Value of x: 100
  5. Address of x: 0x404024
  6.  
  7. $ objdump -t ./address_c | fgrep -i 4024
  8. 0000000000404024 g     O .data  0000000000000004              x
  9.  

Buf if inside main:
Code: Text  [Select][+][-]
  1. $ ./address_c
  2. Value of x: 100
  3. Address of x: 0x7fffc1a330fc
  4.  

It all depends are where the respective compilers/linkers are allocating these variables, and whether they are from the stack or the heap.



Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: Printing a variable's address to the console
« Reply #4 on: December 05, 2022, 08:02:19 pm »
Output:
Code: Pascal  [Select][+][-]
  1. Value of x: 100
  2. Address of x: 0000000100021010

I realized I can't just type something like @x with the writeln function. Is HexStr(@x) the right approach? And no matter how many times I run the program in Pascal I always get as an address numbers between 0,1,2s. That doesn't look ok when comparing with C's hex value.

The address looks actually quite possible.... Depends on the base address for your exe.

Afaik FPC compiles with a fixed base/relocation address => so the range for global variables will always be the same. (Also for locals as the stack address range will also be similar each time).  Fields of dynamically created objects may be a bit more variable.

Check out the fpc command line option, there may be one to change the default reloc address, or make it dynamic.... (or maybe that is an option that needs to be forwarded to the linker.



Try
Code: Pascal  [Select][+][-]
  1. var
  2.   x,y,z : integer;

Then the addresses of those 3 should be in steps of 4 (or 8, depends on alignment).

Bogen85

  • Hero Member
  • *****
  • Posts: 595
Re: Printing a variable's address to the console
« Reply #5 on: December 05, 2022, 08:04:28 pm »
It all depends are where the respective compilers/linkers are allocating these variables, and whether they are from the stack or the heap.

Code: Pascal  [Select][+][-]
  1. program address;
  2. uses sysutils;
  3.  
  4. procedure main;
  5.   var
  6.     y : integer;
  7.   begin
  8.     y := 100;
  9.     writeln(format('Value of y: %d', [y]));
  10.     writeln(format('Address of y: %p', [@y]));
  11.   end;
  12.  
  13. var
  14.   x : integer;
  15. begin
  16.   main;
  17.   x := 100;
  18.   writeln(format('Value of x: %d', [x]));
  19.   writeln(format('Address of x: %p', [@x]));
  20.   readln;
  21. end.
  22.  

Code: Text  [Select][+][-]
  1. $ fpc -g address.pas
  2. Free Pascal Compiler version 3.2.2 [2022/08/17] for x86_64
  3. Copyright (c) 1993-2021 by Florian Klaempfl and others
  4. Target OS: Linux for x86-64
  5. Compiling address.pas
  6. Linking address
  7. 21 lines compiled, 0.2 sec
  8.  
  9. $ ./address
  10. Value of y: 100
  11. Address of y: 00007FFE8338ADDC
  12. Value of x: 100
  13. Address of x: 000000000047D530
  14.  

This is closer to the C example.

x is not off the stack. y is.

YiannisKam

  • Jr. Member
  • **
  • Posts: 99
Re: Printing a variable's address to the console
« Reply #6 on: December 05, 2022, 08:11:46 pm »
Wonderful, thank you all. Now I understand.
Bogen85 your example clarified everything to me. I've tried it on my windows machine and it does look "similar" like the C's program output.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: Printing a variable's address to the console [SOLVED]
« Reply #7 on: December 05, 2022, 10:34:24 pm »
And no matter how many times I run the program in Pascal I always get as an address numbers between 0,1,2s. That doesn't look ok when comparing with C's hex value.

As mentioned by the others by default the binaries will have a specific base address and Windows will load it there each and every time. If you want to have a more “random” address you need to enable a dynamic base (enabled by default on aarch64-win64):

Code: Pascal  [Select][+][-]
  1. program tvar;
  2.  
  3. const
  4.  IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = $0040;
  5.  
  6. {$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE}
  7.  
  8. var
  9.   x: LongInt;
  10.  
  11. begin
  12.   Writeln(HexStr(@x));
  13.   //Readln;
  14. end.

You need to compile this with the -WR option which enforces the generation of relocation code (also default on aarch64-win64).

After that the result of the program above for me is:

Code: [Select]
PS C:\fpc\git> .\testoutput\tvar.exe
00007FF61183C010

instead of

Code: [Select]
PS C:\fpc\git> .\testoutput\tvar.exe
000000010000C010

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: Printing a variable's address to the console [SOLVED]
« Reply #8 on: December 05, 2022, 11:24:55 pm »
In C language I can easily print a variable's address just by using the & operator.
Code: C  [Select][+][-]
  1. int x = 100;
  2. printf("Value of x: %d\n", x);
  3. printf("Address of x: %p\n", &x);
  4.  
you can code the above _almost_ exactly the same in FPC under Windows using NTDLL's sprintf.

basically, instead of a printf call, use sprintf(yourcharbuffer, <same stuff as printf>) with @x instead of &x followed by a writeln(yourcharbuffer);

The only thing you have to be aware of is that NTDLL's sprintf doesn't have support for floating point types e.g, %f, %g, etc.  For those you can use msvcrt.dll (which will often be included in the process anyway because a fair number of Windows dll use it - IOW, you can often use it "for free")

Also, NTDLL includes about a third, maybe even a half, of the C runtime library which is often convenient but, it's important to know the differences (they are some very important ones, as well as some, now well known, bugs.)

HTH.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: Printing a variable's address to the console [SOLVED]
« Reply #9 on: December 08, 2022, 10:16:43 pm »
In C language I can easily print a variable's address just by using the & operator.
Code: C  [Select][+][-]
  1. int x = 100;
  2. printf("Value of x: %d\n", x);
  3. printf("Address of x: %p\n", &x);
  4.  
you can code the above _almost_ exactly the same in FPC under Windows using NTDLL's sprintf.

basically, instead of a printf call, use sprintf(yourcharbuffer, <same stuff as printf>) with @x instead of &x followed by a writeln(yourcharbuffer);

You are aware that YiannisKam's question is mainly about the value of the address itself and not about printing it?

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: Printing a variable's address to the console [SOLVED]
« Reply #10 on: December 08, 2022, 10:39:29 pm »
You are aware that YiannisKam's question is mainly about the value of the address itself and not about printing it?
Yes, I just wanted to show that he can take the address and print it (or use it) in FPC almost exactly as it is done in C.  IOW, depending on the code he uses (e.g, sprintf), he won't need to call HexStr(@x) or something equivalent.

Yet, IOW, he can do it in FPC pretty much the same way he does it in C (courtesy of ntdll and/or msvcrt)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 14157
  • Probably until I exterminate Putin.
Re: Printing a variable's address to the console [SOLVED]
« Reply #11 on: December 12, 2022, 02:16:06 pm »
Ok, week late but why not:
Code: Pascal  [Select][+][-]
  1. V{$ifdef mswindows}{$apptype console}{$endif}
  2. {$mode objfpc}
  3. uses sysutils;
  4. var x:integer = 100;
  5. begin
  6.   writeln('Value of x: $', x.ToHexString(16));
  7.   writeln('Address of x: $', PtrUint(@X).ToHexString(16));
  8. end.
Specialize a type, not a var.

YiannisKam

  • Jr. Member
  • **
  • Posts: 99
Re: Printing a variable's address to the console [SOLVED]
« Reply #12 on: December 20, 2022, 04:39:36 am »
Thank you Thaddy. I have tried the cast with PtrUInt but without ToHexString function. It's very handy and a new thing for me to know.

 

TinyPortal © 2005-2018