Всем доброго вечера! Вчера весь день и весь вечер бился над решением данного вопроса, но так ничего путного и не нашёл. Собственно я успел опробовать только два средства: Visual C++ (ml и link) и MinGW (g++ и ld). И хочу показать что у меня получилось. Сейчас речь пойдёт о Visual C++ (ml и link). Создал файл main.cpp со следующим кодом: Код (Text): bool main(int* _value) { if(!_value) return false; *_value=5; return true; } Обрабатываю: Код (Text): SET INCLUDE=C:\Program Files\Microsoft Visual Studio 10.0\VC\include\ SET LIB=C:\Program Files\Microsoft Visual Studio 10.0\VC\lib\ cl main.cpp /c /nologo /GS- /GR- /TP /Gm /Zi link main.obj /ENTRY:main /RELEASE /OUT:"main.bin" /SUBSYSTEM:NATIVE /NODEFAULTLIB /MACHINE:X86 /BASE:0x0 /MERGE:.text=.data /MERGE:.rdata=.data /IGNORE:4254 objcopy main.bin -I pe-i386 -O binary del main.obj del vc100.idb del vc100.pdb pause Получил файл main.bin, который занимает 26 байт. Вот его hex-содержимое: Код (Text): 00000000: 55 8B EC 83 7D 08 00 75 04 32 C0 EB 0B 8B 45 08 C7 00 05 00 │ UЛьГ} u2└ыЛE╟ 00000014: 00 00 B0 01 5D C3 │ ░]├ А вот дизассемблированный код: Код (Text): 00000000: 55 push ebp 00000001: 8BEC mov ebp,esp 00000003: 837D0800 cmp dw [ebp+008h],000h 00000007: 7504 j) jne 00000000Dh 00000009: 32C0 xor al,al 0000000B: EB0B j) jmp 000000018h 0000000D: 8B4508 mov eax,[ebp+008h] 00000010: C70005000000 mov dw [eax],000000005h 00000016: B001 mov al,001h 00000018: 5D pop ebp 00000019: C3 ret Собственно по генерированному коду (именно лишь по этому примеру) никаких вопросов нет. Вполне можно было бы использовать данный компилятор для разработки операционной системы. Но только меня мучает вопрос, касаемо смещения. Смещение при компоновке задаётся с помощью параметра (ключа) /BASE. Но ведь Visual C++ (ml и link) не умеет компилировать сырой бинарник, поэтому он смещение сделает не то, которое мы хотим получить. Например, если я укажу ему /BASE:0x00008000, наверняка же в действительности смещение получится (после обработки objcopy) другим (например прибавится 1024 байта или ещё что-то). С одной стороны можно рассчитать нужное смещение и указать его (хотя этот вариант мне не нравится). А с другой стороны, если нужно писать программы, которые будут работать по адресу 0x00000000, то смещение такое мы не добъёмся (так как PE-заголовок и прочее). Теперь перейду к MinGW (g++ и ld). Создаю файл main.cpp со следующим кодом: Код (Text): extern "C" bool start(int* _value); bool start(int* _value) { if(!_value) return false; *_value=5; return true; } Обрабатываю: Код (Text): g++ -ffreestanding -c -nodefaultlibs -nostdlib -fno-exceptions -o main.o main.cpp ld -Ttext 0x00000000 --entry _start --file-alignment 1 --section-alignment 1 -o data.bin main.o objcopy.exe data.bin -O binary pause Смотрим дамп объектного файла main.o: Код (Text): main.o: file format pe-i386 Disassembly of section .text: 00000000 <_start>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 7d 08 00 cmpl $0x0,0x8(%ebp) 7: 75 04 jne d <_start+0xd> 9: b0 00 mov $0x0,%al b: eb 0b jmp 18 <_start+0x18> d: 8b 45 08 mov 0x8(%ebp),%eax 10: c7 00 05 00 00 00 movl $0x5,(%eax) 16: b0 01 mov $0x1,%al 18: c9 leave 19: c3 ret 1a: 90 nop 1b: 90 nop В общем то всё практически нормально, только вот зачем то он два nop вставил. Мы получили файл data.bin, который занимает 64 байта (в два с лишним раза больше чем от link). Вот его hex-представление: Код (Text): 00000000: 55 89 E5 83 7D 08 00 75 04 B0 00 EB 0B 8B 45 08 C7 00 05 00 │ U╣е│} u▀ л╗EЗ 00000014: 00 00 B0 01 C9 C3 90 90 FF FF FF FF 00 00 00 00 FF FF FF FF │ ▀ЙГ└└яяяя яяяя 00000028: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ 0000003C: 00 00 00 00 │ А вот дизассемблированный код: Код (Text): 00000000: 55 push ebp 00000001: 89E5 mov ebp,esp 00000003: 837D0800 cmp dw [ebp+008h],000h 00000007: 7504 j) jne 00000000Dh 00000009: B000 mov al,000h 0000000B: EB0B j) jmp 000000018h 0000000D: 8B4508 mov eax,[ebp+008h] 00000010: C70005000000 mov dw [eax],000000005h 00000016: B001 mov al,001h 00000018: C9 leaved 00000019: C3 ret 0000001A: 90 nop 0000001B: 90 nop 0000001C: FF db 0FFh 0000001D: FF db 0FFh 0000001E: FF db 0FFh 0000001F: FF00 inc dw [eax] 00000021: 0000 add [eax],al 00000023: 00FF add bh,bh 00000025: FF db 0FFh 00000026: FF db 0FFh 00000027: FF00 inc dw [eax] 00000029: 0000 add [eax],al 0000002B: 0000 add [eax],al 0000002D: 0000 add [eax],al 0000002F: 0000 add [eax],al 00000031: 0000 add [eax],al 00000033: 0000 add [eax],al 00000035: 0000 add [eax],al 00000037: 0000 add [eax],al 00000039: 0000 add [eax],al 0000003B: 0000 add [eax],al 0000003D: 0000 add [eax],al 0000003F: 00 db 000h Получается что код разный. Но не это важно. Важно то, что файл больно большой, что там мусор. Если кому-то есть что добавить по данному вопросу, пожалуйста, говорите. Я же хочу из под Windows создавать сырые бинарники из языка C++, для которых я смогу устанавливать любое смещение, где не будет мусора. Кто что посоветует?
во-первых, то, чот ты называешь "смещением", на самом деле база. во-вторых, зачем тебе "сырые" бинарники из С++? компилируй в PE или ELF, а на асме сделай небольшой лоадер.
Great Затем, чтобы только лишь на C++ делать. Ну а если всё таки по существу моей проблемы, есть что-то?
На GCC + Binutils, подозреваю, это сделать можно. Во всяком случае, я для АРМа получал бинарник. Правда, писал на смеси ассемблера и Ады (Си/Си++ ненавижу и использую только под страхом смертной казни), но суть проблемы не меняется. Для этого пришлось компоновщику писать умный скрипт, чтобы он правильно настроил секции на нужные мне адреса и разместил их в нужном порядке (и только те, что нужны), ну а затем уже полученный эльф превратить в бин.
Я таких способов не знаю. И вообще, что значит: простыми путями? Если у кого-то мозгов меньше, чем у блондинки, то ему и неча заниматься программированием вообще, не говоря уж о системном, ну а если мозги есть, то в чём проблема с освоением "непростых" путей? С моей точки зрения, эта задача элементарна; во всяком случае, я её решил часа за три, и это с учётом того, что ранее никогда не использовал GCC и никогда не писал под АРМ. В общем, документацию читать надо, а не по дюжине форумов флудить в надежде, что кто-нибудь решит все задачи и принесёт решение на блюдечке с голубой каёмочкой.
mycode.ld: Код (Text): ENTRY(_start); OUTPUT_FORMAT(binary); SECTIONS { . = 0x7C00; .text : AT(0x7C00) { *(.text); } .data : { *(.data); } /DISCARD/ : { *(.drectve); *(/4); *(/18); *(/30); *(/42); *(/55); *(/66); *(/82); *(/98); *(/113); } } Makefile: Код (Text): CC = gcc LD = i586-elf-ld CFLAGS = -c -g -Os -march=i686 -ffreestanding -Wall -Werror -Wno-main -fno-builtin -Isrc -Isrc LDFLAGS = -static -nostdlib --strip-all --nmagic $(LD) $(LDFLAGS) -Tmycode.ld -o myobj.obj
n0name Вы практически вовремя написали. Я тут в Интернете нашёл CrossTools Complete. Так вот, пишу так: Код (Text): i586-elf-g++ -ffreestanding -c -nodefaultlibs -nostdlib -fno-exceptions -o main.o main.cpp i586-elf-ld --oformat binary -Ttext 0x00000000 --entry start -o data.bin main.o del main.o pause И у меня всё на ура делается. Получается без мусора. Решил скомпилировать с 64-битным кодом: Код (Text): i586-elf-g++ -m64 -ffreestanding -c -nodefaultlibs -nostdlib -fno-exceptions -o main.o main.cpp i586-elf-ld --oformat binary -Ttext 0x00000000 --entry start -o data.bin main.o del main.o pause Но в ответ: Код (Text): E:\03>i586-elf-g++ -m64 -ffreestanding -c -nodefaultlibs -nostdlib -fno-exceptio ns -o main.o main.cpp main.cpp:1: sorry, unimplemented: 64-bit mode not compiled in E:\03>i586-elf-ld --oformat binary -Ttext 0x00000000 --entry start -o data.bin m ain.o i586-elf-ld: main.o: No such file: No such file or directory E:\03>del main.o Не удается найти E:\03\main.o E:\03>pause Для продолжения нажмите любую клавишу . . . Никто не знает где же сказать полную версию?
Весь интернет облазил не нашёл что мне нужно. Может быть кто-нибудь подкинет ссылочку на x86_64-pc-elf-gcc для Windows x86?