Рассмотрим простой пример, две функции 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 );
Здравствуйте, Аноним, Вы писали:
А>Рассмотрим простой пример, две функции 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
Здравствуйте, Аноним, Вы писали:
А>Рассмотрим простой пример, две функции 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)
Всё это для дебага
Здравствуйте, <Аноним>, Вы писали:
А>Собсвенно как заставить компилятор записать реальный адрес функции ?
/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