В некоторых отношениях это очень широкий вопрос, который может не выжить по этой причине.
Вся информация находится в inte rnet, продолжайте искать, это не сложно, не достойно бумага или видео. (или вопрос stackoverflow?)
Таким образом, у вас есть грубое представление о том, что компилятор берет программу, написанную на одном языке, и преобразует ее в другой язык, будь то язык ассемблера или машинный код или что-то еще.
Затем существуют форматы файлов, и есть много разных, для которых мы все используем термин «двоичный», но опять же, разные форматы. В идеале они содержат, с использованием какой-либо формы кодирования, машинный код и данные или информацию о данных.
Пока что будем использовать ARM, инструкции фиксированной длины, легко разбираемые и читаемые, и т. Д. c.
#define ONE 1
unsigned int x;
unsigned int y = 5;
const unsigned int z = 7;
unsigned int fun ( unsigned int a )
{
return(a+ONE);
}
и gnu gcc / binutils, поскольку он очень хорошо известен, широко используется, его можно использовать для создания программ на компьютере wintel. Я запускаю linux, так что вы увидите, что elf не exe, но это просто формат файла для того, что вы просите.
arm-none-eabi-gcc -O2 -c so.c -save-temps -o so.o
Этот набор инструментов (цепочка инструментов, которые связаны, например, компилятор -> ассемблер -> компоновщик) unix стиль и модульность. У вас будет ассемблер для цели, поэтому вы не знаете, зачем вам это изобретать, и отладку компилятора гораздо проще посмотреть на вывод сборки, чем пытаться go перейти прямо к машинному коду. Но есть люди, которые любят взбираться на гору только потому, что она есть, а не go вокруг, а некоторые инструменты go прямо для машинного кода только потому, что он есть.
этот специфический c компилятор имеет это Функция сохранения временных параметров, g cc сама по себе является программой переднего плана, которая готовит настоящий компилятор, а затем, если ее попросят (если вы не говорите, нет), вызовет ассемблер и компоновщик.
cat so.i
# 1 "so.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "so.c"
unsigned int x;
unsigned int y = 5;
const unsigned int z = 7;
unsigned int fun ( unsigned int a )
{
return(a+1);
}
, поэтому в этот пункт определяет и включает в себя заботу и один его большой файл для отправки компилятору.
компилятор делает свое дело и превращает его в язык ассемблера
cat so.s
.cpu arm7tdmi
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 2
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "so.c"
.text
.align 2
.global fun
.arch armv4t
.syntax unified
.arm
.fpu softvfp
.type fun, %function
fun:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
add r0, r0, #1
bx lr
.size fun, .-fun
.global z
.global y
.comm x,4,4
.section .rodata
.align 2
.type z, %object
.size z, 4
z:
.word 7
.data
.align 2
.type y, %object
.size y, 4
y:
.word 5
.ident "GCC: (GNU) 9.3.0"
, который затем получает положить в объектный файл, в данном случае binutils, linux default, et c
file so.o
so.o: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), not stripped
он использует формат файла elf, который легко найти информацию, легко написать программы для parse, et c.
Я могу разобрать это, обратите внимание, что, поскольку я использую дизассемблер, он пытается разобрать все, даже если это не машинный код, придерживаясь 32-битной руки ff Это можно перевернуть, и когда есть реальные инструкции, они показываются (выровненные, а не переменной длины, как здесь используется, так что вы можете разбирать линейно, чего вы не можете с набором команд переменной длины, и иметь надежду на успех (например, x86). необходимо разобрать в порядке выполнения, а затем вы часто пропускаете некоторые из-за характера программы)
arm-none-eabi-objdump -D so.o
so.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <fun>:
0: e2800001 add r0, r0, #1
4: e12fff1e bx lr
Disassembly of section .data:
00000000 <y>:
0: 00000005 andeq r0, r0, r5
Disassembly of section .rodata:
00000000 <z>:
0: 00000007 andeq r0, r0, r7
Disassembly of section .comment:
00000000 <.comment>:
0: 43434700 movtmi r4, #14080 ; 0x3700
4: 4728203a ; <UNDEFINED> instruction: 0x4728203a
8: 2029554e eorcs r5, r9, lr, asr #10
c: 2e332e39 mrccs 14, 1, r2, cr3, cr9, {1}
10: Address 0x0000000000000010 is out of bounds.
Disassembly of section .ARM.attributes:
00000000 <.ARM.attributes>:
0: 00002941 andeq r2, r0, r1, asr #18
4: 61656100 cmnvs r5, r0, lsl #2
8: 01006962 tsteq r0, r2, ror #18
c: 0000001f andeq r0, r0, pc, lsl r0
10: 00543405 subseq r3, r4, r5, lsl #8
14: 01080206 tsteq r8, r6, lsl #4
18: 04120109 ldreq r0, [r2], #-265 ; 0xfffffef7
1c: 01150114 tsteq r5, r4, lsl r1
20: 01180317 tsteq r8, r7, lsl r3
24: 011a0119 tsteq r10, r9, lsl r1
28: Address 0x0000000000000028 is out of bounds.
и да, инструмент добавляет туда дополнительные вещи, но обратите внимание прежде всего на то, что я создал. некоторый код, некоторые инициализированные данные для чтения / записи, некоторые инициализированные данные для чтения / записи и некоторые инициализированные данные только для чтения. Авторы цепочки инструментов могут использовать любые имена, которые им нужны, им даже не нужно использовать термин section. Но из десятилетий истории и коммуникации и терминологии .text обычно используется для кода (как в машинном коде и данных, связанных только для чтения), .bss для обнуленных данных чтения / записи, хотя я видел другие имена, .data для инициализированного чтения / записи данные и это поколение этого инструмента .rodata для инициализированных данных только для чтения (технически это может быть в .text)
И обратите внимание, что все они имеют нулевой адрес. они еще не связаны.
Теперь это уродливо, но чтобы не добавлять больше кода, а инструмент позволяет мне сделать это, позволяет связать его для создания совершенно непригодного двоичного файла (нет bootstrap, et c, et c)
arm-none-eabi-ld -Ttext=0x1000 -Tdata=0x2000 so.o -o so.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000000001000
arm-none-eabi-objdump -D so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
00001000 <fun>:
1000: e2800001 add r0, r0, #1
1004: e12fff1e bx lr
Disassembly of section .data:
00002000 <y>:
2000: 00000005 andeq r0, r0, r5
Disassembly of section .rodata:
00001008 <z>:
1008: 00000007 andeq r0, r0, r7
Disassembly of section .bss:
00002004 <x>:
2004: 00000000 andeq r0, r0, r0
А теперь это связано. Элементы только для чтения .text и .rodata находятся в адресном пространстве .text в порядке, указанном в файле. Элементы чтения / записи помещались в адресное пространство .data в порядке, указанном в файле.
yes где был. бсс в объекте? Он там, у него нет фактических данных, как в байтах, которые являются частью объекта, вместо этого у него есть имя и размер, и он является .bss. И по любой причине инструмент показывает его из связанного двоичного файла.
Итак, вернемся к термину двоичный. Двоичный файл so.elf содержит байты go в памяти, составляющие программу, а также инфраструктуру форматов файлов и таблицу символов для облегчения разборки и отладки, а также другие элементы. Elf - это гибкий формат файла, который GNU может использовать, и вы получите один результат, который может использовать другой инструмент или версия инструмента и получить другой файл. И очевидно, что два компилятора могут генерировать различный машинный код из одной и той же исходной программы не только из-за оптимизации, задача состоит в том, чтобы сделать функциональную программу на целевом языке, а функциональность - по мнению автора компилятора / инструмента.
как насчет файла типа образа памяти:
arm-none-eabi-objcopy so.elf so.bin -O binary
hexdump -C so.bin
00000000 01 00 80 e2 1e ff 2f e1 07 00 00 00 00 00 00 00 |....../.........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 05 00 00 00 |....|
00001004
Теперь, как работает инструмент objcopy, он начинается с первого определенного загружаемого или любого другого термина, который вы хотите использовать, и заканчивается последним и использует (ноль) ) заполнение, чтобы размер файла совпадал, чтобы изображение памяти совпадало с точки зрения адреса. Звездочка означает, по существу, 0 отступов. Потому что мы начали с 0x1000 с .text и 0x2000 для .data, но первый байт этого файла (смещение 0) - это начало .text и 0x1000 байт позже, который смещен в файл 0x1000, но мы знаем, что он переходит к 0x2000 в памяти это материал для чтения / записи. Также обратите внимание, что нули bss отсутствуют в выводе. ожидается, что bootstrap обнулит их.
Нет информации, например, где в памяти находятся эти данные из этого файла и т. Д. c. И если вы немного об этом думаете, что если у меня есть один байт в разделе, который я определяю, идет в 0x00000000 и один байт в разделе, который я определяю, идет в 0x80000000 и выводит этот файл, да, это файл байтов 0x80000001, хотя есть только два полезных байта соответствующей информации. Файл 2 ГБ для хранения двух байтов. Вот почему вы не хотите выводить этот формат файла, пока не разберетесь со сценарием и инструментами компоновщика.
Те же данные и два других одинаково старых школьных формата с небольшой историей Intel против Motorola
arm-none-eabi-objcopy so.elf so.hex -O ihex
cat so.hex
:08100000010080E21EFF2FE158
:0410080007000000DD
:0420000005000000D7
:0400000300001000E9
:00000001FF
arm-none-eabi-objcopy so.elf so.srec -O srec
cat so.srec
S00A0000736F2E7372656338
S10B1000010080E21EFF2FE154
S107100807000000D9
S107200005000000D3
S9031000EC
теперь они содержат соответствующие байты, плюс адреса, но не очень много другой информации, занимают более двух байтов на каждый байт данных, но по сравнению с огромным файлом с заполнением, достойным компромиссом. Оба этих формата можно найти сегодня в использовании, не столько, сколько в прежние времена, но все еще там.
И бесчисленное множество других форматов двоичных файлов и инструмент, такой как objdump, имеет приличный список форматов, которые он может генерировать также как и другие компоновщики и / или инструменты там.
Для всего этого важно то, что существует двоичный формат файла некоторой формы, который содержит байты, необходимые для запуска программы.
Какой формат и какие адреса вы можете спросить ... Это часть операционной системы или системы дизайна. В случае Windows существуют определенные c форматы файлов и варианты, возможно, тех форматов, которые поддерживаются операционной системой windows, используемой вами версией c. Windows определил, как выглядит адресное пространство. Подобные операционные системы используют MMU как для виртуализации адресов, так и для защиты. Наличие виртуального адресного пространства означает, что каждая программа может жить в одном и том же пространстве. Все программы могут иметь нулевой адрес, например ....
test. c
int main ( void )
{
return 1;
}
привет. c
int main ( void )
{
return 2;
}
gcc test.c -o test
objdump -D test
Disassembly of section .text:
00000000004003e0 <_start>:
4003e0: 31 ed xor %ebp,%ebp
4003e2: 49 89 d1 mov %rdx,%r9
4003e5: 5e pop %rsi
...
gcc hello.c -o hello
objdump -D hello
Disassembly of section .text:
00000000004003e0 <_start>:
4003e0: 31 ed xor %ebp,%ebp
4003e2: 49 89 d1 mov %rdx,%r9
тот же адрес, как это возможно, если они не сидят друг на друге? нет виртуальной машины. И обратите внимание, что он создан для определенного c linux в указанный c день и т. Д. c. У цепочки инструментов есть скрипт компоновщика по умолчанию (заметьте, я не указывал, как связывать) для этой платформы, когда компилятор был создан для этой цели / платформы.
arm-none-eabi-gcc -O2 test.c -c -o test.o
arm-none-eabi-ld test.o -o test.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000000008000
arm-none-eabi-objdump -D test.elf
test.elf: file format elf32-littlearm
Disassembly of section .text:
00008000 <main>:
8000: e3a00001 mov r0, #1
8004: e12fff1e bx lr
один и тот же исходный код, тот же компилятор, созданный для другой цели и другого системного адреса.
Так что для windows определенно будут правила для поддерживаемых двоичных форматов и правила для адресных пространств, которые можно использовать, как определять эти пространства в файле.
Тогда это просто вопрос запуска операционной системы для чтения двоичного файла и помещения загружаемых элементов в память по этим адресам (в виртуальном пространстве, которое ОС создала для этой конкретной c программы). Вполне возможно, что функция загрузчика на ноль BSS для вас, так как информация там. Программист низкого уровня должен знать, что, возможно, иметь дело с обнулением .bss или нет.
Если нет, вы увидите, и, возможно, потребуется создать решение, к сожалению, здесь вы углубляетесь в спецификацию инструмента c Предметы. В то время как C может быть несколько стандартизирован, существуют инструменты, определяющие c вещи, которые не стандартизированы или по крайней мере стандартизированы инструментом / авторами, но нет причин предполагать, что они переходят на другие инструменты.
.globl _start
_start:
ldr sp,sp_init
bl fun
b .
.word __bss_start__
.word __bss_end__
sp_init:
.word 0x8000
все, что касается языка ассемблера, - это спецификация инструмента c, мнемоника по соображениям здравого смысла, без сомнения, будет напоминать документацию поставщиков IP / процессоров, в которой используется синтаксис, который использует инструмент, который они заплатили за разработку. Но помимо этого ассемблера язык полностью определяется инструментом, а не целью, x86 из-за своего возраста и прочих обстоятельств действительно плох в этом, и это не Intel против AT & T, в общем. Ассемблер Gnu хорошо известен тем, что я предположил бы, возможно, намеренно не создание совместимых языков с другими языками ассемблера. Выше приведен gnu-ассемблер для arm
с использованием функции fun (), приведенной выше, C говорит, что это должно быть main (), но инструменту все равно, я уже достаточно набрал здесь.
add простой скрипт компоновщика на базе оперативной памяти
MEMORY
{
ram : ORIGIN = 0x1000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.rodata : { *(.rodata*) } > ram
.bss : {
__bss_start__ = .;
*(.bss*)
} > ram
__bss_end__ = .;
}
построить все это
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c so.c -o so.o
arm-none-eabi-ld -T sram.ld start.o so.o -o so.elf
исследовать
arm-none-eabi-nm so.elf
0000102c B __bss_end__
00001028 B __bss_start__
00001018 T fun
00001014 t sp_init
00001000 T _start
00001028 B x
00001024 D y
00001020 R z
arm-none-eabi-objdump -D so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
00001000 <_start>:
1000: e59fd00c ldr sp, [pc, #12] ; 1014 <sp_init>
1004: eb000003 bl 1018 <fun>
1008: eafffffe b 1008 <_start+0x8>
100c: 00001028 andeq r1, r0, r8, lsr #32
1010: 0000102c andeq r1, r0, r12, lsr #32
00001014 <sp_init>:
1014: 00008000 andeq r8, r0, r0
00001018 <fun>:
1018: e2800001 add r0, r0, #1
101c: e12fff1e bx lr
Disassembly of section .rodata:
00001020 <z>:
1020: 00000007 andeq r0, r0, r7
Disassembly of section .data:
00001024 <y>:
1024: 00000005 andeq r0, r0, r5
Disassembly of section .bss:
00001028 <x>:
1028: 00000000 andeq r0, r0, r0
так что теперь можно добавить к bootstrap a Обнуление памяти l oop (не используйте C / memset, вы не создаете проблемы с курицей и яйцами, вы пишете bootstrap в asm) на основе начального и конечного адресов.
к счастью или к сожалению, потому что скрипт компоновщика это спецификация инструмента c, а язык ассемблера это спецификация инструмента c, и они должны работать вместе, если вы позволяете инструментам делать работу за вас (нормальный способ сделать это, получайте удовольствие, выясняя, где .bss иначе) ,
это можно сделать в операционной системе, но когда вы попадаете, скажем, в микроконтроллеры, где все это должно быть в энергонезависимой памяти (fla sh), вполне возможно, что она будет загружена из другого места (например, иногда ваша прошивка мыши, иногда клавиатура и т. д. c) в оперативную память, предположим, что fla sh, так как вы справляетесь с .data ??
MEMORY
{
rom : ORIGIN = 0x0000, LENGTH = 0x1000
ram : ORIGIN = 0x1000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.data : {
*(.data*)
} > ram AT > rom
.bss : {
__bss_start__ = .;
*(.bss*)
} > ram
__bss_end__ = .;
}
с GNU LD Это в основном говорит, что .data home находится в ram, но выходные двоичные форматы поместят его во flash / rom
so.elf so.srec -O srec
cat so.srec
S00A0000736F2E7372656338
S11300000CD09FE5030000EBFEFFFFEA04100000A4
S11300100810000000800000010080E21EFF2FE1B4
S107002007000000D1 <- z variable at address 0020
S107002405000000CF <- y variable at 0024
S9030000FC
, и вам придется поиграться со скриптом компоновщика, чтобы получить инструмент, который сообщит вам как ram, так и fla sh начальные адреса и конечные адреса или длина. затем добавьте код в bootstrap (asm not C), чтобы скопировать .data из fla sh в ram.
Также обратите внимание здесь на еще один из ваших многочисленных вопросов.
.word __bss_start__
.word __bss_end__
sp_init:
.word 0x8000
эти пункты являются технически данными. но они живут в .text прежде всего потому, что они были определены в коде, который предположительно был .text (мне не нужно было указывать это в asm, но мог бы иметь). вы также увидите это в x86, но для фиксированной длины, такой как arm, mips, ris c -v, et c, где вы не можете поместить любое старое немедленное / постоянное / связанное значение, которое вы хотите, в саму инструкцию, которую вы помещаете. поблизости в "пуле" и сделайте ap c относительное чтение, чтобы получить его. Вы увидите это и для связи с внешними объектами: переменная
extern unsigned int x;
int main ( void )
{
return x;
}
arm-none-eabi-gcc -O2 -c test.c -o test.o
arm-none-eabi-objdump -D test.o
test.o: file format elf32-littlearm
Disassembly of section .text.startup:
00000000 <main>:
0: e59f3004 ldr r3, [pc, #4] ; c <main+0xc>
4: e5930000 ldr r0, [r3]
8: e12fff1e bx lr
c: 00000000 andeq r0, r0, r0 <--- the code gets the address of the
отсюда, а затем считывает ее из памяти
после привязки
Disassembly of section .text:
00008000 <main>:
8000: e59f3004 ldr r3, [pc, #4] ; 800c <main+0xc>
8004: e5930000 ldr r0, [r3]
8008: e12fff1e bx lr
800c: 00018010 andeq r8, r1, r0, lsl r0
Disassembly of section .data:
00018010 <x>:
18010: 00000005 andeq r0, r0, r5
для x86
gcc -c -O2 test.c -o test.o
dwelch-desktop so # objdump -D test.o
test.o: file format elf64-x86-64
Disassembly of section .text.startup:
0000000000000000 <main>:
0: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 6 <main+0x6>
6: c3 retq
00000000004003e0 <main>:
4003e0: 8b 05 4a 0c 20 00 mov 0x200c4a(%rip),%eax # 601030 <x>
4003e6: c3 retq
Если вы косите, это действительно по-другому? поблизости есть данные, которые процессор читает для загрузки в регистр и / или использования. в любом случае, из-за природы набора команд компоновщик изменяет инструкцию или данные ближайшего пула, или и то и другое.
последний:
arm-none-eabi-gcc -S test.c
cat test.s
.cpu arm7tdmi
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 6
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "test.c"
.text
.align 2
.global main
.arch armv4t
.syntax unified
.arm
.fpu softvfp
.type main, %function
main:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
ldr r3, .L3
ldr r3, [r3]
mov r0, r3
add sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.L4:
.align 2
.L3:
.word x
.size main, .-main
.ident "GCC: (GNU) 9.3.0"
, так что вы можете видеть язык ассемблера, да некоторые инструменты позволят вам сохранить промежуточные файлы и / или сгенерировать выходные данные файла сборки при компиляции.
если у вас есть данные в коде, да, есть моменты и причины для того, чтобы значения данных были в .text область не просто целевая спецификация c, вы увидите это по разным причинам, и некоторые наборы инструментов помещают туда данные только для чтения.
Существует много форматов файлов, которые используются современными операционными системами и имеют функции не только для определения байты, которые составляют машинный код и значения данных, но также будут включать символы и другую отладочную информацию.
Формат файла и пространство памяти для программы определяются операционной системой c, а не языком или даже указанием цели c (linux, windows, макросы на том же ноутбуке не должны иметь одинаковый ru файлы, несмотря на тот же целевой компьютер). У нативного набора инструментов для этой платформы есть скрипт компоновщика по умолчанию и любая другая информация, необходимая для создания работоспособных / работающих программ для этой цели. Включая поддерживаемый формат файла.
Машинный код и элементы данных могут быть представлены в разных форматах файлов по-разному, независимо от того, может ли операционная система или загрузчик целевой системы использовать этот формат, зависит от этой целевой системы. .
Программы имеют ошибки и нюансы. Форматы файлов имеют версии и несоответствия, вы можете найти какой-нибудь эльфийский ридер форматов файлов только для того, чтобы обнаружить, что он не работает или распечатывает странные вещи при подаче очень хорошего эльфийского файла, который работает в некоторой системе. Почему устанавливаются некоторые флаги? Возможно, эти байты были использованы повторно, или был изменен флаг, или структура данных изменилась, или инструмент использует их по-другому или нестандартным образом (например, mov 20h, ax), а другой несовместимый инструмент не может понять или повезло. и подбирается достаточно близко.
Если спросить, почему вопросы в stackoverflow не очень полезны, то шансы найти человека, написавшего эту вещь, очень и очень низки, больше шансов спросить место, откуда вы взяли инструмент, и проследить, чтобы человек все еще надеялся жив и готов быть обеспокоенным. И 99,999 (много по 9 с)% не существует глобального набора божественных правил, для которых эта вещь была написана под / для. В общем, какой-то чувак просто почувствовал, что именно поэтому они сделали то, что сделали, без реальной причины, лени, ошибки, намеренно пытаясь сломать чей-то инструмент. Вплоть до большого комитета людей с мнением, проголосовавшим за него в определенный день в определенной комнате, и вот почему. (и мы знаем, что получаем, когда проектируем по комитетам или пытаемся написать спецификации, которым никто не соответствует)
Я знаю, что вы работаете на windows, и у меня нет машины windows под рукой и я Linux. Но инструменты gnu / binutils и clang / llvm легко доступны и имеют богатый набор инструментов, таких как readelf, nm, objdump и т. Д. c. Это помогает при изучении вещей, хороший инструмент будет иметь это, по крайней мере, для разработчиков, чтобы они могли отладить вывод инструмента до определенного уровня качества. Люди из GNU создали инструменты и сделали их доступными для всех, и хотя для их разбора и их функций требуется время, они очень важны для вещей, которые вы пытаетесь понять.
Вы НЕ найдете хорошего x86 дизассемблер, все они чушь просто из-за природы зверя. Это набор команд переменной длины, поэтому по определению, если вы не выполняете его, вы не можете правильно его отсортировать. Вы должны дизассемблировать в порядке выполнения из известной хорошей точки входа, чтобы иметь половину шансов, и затем по разным причинам существуют пути кода, которые вы не можете увидеть таким образом (например, подумайте о таблицах переходов или файлах dll или около того). ЛУЧШЕЕ решение - иметь очень точный / совершенный эмулятор / симулятор, запускать код и выполнять все необходимые действия / движения, чтобы он покрывал все пути кода, и иметь этот инструмент для записи инструкций из данных и того, где каждый находится или каждая линейная секция без ветви.
Хорошая сторона этого в том, что сегодня много кода скомпилировано с использованием инструментов, которые не пытаются ничего скрыть. В старые времена по разным причинам вы видели рукописный ассм, который намеренно пытался предотвратить разборку или из-за других факторов (ручное редактирование бинарного образа для видеоигры за день до выставки, go разбирать некоторые классы c roms).
mov r0,#0
cmp r0,#0
jz somewhere
.word 0x12345678
дизассемблер не собирается это выяснять, некоторые могут добавить для этого случай, тогда
mov r0,#0
nop
nop
xor r0,#1
nop
nop
xor r0,#3
xor r0,#2
cmp r0,#0
jz somewhere
.word 0x12345678
и он думает, что данные - это инструкция, для переменной длины, которая является очень трудной для дизассемблера, разрешить приличную проблему, по крайней мере, обнаружит коллизии, где часть команды без кода операции разветвлена, и / или часть кода операции кода обнаруживается позже как дополнительные байты в некоторой другой инструкции , Инструмент не может разрешить это человеку.
Даже с рукой и мипсом и с 32- и 16-битными инструкциями, ris c -v с инструкциями переменного размера, et c ...
очень часто дизассемблер GNU срабатывает с x86.