Адрес функции
От: Аноним  
Дата: 18.02.10 07:51
Оценка:
Рассмотрим простой пример, две функции func1 и func2 — нам нужно определить адрес этих функций.
По идее &func1 должен вернуть адрес функции.

void func1()
{
}

void func2()
{
}

int _tmain(int argc, _TCHAR* argv[])
{
    int addr_func1 = (int)(&func1);
    int addr_func2 = (int)(&func2);
    printf( "func1 = %d, func2 = %d ",  addr_func1, addr_func2 );
    return 0;
}



Теперь смотрим дизассемблер этого кода ( в конце сообщения ), из которого видно что func1 имеет адрес 004113C0, а func2 = 004113F0.

Что же нам выведет printf ?

А выводит он следующее

func1 = 4264311, func2 = 4264306


что соотвествует в 16-ричной 0х411177 и 0х411172

1. Во первых эти адреса не совпадают с теми которые в дизассемблере
2. Адрес func1 оказался больше чем адрес func2

Если посмотреть на ассемблер то записывает он следующее

0041143E  mov         dword ptr [addr_func1],offset func1 (411177h) 
    int addr_func2 = (int)(&func2);
00411445  mov         dword ptr [addr_func2],offset func2 (411172h)


Собсвенно как заставить компилятор записать реальный адрес функции ?



void func1()
{
004113C0  push        ebp  
004113C1  mov         ebp,esp 
004113C3  sub         esp,0C0h 
004113C9  push        ebx  
004113CA  push        esi  
004113CB  push        edi  
004113CC  lea         edi,[ebp-0C0h] 
004113D2  mov         ecx,30h 
004113D7  mov         eax,0CCCCCCCCh 
004113DC  rep stos    dword ptr es:[edi] 
}
004113DE  pop         edi  
004113DF  pop         esi  
004113E0  pop         ebx  
004113E1  mov         esp,ebp 
004113E3  pop         ebp  
004113E4  ret              
--- No source file -------------------------------------------------------------
004113E5  int         3    
004113E6  int         3    
004113E7  int         3    
004113E8  int         3    
004113E9  int         3    
004113EA  int         3    
004113EB  int         3    
004113EC  int         3    
004113ED  int         3    
004113EE  int         3    
004113EF  int         3    
--- g:\users\pavel\documents\visual studio 2005\projects\test_mem\test_mem\test_mem.cpp 

void func2()
{
004113F0  push        ebp  
004113F1  mov         ebp,esp 
004113F3  sub         esp,0C0h 
004113F9  push        ebx  
004113FA  push        esi  
004113FB  push        edi  
004113FC  lea         edi,[ebp-0C0h] 
00411402  mov         ecx,30h 
00411407  mov         eax,0CCCCCCCCh 
0041140C  rep stos    dword ptr es:[edi] 
}
0041140E  pop         edi  
0041140F  pop         esi  
00411410  pop         ebx  
00411411  mov         esp,ebp 
00411413  pop         ebp  
00411414  ret              
--- No source file -------------------------------------------------------------
00411415  int         3    
00411416  int         3    
00411417  int         3    
00411418  int         3    
00411419  int         3    
0041141A  int         3    
0041141B  int         3    
0041141C  int         3    
0041141D  int         3    
0041141E  int         3    
0041141F  int         3    
--- g:\users\pavel\documents\visual studio 2005\projects\test_mem\test_mem\test_mem.cpp 

int _tmain(int argc, _TCHAR* argv[])
{
00411420  push        ebp  
00411421  mov         ebp,esp 
00411423  sub         esp,0D8h 
00411429  push        ebx  
0041142A  push        esi  
0041142B  push        edi  
0041142C  lea         edi,[ebp-0D8h] 
00411432  mov         ecx,36h 
00411437  mov         eax,0CCCCCCCCh 
0041143C  rep stos    dword ptr es:[edi] 
    int addr_func1 = (int)(&func1);
0041143E  mov         dword ptr [addr_func1],offset func1 (411177h) 
    int addr_func2 = (int)(&func2);
00411445  mov         dword ptr [addr_func2],offset func2 (411172h) 
    printf( "func1 = %d, func2 = %d ",  addr_func1, addr_func2 );
Re: Адрес функции
От: Кодт Россия  
Дата: 18.02.10 11:11
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Рассмотрим простой пример, две функции func1 и func2 — нам нужно определить адрес этих функций.

А>По идее &func1 должен вернуть адрес функции.

Может быть, включены какие-то оптимизации?
У меня дистиллированный пример работает нормально. VC8, cl.exe t.cpp /FAs
#include <stdio.h>

void func1()
{
    printf("this is func1 \n");
}

void func2()
{
    printf("this is func2 \n");
}

int main()
{
    int addr_func1 = (int)(&func1);
    int addr_func2 = (int)(&func2);
    printf( "func1 = %p, func2 = %p \n",  addr_func1, addr_func2 ); // func1 = 00401000, func2 = 00401020
    printf( "func1 = %p, func2 = %p \n", func1, func2 );            // func1 = 00401000, func2 = 00401020

    ((void(*)(void))addr_func1)(); // this is func1
    ((void(*)(void))addr_func2)(); // this is func2
}

Ассемблерный код
PUBLIC    _main
_TEXT    SEGMENT
_addr_func1$ = -8                    ; size = 4
_addr_func2$ = -4                    ; size = 4
_main    PROC

; 14   : {
    push    ebp
    mov    ebp, esp
    sub    esp, 8

; 15   :     int addr_func1 = (int)(&func1);
    mov    DWORD PTR _addr_func1$[ebp], OFFSET ?func1@@YAXXZ ; func1

; 16   :     int addr_func2 = (int)(&func2);
    mov    DWORD PTR _addr_func2$[ebp], OFFSET ?func2@@YAXXZ ; func2

; 17   :     printf( "func1 = %p, func2 = %p \n",  addr_func1, addr_func2 );
    mov    eax, DWORD PTR _addr_func2$[ebp]
    push    eax
    mov    ecx, DWORD PTR _addr_func1$[ebp]
    push    ecx
    push    OFFSET $SG3677
    call    _printf
    add    esp, 12                    ; 0000000cH

; 18   :     printf( "func1 = %p, func2 = %p \n", func1, func2 );
    push    OFFSET ?func2@@YAXXZ            ; func2
    push    OFFSET ?func1@@YAXXZ            ; func1
    push    OFFSET $SG3678
    call    _printf
    add    esp, 12                    ; 0000000cH

; 19   : 
; 20   :     ((void(*)(void))addr_func1)();
    call    DWORD PTR _addr_func1$[ebp]

; 21   :     ((void(*)(void))addr_func2)();
    call    DWORD PTR _addr_func2$[ebp]

; 22   : }
    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0
_main    ENDP
_TEXT    ENDS
Перекуём баги на фичи!
Re: Адрес функции
От: icWasya  
Дата: 18.02.10 13:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Рассмотрим простой пример, две функции func1 и func2 — нам нужно определить адрес этих функций.

А>По идее &func1 должен вернуть адрес функции.

А>
А>void func1()
А>{
А>}

А>void func2()
А>{
А>}

А>int _tmain(int argc, _TCHAR* argv[])
А>{
А>    int addr_func1 = (int)(&func1);
А>    int addr_func2 = (int)(&func2);
А>    printf( "func1 = %d, func2 = %d ",  addr_func1, addr_func2 );
А>    return 0;
А>}
А>



А>Теперь смотрим дизассемблер этого кода ( в конце сообщения ), из которого видно что func1 имеет адрес 004113C0, а func2 = 004113F0.


А>Что же нам выведет printf ?


А>А выводит он следующее


А>

А>func1 = 4264311, func2 = 4264306


А>что соотвествует в 16-ричной 0х411177 и 0х411172


А>1. Во первых эти адреса не совпадают с теми которые в дизассемблере

А>2. Адрес func1 оказался больше чем адрес func2

а если посмотреть ассемблер по внимательней, то по адресу 00411172 стоит Jump

00411172  jmp         func2 (4113F0h)


Всё это для дебага
Re[2]: Адрес функции
От: Сергей Мухин Россия  
Дата: 20.02.10 18:01
Оценка: +1
Здравствуйте, icWasya, Вы писали:


W>Всё это для дебага


Наверно это для опции Edit % Continue
---
С уважением,
Сергей Мухин
Re: Адрес функции
От: gear nuke  
Дата: 22.02.10 06:57
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Собсвенно как заставить компилятор записать реальный адрес функции ?


/OPT:ICF линкеру
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.