2010-08-08 2 views
73

Я смущен о машинный код и собственный код.В чем разница между собственным кодом, машинным кодом и кодом сборки?

В чем разница между ними? Они одинаковы?

+1

У меня есть вопрос относительно этого вопроса. Этот вопрос подпадает под требование StackOverflow? afaik это не так, но в то же время такой вопрос очень полезен/информативен. Предполагая, что этот тип вопроса не разрешен, где мы должны задавать такие вопросы, если не здесь? – sami1592

ответ

2

В .NET сборки содержат код MS Intermediate Language (MSIL, иногда CIL).
Это как машинный код «высокого уровня».

При загрузке MSIL скомпилирован JIT compiler в собственный код (машинный код Intel x86 или x64).

5

Собственный код и машинный код - это то же самое - фактические байты, которые выполняет ЦП.

Код сборки имеет два значения: один - это машинный код, переведенный в более удобочитаемую форму (с байтами для инструкций, переведенных в короткие словарные мнемоники, такие как «JMP» (который «перескакивает» на другое место в коде). Другим является байт-код IL (байты команд, которые компиляторы, такие как C# или VB generate, которые в конечном итоге будут переведены в машинный код, но еще не созданы), который живет в DLL или EXE.

113

действительно немного запутывают, потому что они иногда используются непоследовательно.

Код машины: Это наиболее четко определенный. Это код, который нам это инструкции байтового кода, которые ваш процессор (физический кусок металла, который выполняет фактическую работу) понимает и выполняет непосредственно. Весь другой код должен быть переведен или преобразован в машинный код, прежде чем ваша машина сможет его выполнить.

Родной код: Этот термин иногда используется в тех местах, где машинный код (см выше) означали. Однако иногда это также означает неуправляемый код (см. Ниже).

Неуправляемый код и управляемый код:неуправляемых код ссылается на код, написанный на языке программирования типа C или C++, который составляется непосредственно в машинный код . Он контрастирует с управляемым кодом, который написан на C#, VB.NET, Java или аналогичен и выполнен в виртуальной среде (например, .NET или JavaVM), которая «имитирует» процессор в программном обеспечении. Основное различие заключается в том, что управляемый код «управляет» ресурсами (в основном выделение памяти) для вас, используя сбор мусора и сохраняя ссылки на объекты непрозрачными. Неуправляемый код - это тот код, который требует, чтобы вы вручную выделяли и де-выделяли память, иногда вызывая утечку памяти (когда вы забываете де-распределять), а иногда и ошибки сегментации (когда вы слишком быстро выделяете выделение). Неуправляемый также обычно подразумевает отсутствие проверок времени выполнения для общих ошибок, таких как разуплотнение нулевого указателя или переполнение границ массива.

Строго говоря, большинство динамически типизированных языков, таких как Perl, Python, PHP и Ruby, также являются управляемым кодом. Тем не менее, они обычно не описываются как таковые, что показывает, что управляемый код на самом деле является некоторым маркетинговым термином для действительно больших, серьезных, коммерческих программных сред (.NET и Java).

Код сборки: Этот термин обычно относится к типу исходного кода, который люди пишут, когда они действительно хотят писать байт-код. Ассемблер - это программа, которая превращает этот исходный код в настоящий байтовый код. Это не компилятор , потому что преобразование 1 к 1. Однако этот термин неоднозначен в отношении того, какой тип байтового кода используется: его можно было бы управлять или неуправляемым. Если он неуправляемый, полученный байт-код равен машинный код. Если он управляется, это приводит к тому, что байтовый код используется за кадром с помощью виртуальной среды, такой как .NET. Управляемый код (например, C#, Java) скомпилирован в этот специальный язык байтового кода, который в случае .NET называется Common Intermediate Language (CIL) и в Java называется Байт-код Java. Обычно обычный программист не имеет доступа к этому коду или для записи на этом языке напрямую, но когда люди делают это, они часто ссылаются на него как на код сборки , потому что они используют ассемблер , чтобы превратить его в байтовый код ,

+0

C++ может компилироваться в машинный код, но он очень часто компилируется в другие форматы, такие как exe, которые будут запускаться с операционной системой. –

+0

Существуют языки, которые поддерживают сбор мусора и непрозрачные ссылки, которые обычно компилируются в машинный код. Большинство серьезных реализаций Common Lisp делают это. То, что вы говорите, может относиться к языкам, поддерживающим Microsoft, но есть более скомпилированные языки, чем поддерживаемые Visual Studio. –

+1

@CrazyJugglerDrummer: код, содержащийся в EXE-файлах, сгенерированных компиляторами C++, по-прежнему является машинным кодом. @David Thornley: Я упомянул значительно больше языков, чем только тех, но я не хотел усложнять вопросы, упоминая каждую неясную странность. – Timwi

38

Что вы видите, когда используете Debug + Windows + Disassembly при отладке программы на C#, является хорошим руководством для этих условий. Вот аннотированный вариант, когда я скомпилировать программу «привет мир», написанный на C# в конфигурации выпуска с оптимизацией JIT включен:

 static void Main(string[] args) { 
      Console.WriteLine("Hello world"); 
00000000 55    push  ebp       ; save stack frame pointer 
00000001 8B EC    mov   ebp,esp      ; setup current frame 
00000003 E8 30 BE 03 6F call  6F03BE38      ; Console.Out property getter 
00000008 8B C8    mov   ecx,eax      ; setup "this" 
0000000a 8B 15 88 20 BD 02 mov   edx,dword ptr ds:[02BD2088h] ; arg = "Hello world" 
00000010 8B 01    mov   eax,dword ptr [ecx]   ; TextWriter reference 
00000012 FF 90 D8 00 00 00 call  dword ptr [eax+000000D8h]  ; TextWriter.WriteLine() 
00000018 5D    pop   ebp       ; restore stack frame pointer 
     } 
00000019 C3    ret          ; done, return 

правой кнопкой мыши окно и отметьте «Показывать код Bytes», чтобы получить подобный дисплей.

Столбец слева - адрес машинного кода. Его значение подделывается отладчиком, код фактически находится где-то в другом месте. Но это может быть где угодно, в зависимости от местоположения, выбранного компилятором JIT, поэтому отладчик только начинает нумерацию адресов от 0 в начале метода.

Вторая колонка машинный код. Фактические 1s и 0s, которые выполняет CPU. Машинный код, как и здесь, обычно отображается в шестнадцатеричном формате. Иллюстративным может быть то, что 0x8B выбирает инструкцию MOV, дополнительные байты должны сообщать CPU точно, что нужно переместить. Также обратите внимание на два варианта команды CALL: 0xE8 - прямой вызов, 0xFF - инструкция косвенного вызова.

Третий столбец код сборки. Сборка - это простой язык, предназначенный для упрощения написания машинного кода. Он сравнивается с C#, скомпилированным с IL. Компилятор, используемый для перевода ассемблерного кода, называется «ассемблером». Вероятно, на вашем компьютере есть ассемблер Microsoft, его исполняемое имя - ml.exe, ml64.exe для 64-разрядной версии. Существуют две распространенные версии языков ассемблера. Тот, который вы видите, тот, который использует Intel и AMD. В мире с открытым исходным кодом обычная сборка в обозначениях AT & T. Синтаксис языка сильно зависит от типа процессора, для которого было написано, язык ассемблера для PowerPC сильно отличается.

Хорошо, что касается двух терминов в вашем вопросе. «Родной код» - это нечеткий термин, он нередко используется для описания кода на неуправляемом языке. По-видимому, инструктивный способ - посмотреть, какой машинный код генерируется компилятором C. Это «привет мир» версия в C:

int _tmain(int argc, _TCHAR* argv[]) 
{ 
00401010 55    push  ebp 
00401011 8B EC   mov   ebp,esp 
    printf("Hello world"); 
00401013 68 6C 6C 45 00 push  offset ___xt_z+128h (456C6Ch) 
00401018 E8 13 00 00 00 call  printf (401030h) 
0040101D 83 C4 04   add   esp,4 
    return 0; 
00401020 33 C0   xor   eax,eax 
} 
00401022 5D    pop   ebp 
00401023 C3    ret 

Я не аннотацию, в основном потому, что это так похож на машинный код, генерируемый C# программы. Вызов функции printf() сильно отличается от вызова Console.WriteLine(), но все остальное примерно одинаково.Также обратите внимание, что отладчик теперь генерирует реальный адрес машинного кода и что он немного умнее о символах. Побочный эффект генерации отладочной информации после часто генерирует машинный код, например неуправляемые компиляторы. Следует также упомянуть, что я отключил несколько вариантов оптимизации машинного кода, чтобы сделать машинный код похожим. Компиляторы C/C++ имеют гораздо больше времени для оптимизации кода, результат часто трудно интерпретировать. И очень трудно отлаживать.

Ключевым моментом здесь является очень Небольшие различия между машинным кодом, сгенерированным на управляемом языке компилятором JIT и машинным кодом, сгенерированным компилятором нативного кода. Что является основной причиной того, что язык C# может быть конкурентоспособным с компилятором собственного кода. Единственное реальное различие между ними - это вызовы функций поддержки. Многие из них реализованы в среде CLR. И это вращается вокруг сборщика мусора.

Смежные вопросы