|
Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.
Mensajes - Eternal Idol
Páginas: 1 ... 202 203 [204] 205
5076
« en: Lunes 14 de Junio de 2004, 17:20 »
Alguna vez se preguntaron por que un programa como este puede llegar a ocupar unos 24KB? int main(int argc, char *argv[],char *env[]) { return 50; }
Este programa no hace NADA, solo nos devuelve un 50 (si recuerdan nuestro último tutorial esto es mov eax,50). El 'problema' es que VC++ por defecto incorpora su Run Time Library que contiene muchisimas funciones indispensables como strlen,malloc,printf y muchas más. Esta Run Time Library ocupa bastantes KB, si hacemos un programa extenso su tamaño no tiene la más mínima importancia, pero si sólo escribimos un par de instrucciones ... Linkeen el código anterior con esta linea de comandos: link codigo.obj /NODEFAULTLIB /ENTRY:mainPaso a explicar, NODEFAULTLIB le indica al linker que quite las librerias que utiliza para resolver referencias externas por defecto. Entry le indica al linker la función que dará comienzo al programa que por defecto nunca es main, nuestras funciones main o WinMain son llamadas por otras que antes hacen inicializacion de la Heap para utilizar malloc y free, que nos devuelven argc, argv y env por ejemplo. Estas funciones se llaman mainCRTStartup para main y WinMainCRTStartup para WinMain. Que hemos logrado con esta linea de comandos? Reducir el tamaño de nuestro ejecutable a nada más y nada menos que 1024 bytes (si no lo consiguieron es porque tienen una versión del linker que usa un align grande prueben con: link codigo.obj /NODEFAULTLIB /ENTRY:main /ALIGN:512 y lo van a conseguir). Esto está muy bien pero en realidad no nos sirve de mucho, ahora tenemos un programa que está discapacitado, no puede llamar ni siquiera a la función strlen(). Pero como el título de este tutorial dice vamos a crear nuestra propia Run Time Library para reemplazar la de VC++, el objetivo no es hacer una mejor que los muchachos de Microsoft, sino tener nuestra propia Run Time Library unicamente con las funciones que necesitemos y de paso aprender MUCHO sobre programación. Primero vamos a ver un ejemplo de Run Time Library muy simple escrito en C++. Nuestro objetivo en este momento es compilar este programa (COMUN.CPP) sin la STDLIB por defecto: #include <windows.h> int main(int argc, char *argv[],char *env[]) { char *dos = (char*)malloc(55); int x = strlen("hola"); wsprintf(dos,"%d",x); MessageBox(0,dos,dos,0); free(dos); return 50; }
Con esta linea de comandos LINK COMUN.OBJ /NODEFAULTLIB user32.lib kernel32.lib nos enteramos que nos faltan un par de funciones, estas cuatro exactamente: COMUN.OBJ : error LNK2001: unresolved external symbol _free COMUN.OBJ : error LNK2001: unresolved external symbol _strlen COMUN.OBJ : error LNK2001: unresolved external symbol _malloc LINKASM : error LNK2001: unresolved external symbol _mainCRTStartup COMUN.exe : fatal error LNK1120: 4 unresolved externals Al crear nuestra libreria la vamos a hacer lo más modular posible, porque cada archivo objeto (código compilado) que sea llamado se cargará completamente, por ejemplo si tenemos todas las funciones dentro de un solo archivo .cpp, lo compilamos y lo solo utilizamos strlen() dentro del programa que usa nuestra Run Time Library también serán cargadas strcpy(),malloc(), free() y todas las funciones que hagamos. Sabiendo esto que es muy importante vamos a crear cuatro archivos, C_STR.CPP con las funciones strlen() y strcpy(), C_MAIN.CPP con mainCRTStartup, C_WMAIN.CPP con WinMainCRTStartup y C_ALLOC.CPP con malloc() y free(). C_STR.CPP: extern "C" size_t strlen(const char *s) { unsigned long Result = 0; while(*s++) { Result++; } return Result; } extern "C" char *strcpy(char *dest, const char *src) { char *cp = dest; while(*cp++ = *src++); return(dest); }
C_MAIN.CPP: extern int main(int argc, char *argv[],char *env[]); extern "C" void mainCRTStartup() { main(0,0,0); }
C_WMAIN.CPP: #include <windows.h> extern WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow); extern "C" void WinMainCRTStartup() { WinMain(GetModuleHandle(NULL),NULL,GetCommandLine(),SW_SHOW); }
C_ALLOC.CPP: #include <windows.h> void *malloc(size_t size) { return HeapAlloc(GetProcessHeap(),NULL,size); } void free(void *block) { HeapFree(GetProcessHeap(),NULL,block); }
Bueno, la mayoria de las cosas las deben entender sin ningún problema, C_STR.CPP tiene dos funciones muy simples strlen() y strcpy() de la STDLIB. C_MAIN.CPP tiene una función que llama al main del programa que estemos escribiendo y le pasa como parametros el argc, argv y env (en este caso solo le pasamos ceros para no complicarnos). C_WMAIN.CPP llama a WinMain() la instancia anterior del programa, la linea de comandos y SW_SHOW. Finalmente C_ALLOC.CPP usa la Heap del proceso para asignar y liberar memoria. Ahora que tenemos todos los archivos de la CLIB (nuestra libreria para reemplazar la Run Time Library de VC++) podemos compilarla y linkearla asi: cl /c C_ALLOC.CPP C_MAIN.CPP C_STR.CPP C_WMAIN.CPP lib /out:CLIB.LIB C_ALLOC.OBJ C_MAIN.OBJ C_STR.OBJ C_WMAIN.OBJEsto nos va a generar nuestra clib.lib. Ahora teniendo el comun.cpp podemos hacer: LINK COMUN.OBJ /NODEFAULTLIB user32.lib kernel32.lib clib.lib y se va a generar un ejecutable que nos va mostrar un MessageBox con el numero 10. Ocupa 2.560 bytes en mi PC. Si prueban a compilar el mismo programa con la STDLIB por defecto verán que lo mínimo que consigan serán 14.484 bytes. En la segunda parte vamos a ver como mejorar nuestra libreria con más rutinas, como por ejemplo implementar los operadores new y delete, entre otras cosas. Saludos, Mariano. Autor: Mariano Ventaja http://www.c0d3rz.com.arDescarga: http://c0d3rz.com.ar/foro/viewtopic.php?t=85
5077
« en: Lunes 14 de Junio de 2004, 17:16 »
5078
« en: Lunes 14 de Junio de 2004, 15:23 »
5079
« en: Lunes 14 de Junio de 2004, 15:22 »
Hay un lindo libro que se llama Ensamblador para DOS, Linux y Windows de Francisco Charte Ojeda, Editorial Anaya. Acá te podes bajar las utilidades que vienen con el libro http://www.c0d3rz.com.ar/
5080
« en: Domingo 13 de Junio de 2004, 11:04 »
Si las preguntas tienen contenido y se la respuesta yo intento responder siempre.
5081
« en: Sábado 12 de Junio de 2004, 20:18 »
5082
« en: Sábado 12 de Junio de 2004, 19:58 »
Es imposible que si te estas refiriendo a un linker te haya salido ... que es lo que queres hacer exactamente y llamas ligador?? "¿Se puede hacer esto con Tree Control o list Control?" esto que cosa es?
5083
« en: Sábado 12 de Junio de 2004, 11:27 »
No se si existe un boton magico que haga todo, eso es VB, si pones un boton cualquier y le agregas esa funcion bien llamada te va a sacar el dialogo para abrir un archivo perfectamente. strcat() concatena palabras. Estas tratando de hacer un linker y no sabes estas cosas??? Sin ofender preo me parece un poco ilusorio que lo logres...
5084
« en: Sábado 12 de Junio de 2004, 11:25 »
Un linker para Windows lo que hace es resolver las diferentes dependencias de un archivo objeto (ya sea de DLLs, libs u otros archivos objeto) y despues escribir la cabecera PE del ejecutable.
5085
« en: Sábado 12 de Junio de 2004, 11:23 »
Empezar con C y despues aprender las nuevas caracteristicas de C++ podria ser una opcion, sino directamente con C++. Los mejores compiladores por lejos son los de Intel y Microsoft. http://msdn.microsoft.com/visualc/vctoolkit2003/ Saludos, Mariano.
5086
« en: Viernes 11 de Junio de 2004, 23:03 »
Perl no puede competir con C++, no tienen nada que ver, uno es un lenguaje interpretado y el otro es un lenguaje compilado; personalmente me gusta trabajar al nivel más bajo posible así que entre estos dos me quedo con C++.
5087
« en: Viernes 11 de Junio de 2004, 21:11 »
GetOpenFileName
5088
« en: Viernes 11 de Junio de 2004, 00:14 »
Esa una función de la API de Windows, si estas haciendo un programa con Borland Builder que unicamente va a correr bajo Windows te recomiendo siempre usar la API directamente y no funciones de C.
5089
« en: Jueves 10 de Junio de 2004, 21:59 »
Un caracter es una variable que ocupa un byte (0-255) un entero ocupa 4 bytes, porque queres compararlos? De cualquier manera podrías usar un casting (int)car == variable_entera
5090
« en: Jueves 10 de Junio de 2004, 20:12 »
Creo que así sería más fácil: char car; while (!File.eof()) { File.get(car); if (car == ';') { count++; } }
5091
« en: Jueves 10 de Junio de 2004, 18:09 »
5092
« en: Jueves 10 de Junio de 2004, 17:18 »
Queres hacer un linker??
5093
« en: Jueves 10 de Junio de 2004, 16:39 »
pues para mi si que es un reto hacerlo, pa ti lo mismo no, pero es que me e quedao bloqueado y tengo que hacerlo No estoy hablando de la dificultad si no como bien dijo Blag de que nadie quiere hacer TU[/size] tarea ...
5094
« en: Jueves 10 de Junio de 2004, 16:29 »
5095
« en: Jueves 10 de Junio de 2004, 16:28 »
O en GetOpenFileName() le pasas OFN_NOCHANGEDIR como flag así no te cambia de directorio o utlizas el path completo del ejecutable para el archivo de ayuda.
Por ejemplo:
char *help_file = (char*)malloc(2048); ZeroMemory(help_file,2048); GetCurrentDirectory(help_file,2000); strcat(help_file,"\\verificador.hlp"); try { Application->Initialize(); Application->Title = "Verificador de iMelody"; Application->HelpFile = help_file; Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } free(help_file); return 0;
5096
« en: Jueves 10 de Junio de 2004, 12:00 »
Sinceramente te parece que esto es un reto?
5097
« en: Jueves 10 de Junio de 2004, 11:18 »
Lo más fácil es que uses la icmp.dll, otra opción es usar Winsock. Aca va un ejemplo (dentro dice de donde salió): Const SOCKET_ERROR = 0 Private Type WSAdata wVersion As Integer wHighVersion As Integer szDescription(0 To 255) As Byte szSystemStatus(0 To 128) As Byte iMaxSockets As Integer iMaxUdpDg As Integer lpVendorInfo As Long End Type Private Type Hostent h_name As Long h_aliases As Long h_addrtype As Integer h_length As Integer h_addr_list As Long End Type Private Type IP_OPTION_INFORMATION TTL As Byte Tos As Byte Flags As Byte OptionsSize As Long OptionsData As String * 128 End Type Private Type IP_ECHO_REPLY Address(0 To 3) As Byte Status As Long RoundTripTime As Long DataSize As Integer Reserved As Integer data As Long Options As IP_OPTION_INFORMATION End Type Private Declare Function GetHostByName Lib "wsock32.dll" Alias "gethostbyname" (ByVal HostName As String) As Long Private Declare Function WSAStartup Lib "wsock32.dll" (ByVal wVersionRequired&, lpWSAdata As WSAdata) As Long Private Declare Function WSACleanup Lib "wsock32.dll" () As Long Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long) Private Declare Function IcmpCreateFile Lib "icmp.dll" () As Long Private Declare Function IcmpCloseHandle Lib "icmp.dll" (ByVal HANDLE As Long) As Boolean Private Declare Function IcmpSendEcho Lib "ICMP" (ByVal IcmpHandle As Long, ByVal DestAddress As Long, ByVal RequestData As String, ByVal RequestSize As Integer, RequestOptns As IP_OPTION_INFORMATION, ReplyBuffer As IP_ECHO_REPLY, ByVal ReplySize As Long, ByVal TimeOut As Long) As Boolean Private Sub Form_Load() 'KPD-Team 2000 'URL: http://www.allapi.net/ 'E-Mail: KPDTeam@Allapi.net Const HostName = " www.allapi.net" Dim hFile As Long, lpWSAdata As WSAdata Dim hHostent As Hostent, AddrList As Long Dim Address As Long, rIP As String Dim OptInfo As IP_OPTION_INFORMATION Dim EchoReply As IP_ECHO_REPLY Call WSAStartup(&H101, lpWSAdata) If GetHostByName(HostName + String(64 - Len(HostName), 0)) <> SOCKET_ERROR Then CopyMemory hHostent.h_name, ByVal GetHostByName(HostName + String(64 - Len(HostName), 0)), Len(hHostent) CopyMemory AddrList, ByVal hHostent.h_addr_list, 4 CopyMemory Address, ByVal AddrList, 4 End If hFile = IcmpCreateFile() If hFile = 0 Then MsgBox "Unable to Create File Handle" Exit Sub End If OptInfo.TTL = 255 If IcmpSendEcho(hFile, Address, String(32, "A"), 32, OptInfo, EchoReply, Len(EchoReply) + 8, 2000) Then rIP = CStr(EchoReply.Address(0)) + "." + CStr(EchoReply.Address(1)) + "." + CStr(EchoReply.Address(2)) + "." + CStr(EchoReply.Address(3)) Else MsgBox "Timeout" End If If EchoReply.Status = 0 Then MsgBox "Reply from " + HostName + " (" + rIP + ") recieved after " + Trim$(CStr(EchoReply.RoundTripTime)) + "ms" Else MsgBox "Failure ..." End If Call IcmpCloseHandle(hFile) Call WSACleanup End Sub
5098
« en: Jueves 10 de Junio de 2004, 10:59 »
Aca tenes otro código que en su momento puse en el foro http://www.jeanpaul.com.ar hace un tiempo: class Valvula { private: static DWORD WINAPI AbrirValvula(LPVOID lpParam) { Valvula *mi_valvula = (Valvula*)lpParam; DWORD Now = GetTickCount(); do { }while(GetTickCount() < Now + mi_valvula->TimeToWait); mi_valvula->Abierta = TRUE; } DWORD TimeToWait; //en milisegundos public: BOOL Abierta; Valvula() { Abierta = FALSE; TimeToWait = 0; } void Abrir(DWORD Espera) //en milisegundos { DWORD dwThreadId, dwThrdParam = 1; dwThrdParam = (DWORD)(this); TimeToWait = Espera; CreateThread(NULL,NULL,AbrirValvula,(void*)dwThrdParam,0,&dwThreadId); } }; Podes probar con este codigo: Valvula xp; xp.Abrir(5000);
5099
« en: Jueves 10 de Junio de 2004, 10:47 »
Una función callback del sistema tiene que tener los parametros exactos de la API, las clases pasan a sus funciones el puntero this. Para poder usar los demás miembros vas a tener que hacer un "truquito" que consiste en pasarle el puntero this a la función estatica y hacer un casting al nombre de la clase, así podes acceder a los otros miembros si no es imposible. A ver como hago un ejemplo ... vamos a usar una clase muy simple. class Id { public: Id() { myname = (char*)malloc(150); ZeroMemory(myname,150); } ~Id() { free(myname); } void Name(char *NewName); const char *Name(); static DWORD WINAPI MergeIndex(LPVOID lpParam) { Id *xp = (Id*)lpParam; MessageBox(0,xp->Name(),xp->Name(),0); return 0; } private: char *myname; }; void Id::Name(char *NewName) { strcpy(myname,NewName); } const char *Id::Name() { return myname; } //creamos un thread con la funcion MergeIndex() DWORD dwThreadId, dwThrdParam = 1; Id *p = new Id[1]; p->Name("holas"); dwThrdParam = (DWORD)p; CreateThread(NULL,NULL,p->MergeIndex,(void*)dwThrdParam,0,&dwThreadId); Name() va a devolver "holas" por que le pasamos el puntero de la clase.
5100
« en: Miércoles 9 de Junio de 2004, 21:00 »
Para que Sistema Operativo?
Páginas: 1 ... 202 203 [204] 205
|
|
|