• Miércoles 20 de Noviembre de 2024, 14:28

Mostrar Mensajes

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
C/C++ / [Artículo] Crear nuestra propia Run Time Library (Primera Parte)
« 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?

Código: C++
  1. int main(int argc, char *argv[],char *env[])
  2. {
  3.   return 50;
  4. }

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:main

Paso 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:

Código: C++
  1. #include <windows.h>
  2.  
  3. int main(int argc, char *argv[],char *env[])
  4. {
  5.   char *dos = (char*)malloc(55);
  6.   int x = strlen("hola");
  7.   wsprintf(dos,"%d",x);
  8.   MessageBox(0,dos,dos,0);
  9.   free(dos);
  10.   return 50;
  11. }

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:
Código: C++
  1. extern "C" size_t strlen(const char *s)
  2. {
  3.   unsigned long Result = 0;
  4.   while(*s++) { Result++; }
  5.   return Result;
  6. }
  7. extern "C" char *strcpy(char *dest, const char *src)
  8. {
  9.   char *cp = dest;
  10.   while(*cp++ = *src++);        
  11.   return(dest);
  12. }

C_MAIN.CPP:
Código: C++
  1. extern int main(int argc, char *argv[],char *env[]);
  2. extern "C" void mainCRTStartup() { main(0,0,0); }

C_WMAIN.CPP:
Código: C++
  1. #include <windows.h>
  2.  
  3. extern WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow);
  4.  
  5. extern "C" void WinMainCRTStartup() { WinMain(GetModuleHandle(NULL),NULL,GetCommandLine(),SW_SHOW); }

C_ALLOC.CPP:
Código: C++
  1. #include <windows.h>
  2.  
  3. void *malloc(size_t size) { return HeapAlloc(GetProcessHeap(),NULL,size); }
  4.  
  5. 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.OBJ


Esto 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.ar

Descarga: http://c0d3rz.com.ar/foro/viewtopic.php?t=85

5077
C/C++ / Re: Reserva De Memoria Dinamicamente
« en: Lunes 14 de Junio de 2004, 17:16 »
new llama a malloc, si estas en Windows podes usar GlobalAlloc, LocalAlloc, VirtualAlloc y HeapAlloc (esta última es la que usa malloc).

 :ph34r:  :comp:  :hola:

5078
ASM (Ensamblador) / Re: Quiero Aprender Ensamblador
« en: Lunes 14 de Junio de 2004, 15:23 »
También para Windows podes visitar esta página: http://www.masm32.com/

 :ph34r:  :comp:  :hola:

5079
ASM (Ensamblador) / Re: Quiero Aprender Ensamblador
« 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/

 :ph34r:  :comp:  :hola:

5080
Visual C++ / Re: Existe alguien que responda las preguntas??????????
« en: Domingo 13 de Junio de 2004, 11:04 »
Si las preguntas tienen contenido y se la respuesta yo intento responder siempre.

 :ph34r:  :comp:

5081
La taberna del BIT / Re: Averiguar De La Vida Personal
« en: Sábado 12 de Junio de 2004, 20:18 »
:rolleyes:

5082
Visual C++ / Re: Como Insetar Un Dialgo De Abrir Archivo
« 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?

 :ph34r:  :comp:  :hola:

5083
Visual C++ / Re: Como Insetar Un Dialgo De Abrir Archivo
« 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...

 :ph34r:  :comp:  :hola:

5084
C/C++ / Re: Ligador En C
« 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.

 :ph34r:

5085
C/C++ / Re: Necesito Un Buen Consejo
« 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/

 :ph34r:  :comp:

Saludos,
Mariano.

5086
Visual C++ / Re: :ph34r: C++ O Perl
« 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++.

 :ph34r:  :comp:

5087
Visual C++ / Re: Como Insetar Un Dialgo De Abrir Archivo
« en: Viernes 11 de Junio de 2004, 21:11 »
GetOpenFileName

 :ph34r:

5088
C++ Builder / Re: Cómo Manejo El Path Actual?
« 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.

 :comp:  :ph34r:

5089
C/C++ / Re: Ayuda Con Variables Tipo Char
« 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

 :ph34r:  :comp:

5090
C/C++ / Re: Ayuda Con Variables Tipo Char
« 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++; }
}

 :ph34r:

5091
Visual Basic 6.0 e inferiores / Re: Hacer Ping Desde Visual
« en: Jueves 10 de Junio de 2004, 18:09 »
De nadas me alegro de que te haya servido

 :ph34r:  :comp:  :hola:

5092
C/C++ / Re: Ligador En C
« en: Jueves 10 de Junio de 2004, 17:18 »
Queres hacer un linker??

 :scream:

5093
C/C++ / Re: Ayuda, En El Proyecto
« en: Jueves 10 de Junio de 2004, 16:39 »
Cita de: "huecijako"
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 ...

:bad:

5094
Programación de Videojuegos / Re: Por Donde Empiezo?
« en: Jueves 10 de Junio de 2004, 16:29 »
El DirectX SDK viene con toda la ayuda que necesitas, pero está orientado a los compiladores de MS (VC++). Para usarlo en Borland necesitarias crear las librerias de importación de las DLL o conseguirlas en algun lado.

 :ph34r:  :comp:  :hola:

5095
C++ Builder / Re: Cómo Manejo El Path Actual?
« 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
C/C++ / Re: Ayuda, En El Proyecto
« en: Jueves 10 de Junio de 2004, 12:00 »
Sinceramente te parece que esto es un reto?

:bad: :no:

5097
Visual Basic 6.0 e inferiores / Re: Hacer Ping Desde Visual
« 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


 :comp:  :hola:

5098
Visual C++ / Re: Esperar A Un Evento Sin Bloquear El Programa
« 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);


 :ph34r:  :comp:

5099
Visual C++ / Re: Esperar A Un Evento Sin Bloquear El Programa
« 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.

 :ph34r:

5100
ASM (Ensamblador) / Re: Programas Gráficos En Asm
« en: Miércoles 9 de Junio de 2004, 21:00 »
Para que Sistema Operativo?

 :ph34r:

Páginas: 1 ... 202 203 [204] 205