15 написать программу выводящую в консоли сообщение hello world используя макросы

Обновлено: 19.05.2024

Для вывода строки используется системная функция DOS. Чтобы напечатать строку, нужно поместить 9 в регистр AH, а в регистр DX поместить адрес строки, которая должна заканчиваться символом ‘$’. Обращение к функциям DOS осуществляется с помощью команды int 21h. Вот код программы:

use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h mov dx,hello ;В DX адрес строки. mov ah,9 ;Номер функции DOS. int 21h ;Обращение к функции DOS. mov ax,4C00h ;\ int 21h ;/ Завершение программы ;------------------------------------------------------- hello db 'Hello, world!$'

В четвёртой строке FASM подставит адрес строки вместо hello. Не трудно догадаться, что завершение программы — это тоже функция DOS с номером 4Ch. Перед её вызовом в регистр AL помещается код завершения программы (ноль соответствует успешному завершению). Можно объединить эти две операции и сразу поместить в AX значение 4C00h.

В учебном курсе я не буду подробно описывать функции DOS, лишь кратко расскажу о тех функциях, которые мы будем использовать. Если вы захотите узнать больше, в Интернете можно найти подробное описание 🙂

Чтобы увидеть работу программы, надо запустить её из командной строки, иначе она печатает строку и сразу закрывается. Или можно написать простенький bat-файл для запуска:

Результат работы программы:


Если вы запустите программу в отладчике, то просмотреть выводимую строку можно, нажав Alt+F5 или выбрав в меню Turbo Debuger пункт Window->User Screen.

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

Третья и последняя строка вышеприведенного листинга завершает процедуру и состоит всего из двух слов – End Sub, чем отмечает конец программы. При выполнении этой инструкции никаких видимых действий не происходит, но при этом высвобождается память, временно использованная при выполнении процедуры.

Используя аргументы для оператора MsgBox можно изменить вид диалогового окна.

Остается выполнить написанный исходный код и посмотреть что получилось. Переключаемся в окно приложения (Word, Excel), нажимаем сочетание клавиш Alt+F8, выбираем в открывшемся окне из предложенного списка строку с именем процедуры "HelloWorld" и нажимаем кнопку "Выполнить".

Написать программу на ассемблере, выводящую на экран строку 100 раз
Написать программу на ассемблере, выводящую на экран строку 100 раз.

Программа "Hello World" из книги Крупника А. "Изучаем ассемблер" не выводит строку
Здравствуйте! :) Начал изучать Ассеблер по книге Крупника А. "Изучаем ассемблер". Переписал.

Напишите программу, выводящую на экран "бегущую строку"
Напишите программу, выводящую на экран "бегущую строку" (бегущую строку можно оформить в виде.

Mikl___, можно и через undoc BOP_3RDPARTY - MessageBox() из доси вывести.
И да, топик-таки лучше прилепить.

чтобы тема не выродилась, a о MessageBox'e создавай новую тему

Mikl___, там не обязательно подсчитывать длину строки, можно просто прекращать вывод символов при встрече контрольного символа в конце строки (например $)

Что-то совсем мало сказано про использование стандартной библиотеки Си.

Этот пост я направляю в первую очередь преподавателям и учителям.

Начинать HelloWorld с реализации для DOS, с использованием WinAPI или макросов, по моему мнению, очень не правильно.
Если изучать Ассемблер после Си, то можно легче понять происходящее, а самое главное, объяснить всем студентам/школьникам значимость Ассемблера, архитектуру компьютера и правила исполнения программ. Современный курс не должен концентрироваться на 100500 способах вывода последовательности байт в консоль и изучении систем исчисления. Чем быстрее будет изучен математический сопроцессор, SSE и прочие вкусности, тем больше можно успеть в рамках курса. А это значит, что надо пользоваться готовыми инструментами для взаимодействия человека и компьютера.

Теперь вспомним, что в Си программа начинает исполняться с функции main. Реализуем её. Эта функция возвращает число с типом int, для Win32, в соответствии с "соглашением о вызове" cdecl, оно должно быть возвращено через регистр EAX.
Процесс сборки готовой программы разобьём на два этапа:
- компиляция asm-файла в объектный файл,
- компоновка объектного файла со стандартными библиотеками средством, предполагающим сборку Си-приложения.
Первый пункт требует, что бы мы не забыли "опубликовать" нашу функцию. Второй - предполагает, что компоновщик будет ждать функцию main.
В качестве компилятора языка Ассемблера я буду использовать NASM, поменять его на другой не составит труда. В роли компоновщика рассмотрю MinGW и MSVS.

Первый пример: "Ничего не делаем"

Компилируем, компонуем, запускаем и видим долгожданную строку.
Я говорил, что можно скомпоновать и с помощью MSVS:

Теперь вспомним, что в main передаются ещё и параметры. Они лежат в стеке. Там сейчас:
- адрес возврата (4 байта),
- int argc (4 байта),
- char *argv[] (4 байта).

А тут ничего почти не изменилось . Мы не использовали системнозависимых функций. Но нам потребуется:
- избавиться от префикса "_",
- изменить формат объектного файла

Замечание: Если добавить ключ "--prefix _" в nasm при компиляции в Win32, то последний код, будет работоспособным.

Изменения:
- Параметры передаются через регистры. Целые числа/указатели в rdi, rsi, rdx, rcx, r8 и r9. Действительные xmm0-xxm7, остальное через стек.
- Если вызывается подпрограмма с переменным числом параметров, то в RAX указываем число использованных xmm-регистров.
- Префикс не нужен.
- Изменился формат объектных файлов.

Что такое FASM? - Это компилятор ассемблера (flat assembler).

Что такое ассемблер? - это машинные инструкции, то есть команды что делать процессору.

Что такое Windows API/WinAPI? - Это функции Windows, без них нельзя работать с Windows.

Что дают WinAPI функции? - Очень много чего:

Работа с файлами.

Работа с окнами, отрисовка картинок, OpenGL, DirectX, GDI, и все в таком духе.

Взаимодействие с другими процессами.

Работа с портами.

Работа с консолью Windows

И еще очень много интересных функций.

Зачем нужен ассемблер?

На нем можно сделать все что угодно, от ОС до 3D игр.

Вот плюсы ассемблера:

Он очень быстрый.

На нем можно сделать любую программу.

А вот минусы ассемблера:

Долго делать программу. (относительно)

Сложен в освоении.

Что нужно для программирования на ассемблере (FASM)?

Это все мероприятие весит всего лишь 8.5MB.

Установка компонентов (если можно так назвать)

Архив FASM-а распаковуем в C:\\FASM\ или любой другой, но потом не забудьте настроить FASMEditor.

Архив FASMEdit-a распаковуем куда-то, в моем случае C:\\FASM Editor 2.0\

Архив OlyDbg распаковуем тоже куда-то, в моем случае C:\\Users\****\Documents\FasmEditorProjects\

Настройка FASM Editor-a

Для этого его нужно запустить.


Сразу вас приветствует FASM Editor соей заставкой.

Теперь вам нужно зайти в вкладку "Сервис" (на картинке выделил синим) -> "Настройки. "


Жмем на кнопку с названием ". " и выбираем путь к файлам или папкам.

Теперь мы полностью готовы. К началу.

Пишем "Hello world!" на FASM

В Fasm Editor нужно нажать на кнопку слева сверху или "файл" -> "новый". Выбираем любое, но можно выбрать "Console"

По началу вас это может напугать, но не боимся и разбираемся.

На самом деле из всей этой каши текста, команд всего 3: на 16, 18, 21 строках. (и то это не команды, а макросы. Мы к командам даже не подобрались)

Все остальное это просто подготовка программы к запуску.

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


Самое интересное то что программа весит 2КБ. (Можно сократить и до 1КБ, но для упрощения и так пойдет)

Разбор: что значат этот весь текст?

На 1 строчке: "format PE Console" - это строчка говорит FASM-у какой файл скомпилировать, точнее 1 слово, все остальные слова это аргументы (можно так сказать).

PE - EXE файл, программа.

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

Но есть кроме это остальные:

format MZ - EXE-файл НО под MS-DOS

format PE - EXE-файл под Windows, аналогично format PE GUI 4.0

format PE64 - EXE-файл под Windows, 64 битное приложение.

format PE GUI 4.0 - EXE-файл под Windows, графическое приложение.

format PE Console - EXE-файл под Windows, консольная программа. (просто подключается заранее консоль)

format PE Native - драйвер

format PE DLL - DLL-файл Windows, поясню позднее.

format COFF - OBJ-файл Linux

format MS COFF - аналогично предыдущему

format ELF - OBJ-файл для gcc (Linux)

format ELF64 - OBJ-файл для gcc (Linux), 64-bit

Сразу за командой (для компилятора) format PE Console идет ; это значит комментарий. К сожалению он есть только однострочный.

3 строка: entry start

Говорим windows-у где\в каком месте стартовать. "start" это метка, но о метках чуть позже.

5 строка: include 'win32a.inc'

Подключает к проекту файл, в данном случае "win32a.inc" он находиться в папке INCLUDE (в папке с FASM). этот файл создает константы и создает макросы для облегчения программирования.

8 строка: section '.data' data readable writeable

Секция данных, то есть программа делиться на секции (части), к этим секциям мы можем дать разрешение, имя.

Флаг "data" (Флаг это бит\байт\аргумент хранившей в себе какую-то информацию) говорит то что эта секция данных.

Флаги "readable writeable" говорят то что эта секция может читаться кем-то и записываться кем-то.

Текст '.data' - имя секции

10 строка: hello db 'hello world!',0

hello - это метка, она может быть любого имени (почти, есть некоторые зарезервированные имена), эта метка хранит в себе адрес строки, это не переменная, а просто адрес, но чтобы не запоминать адреса в ручную, помогает FASM он запоминает адрес и потом когда видит эту метку снова, то он заменяет слово на адрес.

db - говорит то что под каждый символ резервируем 1 байт. То есть 1 символ храниться в одном байте.

'hello world!' - наша строка в кодировке ASCII

Что значит ",0" в конце строки? - это символ с номером 0 (или просто ноль), у вас на клавиатуре нет клавиши которая имела символ с номером 0, по этому этот символ используют как показатель конца строки. То есть это значит конец строки. Просто ноль записываем в байт после строки.

12 строка: section '.code' code readable writeable executable

Флаг "code" - говорит то что это секция кода.

Флаг "executable" - говорит то что эта секция исполняема, то есть в этой секции может выполняться код.

Все остальное уже разобрали.

14 строка: start:

Это второй вид меток. Просто эта метка указывает на следующую команду. Обратите внимание на то что в 3 строке мы указали start как метку входа в программу, это она и есть. Может иметь эта метка любое имя, главное не забудьте ваше новое имя метки вписать в entry

15 строка: invoke printf, hello

Функция printf - выводит текст\число в консоль. В данном случае текст по адресу "hello"

Это штото на подобие команды, но это и близко не команда ассемблера, а просто макрос.

Макрос - Это макро команда для компилятора, то есть вместо имени макроса подставляется что-то другое.

Например, макро команда invoke делиться на такие команды: (взят в пример команда с 15 строки)

Не переживайте если нечего не поняли.

17 строка: invoke getch

getch - функция получения нажатой кнопки, то есть просто ждет нажатия кнопки и потом возвращает нажатую кнопку.

20 строка: invoke ExitProcess, 0

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

23 строка: section '.idata' data import readable

Флаг "import" - говорит то что это секция импорта библиотек.

24-25 строки:

Макро команда "library" загружает DLL библиотеки в виртуальную память (не в ОЗУ, вам ОЗУ не хватит чтоб хранить всю виртуальную память).

Что такое DLL объясню позже.

kernel - имя которое привязывается к библиотеке, оно может быть любым.

Следующий текст после запятой: 'kernel32.dll' - это имя DLL библиотеки который вы хотите подключить.

Дальше есть знак \ это значит что текст на следующей строке нужно подставить в эту строку.

Это нужно потому что у ассемблера 1 строка это 1 команда.

27-28 строка:

import - Макро команда, которая загружает функции из DLL.

kernel - Имя к которой привязана DLL, может быть любым.

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

'ExitProcess' - Это имя функции которое будет загружено из DLL, то есть это имя функции которое прописано в DLL.

Дальше думаю не стоит объяснять, вроде все понятно.

Что такое DLL библиотека?

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

Подводим итог

На ассемблере писать можно не зная самого языка, а используя всего лишь макро команды компилятора. За всю статью я упомянул всего 2 команды ассемблера это push hello и call [printf] . Что это значит расскажу в следующей статье.

CSEG segment
org 100h
begin:
mov ax,dx
mov es,ax
;очищаем экран
mov al, 02h
mov ah, 00h
int 10h

mov bp,offset string
mov ax,1301h
mov bx,1 ;blue screen
mov cx,len
mov dx,0200h
int 10h

mov ax, 0B800h; video buffer
mov es,ax
mov di,0h
mov cx,len
mov si, 0 ;counter
mov ah,01
ccc:
mov al, byte ptr string [si]
mov es:[di],ax
add di,2
inc si
loop ccc

;mov ax,4C00h
; int 21h

string db 'Hello World'
len=$-string
CSEG ends
end begin

> этот пример написан на Tasm
Вообще-то, он написан в синтаксисе Masm с упрощённым объявлением сегментов, причём с ошибками, которые не позволят правильно слинковать программу.
Tasm компилирует такие программы только потому, что по-умолчанию работает в режиме MASM.
Пример написан для DOS, значит и компилировать его нужно соответствующим компилятором. Tasm 4 как раз для этого подойдёт. Зачем вам понадобился Tasm32?

Если уж упоминается о Tasm32, то программа для него может выглядеть, например, так:

ideal
p386
model flat, stdcall

procdesc GetStdHandle winapi :dword
procdesc WriteConsoleA winapi :dword, :dword, :dword, :dword, :dword
procdesc ExitProcess winapi :dword
extrn _kbhit :proc

STD_OUTPUT_HANDLE equ -11

segment data
Msg db 'Hello, World!',13,10
MsgLen equ %($ - Msg)
ends

segment code
start:
call GetStdHandle,STD_OUTPUT_HANDLE
call WriteConsoleA,eax,offset Msg,MsgLen,0,0
Inkey:
call _kbhit
test eax,eax
jz Inkey
call ExitProcess,0
ends
end start

Компилировать и линковать эту программу командами:
tasm32 /ml /q /zn prog.asm
tlink32 -Tpe -ap -c -x prog.obj import32.lib imp32i.lib
где
import32.lib - библиотечный файл для импорта функций из стандартной поставки Tasm 5;
imp32i.lib - библиотечный файл из комплекта Tasm 5 plus для импорта новых функций WinApi, в частности функции _kbhit из библиотеки msvcrt.dll.

Если вдруг вам понадобится Hello World в диалоговом окне для tasm32, то он находится здесь.

Читайте также: