Results 1 to 8 of 8

Thread: [ASM] "Hello World" in machine codes.

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    [ASM] "Hello World" in machine codes.

    Hello. As you know, most of us create programs using high-level languages, some also use assembler. Today we'll write a program using only a HEX editor. It's understood that you know the structure of executable files at least superficially, so i won't go into the details, besides, I have already cited a small overview of the EXE file loader on VB6. So let's go ...

    To begin, we'll define the functionality of the application and the tools used. For simplicity, we'll create a 64-bit application that shows the message "Hello World!" and completes its work. We'll use the 010 Editor as the HEX editor.

    Firstly, we'll create a scheme to determine all the offsets and sizes inside the PE file. Innitially, we'll determine the number of sections. Because our application will call the external API functions it needs the import table (I don't consider the option of getting one from PEB). To display the message, we use the function MessageBoxA and to end the application - ExitProcess, i.e. we need 2 libraries - kernel32.dll and user32.dll. Let's calculate the size of the import table. We need to place the 3 IMAGE_IMPORT_DESCRIPTOR structures for 2 libraries (two with data and one filled with zeros), we get 0x14 * 3 = 0x3C. We also need a space to put the names of the libraries in ASCIIZ format: 0x3C + sizeof ("kernel32.dll") + sizeof ("user32.dll") = 0x54. Next, we need to calculate the size of the names table and the addresses table, one function from each library, we get 0x54 + sizeof (IMAGE_THUNK_DATA) * 4 + sizeof (IMAGE_THUNK_DATA) * 2 = 0x84. Now add the size of the functions names: 0x84 + sizeof ("MessageBoxA") + 2 + sizeof ("ExitProcess") + 2 = 0xA0. So the import table takes the 0xA0 bytes. The first section will be placed on the first available RVA aligned to the page size, i.e. 0x1000. We place the import table at the beginning of the section (not forgetting that the data should be in little-endian format (low byte at the lower address)):

    Code:
    +-----------------+----------+------------------------+---------------------------------------------+
    | label           |  offset  |          data          |              description                    |
    +-----------------+----------+------------------------+---------------------------------------------+
    |  import table   |   0x00   | 0x00001054             | OriginalFirstThunk -----------------------+ |
    |                 |   0x04   | 0x00000000             | TimeDateStamp                             | |
    |                 |   0x08   | 0x00000000             | ForwarderChain                            | |
    |                 |   0x0c   | 0x0000103c             | Name ------------------+                  | |
    |                 |   0x10   | 0x00001074             | FirstThunk ------------+---------------+  | |
    |                 |   0x14   | 0x00001064             | OriginalFirstThunk ----+--------------+|  | |
    |                 |   0x18   | 0x00000000             | TimeDateStamp          |              ||  | |
    |                 |   0x1c   | 0x00000000             | ForwarderChain         |              ||  | |
    |                 |   0x20   | 0x00001049             | Name ----------------+ |              ||  | |
    |                 |   0x24   | 0x0000107c             | FirstThunk ----------+-+-----------+  ||  | |
    |                 |   0x28   | 0x00000000             | OriginalFirstThunk   | |           |  ||  | |
    |                 |   0x2c   | 0x00000000             | TimeDateStamp        | |           |  ||  | |
    |                 |   0x30   | 0x00000000             | ForwarderChain       | |           |  ||  | |
    |                 |   0x34   | 0x00000000             | Name                 | |           |  ||  | |
    |                 |   0x38   | 0x00000000             | FirstThunk           | |           |  ||  | |
    | libraries names |   0x3c   | kernel32.dll, 0        |                 <----+-+           |  ||  | |
    |                 |   0x49   | user32.dll, 0          |                 <----+             |  ||  | |
    |  names table 1  |   0x54   | 0x0000000000001084     | IMAGE_THUNK_DATA ---------------+  |  ||<-+ |
    |                 |   0x5c   | 0x0000000000000000     | IMAGE_THUNK_DATA zeroed         |  |  ||    |
    |  names table 2  |   0x64   | 0x0000000000001092     | IMAGE_THUNK_DATA ------------+  |  |<-+|    |
    |                 |   0x6c   | 0x0000000000000000     | IMAGE_THUNK_DATA zeroed      |  |  |   |    |
    | addresses table |   0x74   | 0x0000000000001084     | IMAGE_THUNK_DATA -+          |  |  |<--+    |
    |                 |   0x7c   | 0x0000000000001092     | IMAGE_THUNK_DATA  |--+       |  |<-+        |
    |      name 1     |   0x84   | 0x0000, ExitProcess, 0 |                 <-+  |       |<-+           |
    |      name 2     |   0x92   | 0x0000, MessageBoxA, 0 |                 <----+     <-+              |
    +-----------------+----------+------------------------+---------------------------------------------+
    We paste this data into a new file - this will be our import table:

    Code:
    54 10 00 00 00 00 00 00 00 00 00 00 3C 10 00 00  T...........<...
    74 10 00 00 64 10 00 00 00 00 00 00 00 00 00 00  t...d...........
    49 10 00 00 7C 10 00 00 00 00 00 00 00 00 00 00  I...|...........
    00 00 00 00 00 00 00 00 00 00 00 00 6B 65 72 6E  ............kern
    65 6C 33 32 2E 64 6C 6C 00 75 73 65 72 33 32 2E  el32.dll.user32.
    64 6C 6C 00 84 10 00 00 00 00 00 00 00 00 00 00  dll.„...........
    00 00 00 00 92 10 00 00 00 00 00 00 00 00 00 00  ....’...........
    00 00 00 00 84 10 00 00 00 00 00 00 92 10 00 00  ....„.......’...
    00 00 00 00 00 00 45 78 69 74 50 72 6F 63 65 73  ......ExitProces
    73 00 00 00 4D 65 73 73 61 67 65 42 6F 78 41 00  s...MessageBoxA.
    To display the message we need to store the message itself somewhere. We'll store it directly behind the import table, i.e. at offset 0xA0:

    Code:
    00A0h: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 00  Hello world!.
    The code itself begins immediately after this message, i.e. at offset 0xA0 + sizeof ("Hello world!") = 0xAD. All the API functions in x64 use the convention with the same name (x64 convention): the first 4 parameters are passed in the registers RCX, RDX, R8, R9, the rest in the stack, also 32 bytes of the shadow area are allocated in the stack (i don't consider the floating point arguments). The stack must be aligned to a 16 byte boundary as well. Now, using the relative offsets, we write the code in assembler, which we'll translate directly into machine code:

    Code:
    MSG db "Hello world!", 0
     
    sub RSP, 0x28           ; Reserve shadow space and align the stack
    mov R9, 0x00000040      ; MB_ICONINFORMATION
    xor R8, R8              ; lpCaption = NULL
    lea RDX, [MSG]          ; lpText = 'Hello world!'
    xor RCX, RCX            ; HWND = NULL
    Call MessageBoxA
    xor RCX, RCX
    Call ExitProcess
    Because the RIP addressing is used in x64 (all the offsets are calculated using the address of the following command), then we rewrite the code using the labels:

    Code:
    MSG db "Hello world!", 0
     
    sub RSP, 0x28                   ; Reserve shadow space and align the stack
    mov R9, 0x00000040              ; MB_ICONINFORMATION
    xor R8, R8                      ; lpCaption = NULL
    lea RDX, [RIP + (MSG - L1)]     ; lpText = 'Hello world!'
    L1: xor RCX, RCX                ; HWND = NULL
    Call [RIP + (MessageBoxA - L2)]
    L2: xor RCX, RCX
    Call [RIP + (ExitProcess - L3)]
    L3:
    Now let's proceed directly to the translation to machine code. For this, i use this table.
    The first instruction is sub RSP, 0x28 which operates with the 64 bit RSP register, so the opcode must contain the REX.W prefix (0x48); then search for the instruction SUB which accepts the first operand a 64 bit register and the second one is immediate single-byte value. This is 0x83. Now we need to determine the mod/rm byte. Because we use the RSP register directly which means the mod field is equal to 0b11 and the r/m field is equal to 0b100 which corresponds to AH/SP/ESP/RSP registers. As we can see the Register/Opcode field must be equal 5 (0b101) according the table. Putting it all together, and we get 0b11-101-100 = 0xEC. The immediate operand is immediately after the mod/rm byte, as a result, the complete command code is 48 83 EC 28.
    The next instruction is mov R9, 0x00000040 also has the REX prefix because it uses the register not available in 32 bit mode, namely the combination REX.W and REX.B = 0x49. The prefix REX.B tells the instruction has the extended rm field. In 32 bit mode we could use single-byte 0xB8 + r, in 64-bit mode we would have to use 0xC7. Let's determine mod/rm byte. Since the operand is the register the mod = 0b11, rm = 0b001 that corresponds to R9 the register. According to the table the Register/Opcode field should be equal to 0, putting everything together will result in 0b11-000-001 = 0xC1. The immediate operand is located directly behind the mod/rm field. As the result, we get the full command code = 49 C7 C1 40 00 00 00.
    The next instruction also works with the extended registers (two), so it also contains the extended prefix with the combination REX.W, REX.B and REX.R = 0x4D. The prefix REX.R indicates that the reg field of the mod/rm byte is also extended. Then search for the opcode of the XOR command, we can choose between the two: 0x31 or 0x33, i take the first one. We also define the mod/rm field. Again, because we use the registers directly, then the mod field will be 0b11, according to the register table we see that the extended field for the register R8 = 0b000. Putting it all together - 0b11-000-000 = 0xC0, and the full command code is 4D 31 C0.
    The next instruction is lea RDX, [RIP + (MSG - L1)], the second operand is an immediate value because we work in 64 bit mode and it addresses them relative to the address of the next command. I.e. we need an instruction like lea reg64, imm32 but firstly we'll define the prefix. Because the command works with 64 bit register then the prefix will be REX.W (0x48). The LEA command opcode is 0x8D. As mod/rm, we should have mod = 0b000, and rm = 0b101, which corresponds to [RIP + disp32]. For the RDX register, the number is 0b010. Compose together - 0b00-010-101 = 0x15. After that there is a 4-byte offset. Now let's calculate the offset to the string relative to the next command: disp = -(sizeof("Hello world!") + sizeof({48 83 EC 28}) + sizeof({49 C7 C1 40 00 00 00}) + sizeof({4D 31 C0}) + sizeof({48 8D 15 00 00 00 00})) = 0xFFFFFFDE. The full code is then = 48 8D 15 DE FF FF FF.
    The following XOR is calculated in the same way as the previous one: REX.W + 0x31 + 0b11-001-001 = 48 31 C9.
    Next we have the call from the import table, so we need to calculate the offset relative from the next command to the 2nd element of the address table (there we have the address of the MessageBoxA function), which is equal in this case to -79 (0xFFFFFFB1). Now we need to find the opcode of the CALL instruction that allows to call to the address located in memory. On the table we find 0xFF, Register/Opcode field should be equal to 2. Also calculate the mod/rm byte - 0b00-010-101 = 0x15. The full opcode = FF 15 B1 FF FF FF.
    The code of the next command is already known, so we go to the last opcode - CALL.
    Again we calculate the offset, it is equal to -96 0xFFFFFFA0, we substitute and we get the opcode of the command FF 15 A0 FF FF FF. That's all! Nothing complicated, only very painstakingly.

    Let's put all the data of section together:

    Code:
    0000h: 54 10 00 00 00 00 00 00 00 00 00 00 3C 10 00 00  T...........<...
    0010h: 74 10 00 00 64 10 00 00 00 00 00 00 00 00 00 00  t...d...........
    0020h: 49 10 00 00 7C 10 00 00 00 00 00 00 00 00 00 00  I...|...........
    0030h: 00 00 00 00 00 00 00 00 00 00 00 00 6B 65 72 6E  ............kern
    0040h: 65 6C 33 32 2E 64 6C 6C 00 75 73 65 72 33 32 2E  el32.dll.user32.
    0050h: 64 6C 6C 00 84 10 00 00 00 00 00 00 00 00 00 00  dll.„...........
    0060h: 00 00 00 00 92 10 00 00 00 00 00 00 00 00 00 00  ....’...........
    0070h: 00 00 00 00 84 10 00 00 00 00 00 00 92 10 00 00  ....„.......’...
    0080h: 00 00 00 00 00 00 45 78 69 74 50 72 6F 63 65 73  ......ExitProces
    0090h: 73 00 00 00 4D 65 73 73 61 67 65 42 6F 78 41 00  s...MessageBoxA.
    00A0h: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 00 48 83 EC  Hello world!.Hē
    00B0h: 28 49 C7 C1 40 00 00 00 4D 31 C0 48 8D 15 DE FF  (IÇÁ@...M1ÀH
    00C0h: FF FF 48 31 C9 FF 15 B1 FF FF FF 48 31 C9 FF 15  ÿÿH1Éÿ.±ÿÿÿH1Éÿ.
    00D0h: A0 FF FF FF                                       ÿÿÿ
    The total section size is 0xD4 bytes. Our entry point is 0x10AD. Now let's proceed to the creation of an EXE file. At the beginning of any PE file is the IMAGE_DOS_HEADER header:

    Code:
    typedef struct _IMAGE_DOS_HEADER
    {
         WORD e_magic;
         WORD e_cblp;
         WORD e_cp;
         WORD e_crlc;
         WORD e_cparhdr;
         WORD e_minalloc;
         WORD e_maxalloc;
         WORD e_ss;
         WORD e_sp;
         WORD e_csum;
         WORD e_ip;
         WORD e_cs;
         WORD e_lfarlc;
         WORD e_ovno;
         WORD e_res[4];
         WORD e_oemid;
         WORD e_oeminfo;
         WORD e_res2[10];
         DWORD e_lfanew;
    } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
    In this structure, we are interested only in the e_magic and e_lfanew fields, which are located at offsets 0x00 and 0x3C, respectively. The first field contains the signature MZ, and the second offset on the NT headers. Because we do not use the DOS stub, we will place the NT headers right behind it, i.e. the offset will be 0x40. This is very convenient because NT headers must be aligned to an 8 byte boundary, and the IMAGE_DOS_HEADER structure is 0x40 bytes in size. So create a new file and enter our data:

    Code:
    0000h: 4D 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00  MZ..............
    0010h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0030h: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00  ............@...
    Then insert the IMAGE_NT_HEADERS structure:

    Code:
    typedef struct _IMAGE_NT_HEADERS
    {
         DWORD Signature;
         IMAGE_FILE_HEADER FileHeader;
         IMAGE_OPTIONAL_HEADER64 OptionalHeader;
    } IMAGE_NT_HEADERS;
    typedef struct _IMAGE_FILE_HEADER
    {
         WORD Machine;
         WORD NumberOfSections;
         DWORD TimeDateStamp;
         DWORD PointerToSymbolTable;
         DWORD NumberOfSymbols;
         WORD SizeOfOptionalHeader;
         WORD Characteristics;
    } IMAGE_FILE_HEADER;
    typedef struct _IMAGE_OPTIONAL_HEADER64
    {
         WORD Magic;
         UCHAR MajorLinkerVersion;
         UCHAR MinorLinkerVersion;
         DWORD SizeOfCode;
         DWORD SizeOfInitializedData;
         DWORD SizeOfUninitializedData;
         DWORD AddressOfEntryPoint;
         DWORD BaseOfCode;
         DWORD64 ImageBase;
         DWORD SectionAlignment;
         DWORD FileAlignment;
         WORD MajorOperatingSystemVersion;
         WORD MinorOperatingSystemVersion;
         WORD MajorImageVersion;
         WORD MinorImageVersion;
         WORD MajorSubsystemVersion;
         WORD MinorSubsystemVersion;
         DWORD Win32VersionValue;
         DWORD SizeOfImage;
         DWORD SizeOfHeaders;
         DWORD CheckSum;
         WORD Subsystem;
         WORD DllCharacteristics;
         DWORD64 SizeOfStackReserve;
         DWORD64 SizeOfStackCommit;
         DWORD64 SizeOfHeapReserve;
         DWORD64 SizeOfHeapCommit;
         DWORD LoaderFlags;
         DWORD NumberOfRvaAndSizes;
         IMAGE_DATA_DIRECTORY DataDirectory[16];
    } IMAGE_OPTIONAL_HEADER64;
    As Signature we use the string with 4 characters PE\0\0. Because we have a 64 bit application, then the Machine field contains the value IMAGE_FILE_MACHINE_AMD64 (0x8664). As NumberOfSections, we specify 1, since we have single section. We don't need the next three fields, so we fill them with zeros. The size of optional header we set to IMAGE_SIZEOF_NT_OPTIONAL64_HEADER (0x00F0). Set the Characteristics field to the combination of the flags IMAGE_FILE_EXECUTABLE_IMAGE and IMAGE_FILE_LARGE_ADDRESS_AWARE (0x0022). Then, start filling out the optional header.

    As Magic we set IMAGE_NT_OPTIONAL_HDR64_MAGIC (0x020B). We don't need the linker version, so we fill it with zeros. We specify the size of the code as 0x1000 because it indicates the data size aligned by page boundary. The size of the initialized and uninitialized data is filled with zeros. As we have calculated earlier the entry point is 0x10AD, to the BaseOfCode field we place the RVA of our section since it contains code. As ImageBase we set 0x0000000000400000 - this is our base address, here we could in principle specify any value, since our module doesn't contain the absolute references. As SectionAlignment specify 0x1000 - the size of one page of memory, and as FileAlignment - 0x200 (the standard value for PE files). We don't use versions of the operating system and image but we specify 0x0005 and 0x0002 as MajorSubsystemVersion and MinorSubsystemVersion (similar to /SUBSYSTEM[,major[.minor]] linker key). As SizeOfImage we specify the value 0x2000, since our file will be located on two pages of memory (headers and one section). The value of SizeOfHeaders must be calculated by adding all the headers and aligning it to the FileAlignment boundary:
    align(sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER), 0x200) = 0x200. The checksum is also ignored and the Subsystem we set to IMAGE_SUBSYSTEM_WINDOWS_GUI (0x0002). The DllCharacteristics field contains the combination of flags IMAGE_DLLCHARACTERISTICS_NO_SEH and IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0C00. The size of the stack's reserved memory is filled by default - 0x100000 bytes, the same with the initial size - 0x1000 bytes. The same values are also for the heap. LoaderFlags is an obsolete field and doesn't interest us. NumberOfRvaAndSizes = 0x10.
    In the data directories we need only the import table under the index 1. We fill 0x1000 into it as the virtual address and the size is (as we have previously calculated) 0xA0. Here's what we got:

    Code:
    0000h: 4D 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00  MZ..............
    0010h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0030h: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00  ............@...
    0040h: 50 45 00 00 64 86 01 00 00 00 00 00 00 00 00 00  PE..d†..........
    0050h: 00 00 00 00 F0 00 22 00 0B 02 00 00 00 10 00 00  ....ð.".........
    0060h: 00 00 00 00 00 00 00 00 AD 10 00 00 00 10 00 00  ........*.......
    0070h: 00 00 40 00 00 00 00 00 00 10 00 00 00 02 00 00  ..@.............
    0080h: 00 00 00 00 00 00 00 00 05 00 02 00 00 00 00 00  ................
    0090h: 00 20 00 00 00 02 00 00 00 00 00 00 02 00 00 0C  . ..............
    00A0h: 00 00 10 00 00 00 00 00 00 10 00 00 00 00 00 00  ................
    00B0h: 00 00 10 00 00 00 00 00 00 10 00 00 00 00 00 00  ................
    00C0h: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00  ................
    00D0h: 00 10 00 00 A0 00 00 00 00 00 00 00 00 00 00 00  .... ...........
    00E0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00F0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0100h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0110h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0120h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0130h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0140h: 00 00 00 00 00 00 00 00                          ........

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: [ASM] "Hello World" in machine codes.

    Next, insert the section descriptor:

    Code:
    typedef struct _IMAGE_SECTION_HEADER
    {
         BYTE Name[8];
         DWORD VirtualSize;
         DWORD VirtualAddress;
         DWORD SizeOfRawData;
         DWORD PointerToRawData;
         DWORD PointerToRelocations;
         DWORD PointerToLinenumbers;
         WORD NumberOfRelocations;
         WORD NumberOfLinenumbers;
         DWORD Characteristics;
    } IMAGE_SECTION_HEADER;
    As a name, we set the standard name - '.text\0\0\0'. VirtualSize set to 0x1000 (rounded on the sections alignment). The VirtualAdress we defined as 0x1000. The SizeOfRawData field is set to 0x200 bytes because the size of the section data is 0xD4 bytes, but it needs to be rounded to the FileAlignment boundary, and the rest of data we can fill with zeroes or arbitrary data. The PointerToRawData field is equal to the value from IMAGE_OPTIONAL_HEADER64.SizeOfHeaders, i.e. 0x200. All the next fields to Characteristic fill with zeros. The Characteristic contains the combination of the flags IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE and IMAGE_SCN_MEM_READ, i.e. 0x60000020. That's almost done, just fill the data with zeroes to 512 bytes boundary and attach the section (which we should fill with zeroes to 512 bytes too). As a result, we get this file:

    Code:
    0000h: 4D 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00  MZ..............
    0010h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0030h: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00  ............@...
    0040h: 50 45 00 00 64 86 01 00 00 00 00 00 00 00 00 00  PE..d†..........
    0050h: 00 00 00 00 F0 00 22 00 0B 02 00 00 00 10 00 00  ....ð.".........
    0060h: 00 00 00 00 00 00 00 00 AD 10 00 00 00 10 00 00  ........*.......
    0070h: 00 00 40 00 00 00 00 00 00 10 00 00 00 02 00 00  ..@.............
    0080h: 00 00 00 00 00 00 00 00 05 00 02 00 00 00 00 00  ................
    0090h: 00 20 00 00 00 02 00 00 00 00 00 00 02 00 00 0C  . ..............
    00A0h: 00 00 10 00 00 00 00 00 00 10 00 00 00 00 00 00  ................
    00B0h: 00 00 10 00 00 00 00 00 00 10 00 00 00 00 00 00  ................
    00C0h: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00  ................
    00D0h: 00 10 00 00 A0 00 00 00 00 00 00 00 00 00 00 00  .... ...........
    00E0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00F0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0100h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0110h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0120h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0130h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0140h: 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00  .........text...
    0150h: 00 10 00 00 00 10 00 00 00 02 00 00 00 02 00 00  ................
    0160h: 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60  ............ ..`
    0170h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0180h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0190h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    01A0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    01B0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    01C0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    01D0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    01E0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    01F0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0200h: 54 10 00 00 00 00 00 00 00 00 00 00 3C 10 00 00  T...........<...
    0210h: 74 10 00 00 64 10 00 00 00 00 00 00 00 00 00 00  t...d...........
    0220h: 49 10 00 00 7C 10 00 00 00 00 00 00 00 00 00 00  I...|...........
    0230h: 00 00 00 00 00 00 00 00 00 00 00 00 6B 65 72 6E  ............kern
    0240h: 65 6C 33 32 2E 64 6C 6C 00 75 73 65 72 33 32 2E  el32.dll.user32.
    0250h: 64 6C 6C 00 84 10 00 00 00 00 00 00 00 00 00 00  dll.„...........
    0260h: 00 00 00 00 92 10 00 00 00 00 00 00 00 00 00 00  ....’...........
    0270h: 00 00 00 00 84 10 00 00 00 00 00 00 92 10 00 00  ....„.......’...
    0280h: 00 00 00 00 00 00 45 78 69 74 50 72 6F 63 65 73  ......ExitProces
    0290h: 73 00 00 00 4D 65 73 73 61 67 65 42 6F 78 41 00  s...MessageBoxA.
    02A0h: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 00 48 83 EC  Hello world!.Hē
    02B0h: 28 49 C7 C1 40 00 00 00 4D 31 C0 48 8D 15 DE FF  (IÇÁ@...M1ÀH
    02C0h: FF FF 48 31 C9 FF 15 B1 FF FF FF 48 31 C9 FF 15  ÿÿH1Éÿ.±ÿÿÿH1Éÿ.
    02D0h: A0 FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00   ÿÿÿ............
    02E0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    02F0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0300h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0310h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0320h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0330h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0340h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0350h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0360h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0370h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0380h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0390h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    03A0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    03B0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    03C0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    03D0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    03E0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    03F0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    Now, if we try to start it, we will have a message, as we expected

    Name:  fa0e0ceb762e661e2463d7496f2a14ba.png
Views: 1070
Size:  6.1 KB

    You can also play around with the FileAlignment parameter in order to reduce the file size.
    I hope you were interested, thank you for your attention!

    Best regards,
    The trick.
    Attached Files Attached Files

  3. #3

  4. #4
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,817

    Re: [ASM] "Hello World" in machine codes.

    Quote Originally Posted by The trick View Post
    Awww, I think it's wonderful right here. I think this is stuff about which us VB6 programmers should be educated, especially since we talk about wanting a VB6.5 so much.

    I know that, technically, it's got nothing to do with VB6, but maybe we could start developing the very beginnings of a VB6.5 compiler in VB6. The above could certainly be developed into VB6 code that produced this "Hello World" app's executable.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: [ASM] "Hello World" in machine codes.

    Elroy, thank you for the reply!
    The first thing we need to do i think is the 64 bit runtime. I know one guy makes the full reversing of the runtime and IDE and probably he'll publish it when it'll have some foundation.
    But we already have 64 bit IDE (VBA) and we already have the 64 bit MS compiler backend (C2.dll). I don't know exactly (i didn't researches it) but i hear VB6 translates the P-Codes to IL (like VC++ translates C source to IL by C1xx (front end)) and passes it to C2 (back end). So i think we can use C2 from the new studios. The same story with linker. Anyway we need the runtime (although we already have one (VBE7 for example (only EB))). Just it need to check if VBA contains the front end and it can make IL which we can pass to C2.dll to make COFF files.
    The other thing is the Ruby. We don't have the Forms/Controls/etc. functionality in VBA and anyway we need to implement it.

  6. #6
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,092

    Re: [ASM] "Hello World" in machine codes.

    From the linked article:



    The people w/ smeared faces were invited to the photo as "fillers" and have no connection w/ VB's development. Hilarious! :-))

    Still I count 9 devs here. . . and from the article 2 managers at least.

    Quote Originally Posted by The trick View Post
    Mnoo. . . Better merge ASM forums w/ VB6 ones as devs/target readers overlap significantly :-))

    cheers,
    </wqw>

  7. #7
    Member
    Join Date
    Apr 2019
    Posts
    63

    Re: [ASM] "Hello World" in machine codes.

    This is a really nice article Trick. I'm quite surprised no one has made a ASM-->HEX compiler in VB6 now, as this stuff seems relatively unobscure... Definitely a really worthwhile resource

  8. #8

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width