Поиск…


замечания

Сборка - это общее имя, используемое для многих машиночитаемых форм машинного кода. Он, естественно, сильно отличается между разными CPU (Central Processing Unit), но также и на одном процессоре может существовать несколько несовместимых диалектов Assembly, каждый из которых скомпилирован другим ассемблером, в идентичный машинный код, определенный разработчиком ЦП.

Если вы хотите задать вопрос о своей собственной проблеме сборки, всегда указывайте, какой HW и какой ассемблер вы используете, иначе вам будет сложно ответить на ваш вопрос в деталях.

Изучение сборки одного конкретного процессора поможет изучить основы разных процессоров, но каждая архитектура HW может иметь значительные различия в деталях, поэтому изучение ASM для новой платформы может быть близко к изучению этого с нуля.

Ссылки:

X86 Assembly Wikibook

Вступление

Язык ассемблера - это читаемая человеком форма машинного языка или машинный код, который является фактической последовательностью бит и байтов, на которых работает логика процессора. Обычно людям проще читать и программировать в мнемонике, чем в двоичном, восьмеричном или шестнадцатеричном, поэтому люди обычно пишут код на ассемблере, а затем используют одну или несколько программ для преобразования его в формат машинного языка, понятный процессору.

ПРИМЕР:

mov eax, 4
cmp eax, 5
je point

Ассемблер - это программа, которая читает программу языка ассемблера, анализирует ее и создает соответствующий машинный язык. Важно понимать, что в отличие от языка C ++, который является единственным языком, определенным в стандартном документе, существует много разных языков ассемблера. Каждая архитектура процессора, ARM, MIPS, x86 и т. Д. Имеет другой машинный код и, следовательно, другой язык ассемблера. Кроме того, иногда существует несколько разных языков ассемблера для одной и той же архитектуры процессора. В частности, семейство процессоров x86 имеет два популярных формата, которые часто называют синтаксисом газа ( gas - это имя исполняемого файла для GNU Assembler) и синтаксис Intel (названный в честь создателя семейства процессоров x86). Они различны, но эквивалентны, поскольку обычно можно писать любую данную программу в любом синтаксисе.

Как правило, изобретатель процессора документирует процессор и его машинный код и создает язык ассемблера. Обычно этот конкретный язык ассемблера является единственным используемым, но, в отличие от писателей-компиляторов, пытающихся соответствовать стандарту языка, язык ассемблера, определенный изобретателем процессора, обычно, но не всегда является версией, используемой людьми, которые пишут ассемблеры ,

Существует два основных типа процессоров:

  • CISC (компьютер с множеством инструкций): имеет множество различных и часто сложных инструкций машинного языка

  • RISC (компьютеры с сокращенным набором инструкций): напротив, имеет меньше и более простых инструкций

Для программиста на языке ассемблера разница в том, что процессор CISC может иметь очень много инструкций для изучения, но часто есть инструкции, подходящие для конкретной задачи, в то время как RISC-процессоры имеют меньше и более простых инструкций, но для любой операции может потребоваться программист на языке ассемблера чтобы написать больше инструкций, чтобы сделать то же самое.

Другие компиляторы языка программирования иногда производят ассемблер сначала, который затем компилируется в машинный код, вызывая ассемблер. Например, gcc использует собственный газовый ассемблер на заключительной стадии компиляции. Произведенный машинный код часто хранится в объектных файлах, которые могут быть связаны с исполняемым файлом программой-компоновщиком.

Полная «toolchain» часто состоит из компилятора, ассемблера и компоновщика. Затем можно использовать этот ассемблер и компоновщик непосредственно для написания программ на ассемблере. В мире GNU пакет binutils содержит сборщик и компоновщик и связанные с ним инструменты; тем, кто интересуется только программированием на языке ассемблера, не нужны gcc или другие пакеты компилятора.

Малые микроконтроллеры часто программируются исключительно на языке ассемблера или в сочетании с языком ассемблера и одним или несколькими языками более высокого уровня, такими как C или C ++. Это делается потому, что часто можно использовать конкретные аспекты архитектуры набора команд для таких устройств, чтобы писать более компактный и эффективный код, чем это было бы возможно на языке более высокого уровня, и такие устройства часто имеют ограниченную память и регистры. Многие микропроцессоры используются во встроенных системах, которые являются устройствами, отличными от компьютеров общего назначения, в которых встроен микропроцессор. Примерами таких встроенных систем являются телевизоры, микроволновые печи и блок управления двигателем современного автомобиля. Многие такие устройства не имеют клавиатуры или экрана, поэтому программист обычно записывает программу на компьютер общего назначения, запускает кросс-ассемблер (так называемый, потому что такой ассемблер создает код для другого типа процессора, чем тот, на котором он запускается ) и / или кросс-компилятор и сшивающий агент для создания машинного кода.

Для таких инструментов существует множество поставщиков, которые так же разнообразны, как и процессоры, для которых они производят код. Многие, но не все процессоры также имеют решение с открытым исходным кодом, такое как GNU, sdcc, llvm или другое.

Машинный код

Машинный код является термином для данных, в частности, собственного машинного формата, которые непосредственно обрабатываются машиной - обычно процессором, называемым CPU (Central Processing Unit).

Общая архитектура компьютера (архитектура фон Неймана ) состоит из процессора общего назначения (ЦП), памяти общего назначения - хранения как программ (ROM / RAM), так и обработанных данных и устройств ввода / вывода (устройств ввода / вывода).

Основным преимуществом этой архитектуры является относительная простота и универсальность каждого из компонентов - по сравнению с компьютерными машинами (с жесткой проводной программой в конструкции машины) или конкурирующие архитектуры (например, архитектура Гарварда, разделяющая память программы из памяти данные). Недостаток - это немного худшая общая производительность. В долгосрочной перспективе универсальность допускает гибкое использование, которое, как правило, перевешивает стоимость исполнения.

Как это связано с машинным кодом?

Программа и данные хранятся на этих компьютерах в виде чисел в памяти. Не существует подлинного способа рассказать код от данных, поэтому операционные системы и операторы компьютеров дают подсказки CPU, на которых начальная точка памяти запускает программу после загрузки всех номеров в память. Затем ЦПУ считывает инструкцию (число), хранящуюся в точке входа, и обрабатывает ее строго, последовательно считывая следующие числа в качестве дальнейших инструкций, если сама программа не сообщит ЦП продолжать выполнение в другом месте.

Например, два 8-битных номера (8 бит, сгруппированные вместе, равны 1 байту, это целое число без знака в диапазоне 0-255): 60 201 , когда он выполняется как код на Zilog Z80 CPU, обрабатывается как две инструкции: INC a (приращение значения в регистре a на единицу) и RET (возврат из подпрограммы, указание CPU для выполнения команд из разных частей памяти).

Чтобы определить эту программу, человек может ввести эти числа некоторым редактором памяти / файла, например, в шестнадцатеричном редакторе, как два байта: 3C C9 (десятичные числа 60 и 201, записанные в кодировке base 16). Это будет программирование в машинный код .

Чтобы облегчить задачу программирования ЦП для людей, были созданы программы Ассемблера , способные читать текстовый файл, содержащий что-то вроде:

subroutineIncrementA:
    INC   a
    RET

dataValueDefinedInAssemblerSource:
    DB    60          ; define byte with value 60 right after the ret

вывод байтовой последовательности шестнадцатеричных чисел 3C C9 3C , завернутый с дополнительными дополнительными номерами, определенными для целевой платформы: обозначение, какая часть такого двоичного кода является исполняемым кодом, где находится точка входа для программы (первая инструкция), какие части закодированы данные (не исполняемые) и т. д.

Обратите внимание, как программист указал последний байт со значением 60 как «данные», но с точки зрения ЦП он ничем не отличается от INC a байта. Это зависит от выполняемой программы, чтобы правильно перемещать процессор по байтам, подготовленным в виде инструкций, и обрабатывать байты данных только как данные для инструкций.

Такой вывод обычно хранится в файле на устройстве хранения, загруженном позже операционной системой ( операционная система - машинный код, уже запущенный на компьютере, помогающий манипулировать компьютером ) в память перед ее выполнением, и, наконец, указывая CPU на точка входа в программу.

ЦП может обрабатывать и выполнять только машинный код, но любой контент памяти, даже случайный, может обрабатываться как таковой, хотя результат может быть случайным, начиная от « сбоя », обнаруженного и обрабатываемого ОС, до случайной очистки данных от ввода / Вывода или повреждение чувствительного оборудования, подключенного к компьютеру (не общий случай для домашних компьютеров :)).

За аналогичным процессом следуют многие другие языки программирования высокого уровня, скомпилировав исходные тексты (читаемые пользователем текстовые формы) в числа, представляющие машинный код (собственные инструкции CPU), или в случае интерпретируемых / гибридных языков в некоторые общие языковой код виртуальной машины, который далее декодируется в собственный машинный код во время выполнения интерпретатором или виртуальной машиной.

Некоторые компиляторы используют Ассемблер как промежуточную стадию компиляции, сначала переводя исходный код в форму Ассемблера, затем запуская инструмент ассемблера, чтобы получить из него окончательный код машины (пример GCC: запустите gcc -S helloworld.c чтобы получить версию ассемблера программы C helloworld.c ).

Привет, мир для Linux x86_64 (Intel 64 бит)

section .data
    msg db "Hello world!",10      ; 10 is the ASCII code for a new line (LF)

section .text
    global _start

_start:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, 13
    syscall
    
    mov rax, 60
    mov rdi, 0
    syscall

Если вы хотите выполнить эту программу, вам сначала понадобится Netwide Assembler , nasm , потому что этот код использует свой синтаксис. Затем используйте следующие команды (предполагая, что код находится в файле helloworld.asm ). Они необходимы для сборки, компоновки и выполнения, соответственно.

  • nasm -felf64 helloworld.asm
  • ld helloworld.o -o helloworld
  • ./helloworld

В коде используется sys_write вызов sys_write Linux. Здесь вы можете увидеть список всех системных вызовов для архитектуры x86_64. Когда вы также берете страницы руководства для записи и выхода во внимание, вы можете перевести указанную выше программу на C, которая делает то же самое и становится гораздо более читаемой:

#include <unistd.h>

#define STDOUT 1

int main()
{
    write(STDOUT, "Hello world!\n", 13);
    _exit(0);
}

Для компиляции и компоновки (первая) необходимы только две команды и выполнение:

  • gcc helloworld_c.c -o helloworld_c .
  • ./helloworld_c

Hello World для OS X (x86_64, синтаксис газа Intel)

.intel_syntax noprefix

.data

.align 16
hello_msg:
    .asciz "Hello, World!"

.text

.global _main
_main:
    push rbp
    mov rbp, rsp

    lea rdi, [rip+hello_msg]
    call _puts

    xor rax, rax
    leave
    ret

Собрать:

clang main.s -o hello
./hello

Заметки:

Выполнение сборки x86 в Visual Studio 2015

Шаг 1. Создайте пустой проект через File -> New Project .

введите описание изображения здесь

Шаг 2 : Щелкните правой кнопкой мыши проектное решение и выберите « Построить зависимости» -> «Настроить настройки» .

Шаг 3 : Установите флажок «.masm» .

введите описание изображения здесь

Шаг 4 : Нажмите кнопку «ОК» .

Шаг 5 : Создайте файл сборки и введите следующее:

.386
    .model small
        .code

            public main
                main proc

                    ; Ends program normally

                    ret
                main endp
            end main

Шаг 6 : Скомпилируйте!

введите описание изображения здесь



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow