Основы программирования на языке Assembler под архитектуру RISC-V

Инструменты разработчика

Разбить на страницы
Показывать лекцию целиком

Эта Лекция посвящена настройке окружения и инструментов разработчика для написания программного кода на языке Assembler для процессора RISC-V и его запуска на компьютере. Существует достаточно большое количество различных программ и утилит, позволяющих писать и тестировать небольшие программы, которые достаточно сильно отличаются своей функциональностью. В этой Лекции мы рассмотрим небольшую часть таких инструментов, позволяющих писать код для микропроцессоров RISC-V, транслировать его в исполняемые модули, а также запускать и отлаживать его, работая при этом на обычных ПК с ОС Linux. В частности, будут рассмотрены: симулятор Ripes, эмулятор аппаратного обеспечения Qemu с набором инструментов GNU toolchain, одноплатный компьютер StarVision VisionFive.

Вам потребуется ОС Linux (предпочтительно - Debian) в качестве хоста для запуска симуляторов. Вы также можете использовать WSLWSL (Windows Subsystem for Linux) - подсистема ОС Windows, которая позволяет разработчикам запускать среду GNU/Linux с большинством программ командной строки, служебных программ и приложений непосредственно в Windows без каких-либо изменений и необходимости использовать традиционную виртуальную машину или двойную загрузку. (Windows Subsystem for Linux) или macOS, однако использование этих средств здесь рассматриваться не будет.

После прохождения этого раздела вы будете знать, как:

  • устанавливать и использовать любое рассмотренное в разделе ПО;
  • знать и уметь применять наборы инструментов GNU (GNU toolchain) для сборки приложений.
  • Набор инструментов разработчика

    Обзор наборов инструментов

    На рис.2.1. показан процесс того, как происходит преобразование исходного кода программы в исполняемый бинарный файл. Шаги этого процесса обычно скрыты внутри специального ПО, которое называется интегрированная среда разработки (integrated development environment, IDE). Работая в таких средах, вы просто печатаете кода в редакторе и сохраняете его в текстовом виде в файле исходного кода. Этот файл передаётся ассемблеру (или кросс-ассемблеру, специальной программе, позволяющей, находясь на компьютере одной архитектуры, компилировать бинарный код для совершенно другой архитектуры), который переводит его содержимое в так называемый объектный файл - бинарный код, в точности соответствующий машинному представлению инструкций из транслируемого файла, но при этом не содержащий дополнительную информацию, необходимую для запуска и исполнения программы операционной системой. Для преобразования объектного файла в исполняемый используется программа, которая называется компоновщик (или линкер, от англ. linker). Компоновщик принимает на вход объектный файл (или группу объектных файлов, если исходных файлов в проекте компилировалось несколько) и скрипт линковки - специальный набор указаний о том, как сегменты, описанные в исходном коде, должны размещаться в памяти при загрузке программы операционной системой и её исполнении. Результатом этой процедуры является исполняемый файл.

    (рис 2.1) Процесс преобразования исходного кода в исполняемый

    Набор инструментов (toolchain) включает в себя все описанные выше утилиты, конфигурационные файлы и прочие файлы и программы, необходимые для перевода текстового представления исходного кода в бинарный исполняемый файл.

    Симулятор Ripes

    Ripes - симулятор, который позволяет отслеживать выполнение машинного (исполняемого) кода на процессорах с архитектурами RV32IMC и RV64IMC (суффиксы IMC показывают расширения архитектуры, добавляющие новую функциональность, и будут рассмотрены позднее в третьей части). Симулятор Ripes доступен по ссылке: http://https://github.com/mortbopet/Ripes, на сайте имеется возможность скачать исполняемые файлы для ОС Linux, Windows и macOS. На рис.2.2. показан пользовательский интерфейс симулятора Ripes. Слева расположен редактор программного кода на языке Assembler, по центру - сгенерированный машинный код, справа расположено коно, показывающее состояние регистров процессора, а внизу расположена консоль, в которую перенаправляется вывод программы и служебная информация. Помимо показанного интерфейса Ripes может визуализировать состояние процессора и его компонентов, кэш, память и простой ввод/вывод. Симулятор Ripes очень полезен для быстрого погружения в программирование на языке Assembler.

    (рис 2.2) Интерфейс симулятора Ripes, запущенного под MacOS

    Эмулятор Qemu и набор инструментов GNU-toolchain для процессора RISC-V

    Существуют различные способы обеспечения эмуляции систем на основе микропроцессоров RISC-V благодаря использованию Qemu (доступен по ссылке http://https://www.qemu.org) - эмулятора аппаратного обеспечения, который позволяет эмулировать как целые системы, так и отдельные программы в так называемом "пользовательском режиме" (англ. "user-mode"). В случае эмуляции целой системы операционная система запускается так, как будто она действительно работает на реальном (а не на эмулируемом) железе. При запуске приложений в пользовательском режиме (user-mode emulation) отдельная программа может быть запущена на текущей ОС, даже если она была скомпилирована под другую архитектуру.

    В рассматриваемых примерах мы будем считать, что работа идёт на машине с установленной ОС Debian Linux. С более детальной информацией можно ознакомиться на сайте "Debian wiki for RISC-V" по адресу http://https://wiki.debian.org/RISC-V. Далее будет использоваться установка готовых пакетов с использованием менеджера пакетов Debian Advanced Packaging Tool (apt), тем не менее, по адресу http://https://github.com/riscv-collab/riscv-gnu-toolchain располагается инструкция о том, как можно собрать рассматриваемые утилиты из исходников.

    Для установки Qemu на компьютер наберите в консоли следующий набор команд:

    sudo apt install qemu-system-misc qemu-user-static binfmt-support opensbi u-boot-qemu
    

    Теперь у вас появилась возможность эмулировать систему на процессоре RISC-V. Введите команду:

    qemu-riscv64-static -help  
    

    Вы должны получить в ответ текст, который начинается со следующей строки:

    usage: qemu-riscv64 [options] program [arguments...]
    ...
    

    Следующим шагом идёт установка набора инструментов кросс-компилятора для сборки программ. Введите следующие команды:

    sudo apt install gcc-riscv64-linux-gnu
    sudo ln -s /usr/riscv64-linux-gnu/lib/ld-linux-riscv64-lp64d.so.1 /lib
    

    И следом за ними команду:

    riscv64-linux-gnu-as --version
    GNU assembler (GNU Binutils for Debian) 2.35.2
    ...
    

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

    После установки эмулятора и набора средств кросс-компилятора необходимо установить отладчик для процессоров с архитектурой RISC-V. В зависимости от версии ОС Debian Linux возможно потребуется поставить нестабильные версии пакетов (для более новых версий ОС).

    Отладчик с поддержкой приложений для архитектуры RISC-V называется gdb-multiarch и может быть установлен следующей командой:

    sudo apt install gdb-multiarch
    

    Пример использования набора инструментов

    В качестве примера использования установленного выше набора инструментов необходимо написать исходный файл на языке Assembler. Для этого необходимо открыть текстовый редактор (например, nano или vi для работы в консоли, а также gedit, kate, sublime или code для работы в графическом режиме) и ввести следующий код, после чего необходимо сохранить его с именем example.s.

    .text 
    .globl _start
    _start:
          addi x10, x0,  7
          addi x17, x0, 93
          ecall
    

    Для сборки и запуска программы, а также проверки результата её исполнения необходимо ввести следующую последовательность команд:

    riscv64-linux-gnu-as -o example.o example.s 
    riscv64-linux-gnu-ld -o example example.o
    qemu-riscv64-static example
    echo $? 
    7
    

    Первая команда вызывает для написанного исходного кода компилятор программ на языке Assembler, который транслирует исходный код в машинные инструкции объектного файла. Вторая команда вызывает компоновщик, который дополняет код объектного файла не обходимыми инструкциями и генерирует исполняемый файл с именем example. Третья команда запускает скомпилированный бинарный исполняемый файл на исполнение в эмуляторе архитектуры RISC-V. Поскольку этот код ничего не делает, кроме как завершает работу с указанным кодом возврата, на экране в результате выполнения программы ничего не будет выведено. Для того, чтобы увидеть код возврата последней вызываемой команды или программы, воспользуемся командой командного интерпретатора bash (строка 4). В качестве результата в консоли должно напечататься число 7.

    Помимо компилятора и компоновщика, набор инструментов также содержит утилиту objdump (файл riscv64-linux-gnu-objdump) - дизассемблер, который позволяет провести обратное описанным выше операциям действие и на основе скомпилированного бинарного кода получить набор инструкций на языке Assembler. Пример вызова утилиты дизассемблирования показан ниже:

    riscv64-linux-gnu-objdump -sd example
    example:     file format elf64-littleriscv
    
    Contents of section .text:
     100b0 13057000 9308d005 73000000           ..p.....s...    
    Contents of section .riscv.attributes:
     0000 412d0000 00726973 63760001 23000000  A-...riscv..#...
     0010 05727636 34693270 305f6d32 70305f61  .rv64i2p0_m2p0_a
     0020 3270305f 66327030 5f643270 3000      2p0_f2p0_d2p0.  
    
    Disassembly of section .text:
    
    00000000000100b0 <_start>:
       100b0:	00700513          	li	a0,7
       100b4:	05d00893          	li	a7,93
       100b8:	00000073          	ecall
    

    Первая часть вывода objdump показывает содержимое файла в шестнадцатеричном виде (за это отвечает передаваемый программе ключ -s), вторая часть - собственно дизассемблированный код (ключ -d). К этому примеру мы ещё вернёмся позднее, сейчас он служит просто демонстрацией работоспособности установленных пакетов набора инструментов.

    Наконец, можно использовать отладчик. Для этого введите следующие команды:

    qemu-riscv64-static -g 1234 example 
    gdb-multiarch example
    ...
    Reading symbols from example...
    (No debugging symbols found in example)
    (gdb) target remote :1234
    Remote debugging using :1234
    0x00000000000100b0 in _start ()
    (gdb) display /3i $pc
    1: x/3i $pc
    => 0x100b0 <_start>:	li	a0,7
       0x100b4 <_start+4>:	li	a7,93
       0x100b8 <_start+8>:	ecall
    (gdb) si
    0x00000000000100b4 in _start ()
    1: x/3i $pc
    => 0x100b4 <_start+4>:	li	a7,93
       0x100b8 <_start+8>:	recall
       0x100bc:	.2byte	0x2d41
    (gdb) si
    0x00000000000100b8 in _start ()
    1: x/3i $pc
    => 0x100b8 <_start+8>:	ecall
       0x100bc:	.2byte	0x2d41
       0x100be:	.2byte	0x0
    (gdb) c
    Continuing.
    [Inferior 1 (process 1) exited with code 07]
    

    После запуска эмулятора с подключением возможности удалённой отладки через порт 1234, запускается программа-отладчик gdb-multiarch. Отладчик подключается к удалённой системе благодаря команде target remote с указанием требуемого порта (1234). Команда display /3i $pc показывает 3 следующие за текущей инструкции, команда si предписывает выполнить одну инструкцию (сделать один шаг по коду), а команда c даёт указание продолжить выполнение программы. Чтобы выйти из отладчика, нужно ввести команду q.

    Запуск Visual Studio Code и PlatformIO вместе с Qemu и пакетом инструментов RISC-V GNU Toolchain

    Помимо работы в командной строке, также возможно настроить работу в интегрированной среде разработки. В качестве примера рассмотрим, как можно использовать среду разработки Visual Studio Code (доступна по адресу http://https://code.visualstudio.com) с установленным расширением PlatformIO, пример работы которого показан на рис.2.3 (расширение доступно по адресу http://https://platformio.org).

    Откройте терминал в среде VS Code, находясь внутри PlatformIO и выбрав пункт меню QUOT;New terminalQUOT;, и введите следующую команду:

    pio platform install https://github.com/e1d1-academy/platform-linux_riscv.git
    

    Также можно импортировать тестовый проект, как показано в следующем разделе, и проверить, запускается ли он корректно.

    (рис 2.3) Пример интерфейса среды разработки VS Code с расширением PlatformIO, работающим в режиме отладки

    Примеры к этому курсу выложены на GitHub, в каждом из каталогов примеров лежит файл platformio.ini. Эти файлы подготовлены для запуска примеров в Qemu с использованием пользовательского режима.

    Пример работы в Visual Studio Code с расширением PlatformIO

    Для получения окружения для программирования на языке Assembler в расширении PlatformIO среды разработки VS Code наберите к консоли расширения PlatformIO команду:

    https://github.com/e1d1-academy/platform-linux_riscv.git
    

    В расширении PlatformIO есть возможность работать под различны платформы, и если в диалоге вы наберёте "Linux", вам будет доступно окружение для ОС Linux для архитектуры RISC-V.

    В появившемся списке вы можете кликнуть на требуемое окружение и увидите, что там есть раздел с примерами, которые можно импортировать и попробовать их в работе. Все примеры идут с конфигурационными файлами, которые позволяют сгенерировать шаблон приложения с вашим собственным кодом на языке Assembler. Этот код можно компилировать прямо из среды VS Code, а также запускать его как в обычном режиме, так и в режиме отладки.

    В результате работы показанного примера на экран выводится фраза "Hello World!".

    Мини-компьютер StarFive VisionFive и набор инструментов RISC-V GNU Toolchain

    Одноплатный компьютер StarFive VisionFive поставляется с двухъядерным RISC-V процессором с архитектурой RV64IMAFDC. По умолчанию поставляется с ОС Fedora Linux и предустановленным набором инструментов. Этот одноплатный компьютер можно использовать как "живую" аппаратную платформу с процессором RISC-V и работать на нём без необходимости устанавливать эмуляторов, симуляторов и кросс-ассемблеров.

    На рис.2.4 показан скриншот рабочего стола xfce4 с четырьмя открытыми терминалами, запущенного на плате VisionFive.

    (рис 2.4) Рабочий стол Linux на плате VisionFile с запущенными терминалами с набором инструментов GNU toolchain

    В левом верхнем углу расположен первый терминал, в нём открыт текстовый редактор nano с исходным кодом файла example.s. Чтобы воспроизвести это, наберите в консоли команду:

    nano example.s
    

    Затем вставьте скопированный программный код (или напишите его самостоятельно) и запишите содержимое файла на диск, нажав сочетание клавиш ^O (Сtrl+o).

    Во втором терминале, расположенном слева посередине, показан результат сборки и линковки с последующей распечаткой дизассемблированного кода, выполненной с использованием утилиты objdump, а также результат запуска программы - демонстрация возвращаемого программой кода возврата. Отладочная информация внесена в исполняемый бинарный файл благодаря ключу "-g" компилятора. Для воспроизведения этих результатов введите в консоли команды:

    as -g -o example.o example.s
    ld -o example example.o
    objdump -d example
    ./example
    echo $?
    

    В третьем терминале, расположенном слева внизу, показана работа отладчика. Для воспроизведения введите в консоли команду:

    gdb example
    

    После запуска отладчика были использованы следующие управляющие команды: "layout src" - показать исходный код, "b 5" - установить точку останова на строке 5, "r" - запустить код на исполнение до точки останова, "info reg x107quot; - показать содержимое регистра x10:

    (gdb) layout src
    (gdb) b 5
    (gdb) r
    (gdb) info reg x10
    

    Из отладчика можно выйти, набрав команду "q".

    И, наконец, четвёртый терминал, расположенный справа, выводит информацию о процессоре.

    Исходные коды примеров:

    Исходные коды доступны в репозитории github по адресу: http://https://github.com/U2654/LFD117x

    Контрольные вопросы

  • Чем объектный файл отличается от исполняемого?
  • В чём отличие ассемблера от языка ассемблера?
  • Как компоновщик получает исполняемый файл из нескольких объектных?
  • Состояние каких модулей процессора позволяет отслеживать Ripes?
  • Чем симулятор отличается от эмулятора?
  • В каких режимах может работать Qemu?
  • Как с помощью objdump посмотреть информацию об исполняемом файле?
  • Как отладчиком подключиться к запущенному процессу в Qemu?
  • Какие команды отладчика необходимо использовать для выполнения программы?
  • Какие команды позволяют просматривать значения переменных/регистров в процессе отладки?
  • Страницы:

    Эта Лекция посвящена настройке окружения и инструментов разработчика для написания программного кода на языке Assembler для процессора RISC-V и его запуска на компьютере. Существует достаточно большое количество различных программ и утилит, позволяющих писать и тестировать небольшие программы, которые достаточно сильно отличаются своей функциональностью. В этой Лекции мы рассмотрим небольшую часть таких инструментов, позволяющих писать код для микропроцессоров RISC-V, транслировать его в исполняемые модули, а также запускать и отлаживать его, работая при этом на обычных ПК с ОС Linux. В частности, будут рассмотрены: симулятор Ripes, эмулятор аппаратного обеспечения Qemu с набором инструментов GNU toolchain, одноплатный компьютер StarVision VisionFive.

    Вам потребуется ОС Linux (предпочтительно - Debian) в качестве хоста для запуска симуляторов. Вы также можете использовать WSLWSL (Windows Subsystem for Linux) - подсистема ОС Windows, которая позволяет разработчикам запускать среду GNU/Linux с большинством программ командной строки, служебных программ и приложений непосредственно в Windows без каких-либо изменений и необходимости использовать традиционную виртуальную машину или двойную загрузку. (Windows Subsystem for Linux) или macOS, однако использование этих средств здесь рассматриваться не будет.

    После прохождения этого раздела вы будете знать, как:

  • устанавливать и использовать любое рассмотренное в разделе ПО;
  • знать и уметь применять наборы инструментов GNU (GNU toolchain) для сборки приложений.
  • Набор инструментов разработчика

    Обзор наборов инструментов

    На рис.2.1. показан процесс того, как происходит преобразование исходного кода программы в исполняемый бинарный файл. Шаги этого процесса обычно скрыты внутри специального ПО, которое называется интегрированная среда разработки (integrated development environment, IDE). Работая в таких средах, вы просто печатаете кода в редакторе и сохраняете его в текстовом виде в файле исходного кода. Этот файл передаётся ассемблеру (или кросс-ассемблеру, специальной программе, позволяющей, находясь на компьютере одной архитектуры, компилировать бинарный код для совершенно другой архитектуры), который переводит его содержимое в так называемый объектный файл - бинарный код, в точности соответствующий машинному представлению инструкций из транслируемого файла, но при этом не содержащий дополнительную информацию, необходимую для запуска и исполнения программы операционной системой. Для преобразования объектного файла в исполняемый используется программа, которая называется компоновщик (или линкер, от англ. linker). Компоновщик принимает на вход объектный файл (или группу объектных файлов, если исходных файлов в проекте компилировалось несколько) и скрипт линковки - специальный набор указаний о том, как сегменты, описанные в исходном коде, должны размещаться в памяти при загрузке программы операционной системой и её исполнении. Результатом этой процедуры является исполняемый файл.

    (рис 2.1) Процесс преобразования исходного кода в исполняемый

    Набор инструментов (toolchain) включает в себя все описанные выше утилиты, конфигурационные файлы и прочие файлы и программы, необходимые для перевода текстового представления исходного кода в бинарный исполняемый файл.

    Симулятор Ripes

    Ripes - симулятор, который позволяет отслеживать выполнение машинного (исполняемого) кода на процессорах с архитектурами RV32IMC и RV64IMC (суффиксы IMC показывают расширения архитектуры, добавляющие новую функциональность, и будут рассмотрены позднее в третьей части). Симулятор Ripes доступен по ссылке: http://https://github.com/mortbopet/Ripes, на сайте имеется возможность скачать исполняемые файлы для ОС Linux, Windows и macOS. На рис.2.2. показан пользовательский интерфейс симулятора Ripes. Слева расположен редактор программного кода на языке Assembler, по центру - сгенерированный машинный код, справа расположено коно, показывающее состояние регистров процессора, а внизу расположена консоль, в которую перенаправляется вывод программы и служебная информация. Помимо показанного интерфейса Ripes может визуализировать состояние процессора и его компонентов, кэш, память и простой ввод/вывод. Симулятор Ripes очень полезен для быстрого погружения в программирование на языке Assembler.

    (рис 2.2) Интерфейс симулятора Ripes, запущенного под MacOS

    Эмулятор Qemu и набор инструментов GNU-toolchain для процессора RISC-V

    Существуют различные способы обеспечения эмуляции систем на основе микропроцессоров RISC-V благодаря использованию Qemu (доступен по ссылке http://https://www.qemu.org) - эмулятора аппаратного обеспечения, который позволяет эмулировать как целые системы, так и отдельные программы в так называемом "пользовательском режиме" (англ. "user-mode"). В случае эмуляции целой системы операционная система запускается так, как будто она действительно работает на реальном (а не на эмулируемом) железе. При запуске приложений в пользовательском режиме (user-mode emulation) отдельная программа может быть запущена на текущей ОС, даже если она была скомпилирована под другую архитектуру.

    В рассматриваемых примерах мы будем считать, что работа идёт на машине с установленной ОС Debian Linux. С более детальной информацией можно ознакомиться на сайте "Debian wiki for RISC-V" по адресу http://https://wiki.debian.org/RISC-V. Далее будет использоваться установка готовых пакетов с использованием менеджера пакетов Debian Advanced Packaging Tool (apt), тем не менее, по адресу http://https://github.com/riscv-collab/riscv-gnu-toolchain располагается инструкция о том, как можно собрать рассматриваемые утилиты из исходников.

    Для установки Qemu на компьютер наберите в консоли следующий набор команд:

    sudo apt install qemu-system-misc qemu-user-static binfmt-support opensbi u-boot-qemu
    

    Теперь у вас появилась возможность эмулировать систему на процессоре RISC-V. Введите команду:

    qemu-riscv64-static -help  
    

    Вы должны получить в ответ текст, который начинается со следующей строки:

    usage: qemu-riscv64 [options] program [arguments...]
    ...
    

    Следующим шагом идёт установка набора инструментов кросс-компилятора для сборки программ. Введите следующие команды:

    sudo apt install gcc-riscv64-linux-gnu
    sudo ln -s /usr/riscv64-linux-gnu/lib/ld-linux-riscv64-lp64d.so.1 /lib
    

    И следом за ними команду:

    riscv64-linux-gnu-as --version
    GNU assembler (GNU Binutils for Debian) 2.35.2
    ...
    

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

    После установки эмулятора и набора средств кросс-компилятора необходимо установить отладчик для процессоров с архитектурой RISC-V. В зависимости от версии ОС Debian Linux возможно потребуется поставить нестабильные версии пакетов (для более новых версий ОС).

    Отладчик с поддержкой приложений для архитектуры RISC-V называется gdb-multiarch и может быть установлен следующей командой:

    sudo apt install gdb-multiarch
    

    Пример использования набора инструментов

    В качестве примера использования установленного выше набора инструментов необходимо написать исходный файл на языке Assembler. Для этого необходимо открыть текстовый редактор (например, nano или vi для работы в консоли, а также gedit, kate, sublime или code для работы в графическом режиме) и ввести следующий код, после чего необходимо сохранить его с именем example.s.

    .text 
    .globl _start
    _start:
          addi x10, x0,  7
          addi x17, x0, 93
          ecall
    

    Для сборки и запуска программы, а также проверки результата её исполнения необходимо ввести следующую последовательность команд:

    riscv64-linux-gnu-as -o example.o example.s 
    riscv64-linux-gnu-ld -o example example.o
    qemu-riscv64-static example
    echo $? 
    7
    

    Первая команда вызывает для написанного исходного кода компилятор программ на языке Assembler, который транслирует исходный код в машинные инструкции объектного файла. Вторая команда вызывает компоновщик, который дополняет код объектного файла не обходимыми инструкциями и генерирует исполняемый файл с именем example. Третья команда запускает скомпилированный бинарный исполняемый файл на исполнение в эмуляторе архитектуры RISC-V. Поскольку этот код ничего не делает, кроме как завершает работу с указанным кодом возврата, на экране в результате выполнения программы ничего не будет выведено. Для того, чтобы увидеть код возврата последней вызываемой команды или программы, воспользуемся командой командного интерпретатора bash (строка 4). В качестве результата в консоли должно напечататься число 7.

    Помимо компилятора и компоновщика, набор инструментов также содержит утилиту objdump (файл riscv64-linux-gnu-objdump) - дизассемблер, который позволяет провести обратное описанным выше операциям действие и на основе скомпилированного бинарного кода получить набор инструкций на языке Assembler. Пример вызова утилиты дизассемблирования показан ниже:

    riscv64-linux-gnu-objdump -sd example
    example:     file format elf64-littleriscv
    
    Contents of section .text:
     100b0 13057000 9308d005 73000000           ..p.....s...    
    Contents of section .riscv.attributes:
     0000 412d0000 00726973 63760001 23000000  A-...riscv..#...
     0010 05727636 34693270 305f6d32 70305f61  .rv64i2p0_m2p0_a
     0020 3270305f 66327030 5f643270 3000      2p0_f2p0_d2p0.  
    
    Disassembly of section .text:
    
    00000000000100b0 <_start>:
       100b0:	00700513          	li	a0,7
       100b4:	05d00893          	li	a7,93
       100b8:	00000073          	ecall
    

    Первая часть вывода objdump показывает содержимое файла в шестнадцатеричном виде (за это отвечает передаваемый программе ключ -s), вторая часть - собственно дизассемблированный код (ключ -d). К этому примеру мы ещё вернёмся позднее, сейчас он служит просто демонстрацией работоспособности установленных пакетов набора инструментов.

    Наконец, можно использовать отладчик. Для этого введите следующие команды:

    qemu-riscv64-static -g 1234 example 
    gdb-multiarch example
    ...
    Reading symbols from example...
    (No debugging symbols found in example)
    (gdb) target remote :1234
    Remote debugging using :1234
    0x00000000000100b0 in _start ()
    (gdb) display /3i $pc
    1: x/3i $pc
    => 0x100b0 <_start>:	li	a0,7
       0x100b4 <_start+4>:	li	a7,93
       0x100b8 <_start+8>:	ecall
    (gdb) si
    0x00000000000100b4 in _start ()
    1: x/3i $pc
    => 0x100b4 <_start+4>:	li	a7,93
       0x100b8 <_start+8>:	recall
       0x100bc:	.2byte	0x2d41
    (gdb) si
    0x00000000000100b8 in _start ()
    1: x/3i $pc
    => 0x100b8 <_start+8>:	ecall
       0x100bc:	.2byte	0x2d41
       0x100be:	.2byte	0x0
    (gdb) c
    Continuing.
    [Inferior 1 (process 1) exited with code 07]
    

    После запуска эмулятора с подключением возможности удалённой отладки через порт 1234, запускается программа-отладчик gdb-multiarch. Отладчик подключается к удалённой системе благодаря команде target remote с указанием требуемого порта (1234). Команда display /3i $pc показывает 3 следующие за текущей инструкции, команда si предписывает выполнить одну инструкцию (сделать один шаг по коду), а команда c даёт указание продолжить выполнение программы. Чтобы выйти из отладчика, нужно ввести команду q.

    Запуск Visual Studio Code и PlatformIO вместе с Qemu и пакетом инструментов RISC-V GNU Toolchain

    Помимо работы в командной строке, также возможно настроить работу в интегрированной среде разработки. В качестве примера рассмотрим, как можно использовать среду разработки Visual Studio Code (доступна по адресу http://https://code.visualstudio.com) с установленным расширением PlatformIO, пример работы которого показан на рис.2.3 (расширение доступно по адресу http://https://platformio.org).

    Откройте терминал в среде VS Code, находясь внутри PlatformIO и выбрав пункт меню QUOT;New terminalQUOT;, и введите следующую команду:

    pio platform install https://github.com/e1d1-academy/platform-linux_riscv.git
    

    Также можно импортировать тестовый проект, как показано в следующем разделе, и проверить, запускается ли он корректно.

    (рис 2.3) Пример интерфейса среды разработки VS Code с расширением PlatformIO, работающим в режиме отладки

    Примеры к этому курсу выложены на GitHub, в каждом из каталогов примеров лежит файл platformio.ini. Эти файлы подготовлены для запуска примеров в Qemu с использованием пользовательского режима.

    Пример работы в Visual Studio Code с расширением PlatformIO

    Для получения окружения для программирования на языке Assembler в расширении PlatformIO среды разработки VS Code наберите к консоли расширения PlatformIO команду:

    https://github.com/e1d1-academy/platform-linux_riscv.git
    

    В расширении PlatformIO есть возможность работать под различны платформы, и если в диалоге вы наберёте "Linux", вам будет доступно окружение для ОС Linux для архитектуры RISC-V.

    В появившемся списке вы можете кликнуть на требуемое окружение и увидите, что там есть раздел с примерами, которые можно импортировать и попробовать их в работе. Все примеры идут с конфигурационными файлами, которые позволяют сгенерировать шаблон приложения с вашим собственным кодом на языке Assembler. Этот код можно компилировать прямо из среды VS Code, а также запускать его как в обычном режиме, так и в режиме отладки.

    В результате работы показанного примера на экран выводится фраза "Hello World!".

    Мини-компьютер StarFive VisionFive и набор инструментов RISC-V GNU Toolchain

    Одноплатный компьютер StarFive VisionFive поставляется с двухъядерным RISC-V процессором с архитектурой RV64IMAFDC. По умолчанию поставляется с ОС Fedora Linux и предустановленным набором инструментов. Этот одноплатный компьютер можно использовать как "живую" аппаратную платформу с процессором RISC-V и работать на нём без необходимости устанавливать эмуляторов, симуляторов и кросс-ассемблеров.

    На рис.2.4 показан скриншот рабочего стола xfce4 с четырьмя открытыми терминалами, запущенного на плате VisionFive.

    (рис 2.4) Рабочий стол Linux на плате VisionFile с запущенными терминалами с набором инструментов GNU toolchain

    В левом верхнем углу расположен первый терминал, в нём открыт текстовый редактор nano с исходным кодом файла example.s. Чтобы воспроизвести это, наберите в консоли команду:

    nano example.s
    

    Затем вставьте скопированный программный код (или напишите его самостоятельно) и запишите содержимое файла на диск, нажав сочетание клавиш ^O (Сtrl+o).

    Во втором терминале, расположенном слева посередине, показан результат сборки и линковки с последующей распечаткой дизассемблированного кода, выполненной с использованием утилиты objdump, а также результат запуска программы - демонстрация возвращаемого программой кода возврата. Отладочная информация внесена в исполняемый бинарный файл благодаря ключу "-g" компилятора. Для воспроизведения этих результатов введите в консоли команды:

    as -g -o example.o example.s
    ld -o example example.o
    objdump -d example
    ./example
    echo $?
    

    В третьем терминале, расположенном слева внизу, показана работа отладчика. Для воспроизведения введите в консоли команду:

    gdb example
    

    После запуска отладчика были использованы следующие управляющие команды: "layout src" - показать исходный код, "b 5" - установить точку останова на строке 5, "r" - запустить код на исполнение до точки останова, "info reg x107quot; - показать содержимое регистра x10:

    (gdb) layout src
    (gdb) b 5
    (gdb) r
    (gdb) info reg x10
    

    Из отладчика можно выйти, набрав команду "q".

    И, наконец, четвёртый терминал, расположенный справа, выводит информацию о процессоре.

    Исходные коды примеров:

    Исходные коды доступны в репозитории github по адресу: http://https://github.com/U2654/LFD117x

    Контрольные вопросы

  • Чем объектный файл отличается от исполняемого?
  • В чём отличие ассемблера от языка ассемблера?
  • Как компоновщик получает исполняемый файл из нескольких объектных?
  • Состояние каких модулей процессора позволяет отслеживать Ripes?
  • Чем симулятор отличается от эмулятора?
  • В каких режимах может работать Qemu?
  • Как с помощью objdump посмотреть информацию об исполняемом файле?
  • Как отладчиком подключиться к запущенному процессу в Qemu?
  • Какие команды отладчика необходимо использовать для выполнения программы?
  • Какие команды позволяют просматривать значения переменных/регистров в процессе отладки?
  • Вернуться к учебному плану