Программа на NASM — сравнение двух строк — t2.asm:
section .data
msg1 db «Мой текст»,0 ; 0 — означает конец строки
msg2 db «Мой текст»,0
msg_res_y db «Строки идентичны», 10 ; 10 — переход на новую строку
res_y equ $ — msg_res_y ; вычислим размер надписи включая знак перехода на новую строку
msg_res_n db «Строки не равны»,10
res_n equ $ — msg_res_n
section .text
global _start
_start:
;загрузим адреса строк в регистры
mov rsi, msg1
mov rdi ,msg2
compare_loop:
;возьмем по байту от каждого сообщения и поместим в r8b. [rsi] — взять байт содержимого из rsi, без квадратных скобок было бы — взять адрес
mov r8b, [rsi]
mov r9b , [rdi]
cmp r8b, r9b ; сравним байт из одного слова и байт из другого
jne res_dif ; jne — если не равны, переход на ссылку res_equal. jne — jump not equal — прыгнуть если не равны/не эквивалентны
;проверяем байт конца строки, не кончилась ли строка, должен быть 0 если кончилась
cmp r8b, 0
jz res_equal ; строка кончилась, 0, значит весь цикл прошел до конца и строки равные. jz -jump zero — прыгнуть на метку если ноль.
inc rsi ;перейти к следующему байту/букве
inc rdi ;тоже самое для второго слова
jmp compare_loop ;прыгнуть на метку начала сравнения
res_equal:
; sys_write
mov rax,1 ; функция вывода текста
mov rdi, 1 ; первый аргумент 1 — это консоль. выводим в stdout, в консоль
mov rsi, msg_res_y ; строка «строки равны»
mov rdx, res_y ;ее длина, требуется для вызова вывода строки
syscall ;исполним вывод строки
jmp ext_prog ; прыгнем на функцию корректного завершения программы
res_dif:
mov rax,1 ; функция вывода
mov rdi, 1 ; первый аргумент 1 — это консоль/stdout
mov rsi, msg_res_n ; строка «cтроки не равны»
mov rdx, res_n ;ее длина
syscall
ext_prog:
mov rax,60
xor rdi, rdi
syscall
Скомпилировать:
nasm -f elf64 t2.asm -o t2.o
ld t2.o -o t2.bin
Запуск скомпилированной программы из папки с программой из консоли
./t2.bin
Это 64 битная программа для Linux.
Для 32 бит она выглядела бы иначе, так как в 32 битах используется лишь часть 64 битных регистров, пример 32 битной программы на рисунке ниже (сегодня 32 бита уже не актуальны):
Для версии этой программы для Windows прийдется обращаться к WinAPI, что довольно громоздко, у каждого вызова есть свои параметры и требования в каких регистрах, что должно находится.
Линкуется программа тоже не через ld, а через golink.
bits 64
default rel ; Обязательно для Windows x64: RIP‑relative адресация
section .data
msg1 db «Мой текст», 0
msg2 db «Мой текст», 0
; В Windows нужен CRLF: 13 (CR) + 10 (LF)
msg_res_y db «Строки идентичны», 13, 10
res_y equ $ — msg_res_y
msg_res_n db «Строки не равны», 13, 10
res_n equ $ — msg_res_n
bytes_written dq 0 ; Буфер, который требует WriteFile
section .text
global _start
_start:
; — Получить дескриптор stdout через GetStdHandle(-11) —
mov ecx, -11 ; STD_OUTPUT_HANDLE = -11 (0xFFFFFFF5)
call GetStdHandle ; результат (HANDLE) будет в RAX
mov rbx, rax ; сохраняем в RBX, чтобы не потерять
; — Цикл сравнения строк (логика та же, что и в Linux) —
mov rsi, msg1
mov rdi, msg2
compare_loop:
mov r8b, [rsi]
mov r9b, [rdi]
cmp r8b, r9b
jne res_dif
cmp r8b, 0
jz res_equal
inc rsi
inc rdi
jmp compare_loop
res_equal:
; — Вызов WriteFile для msg_res_y —
; Соглашение Microsoft x64: RCX, RDX, R8, R9, [стек]
mov rcx, rbx ; 1. hFile (дескриптор консоли)
mov rdx, msg_res_y ; 2. lpBuffer (адрес строки)
mov r8d, res_y ; 3. nNumberOfBytesToWrite (длина строки)
mov r9, bytes_written ; 4. lpNumberOfBytesWritten (адрес переменной)
sub rsp, 32 ; Выравнивание стека по 16 байт + место под 5‑й аргумент
xor eax, eax
mov [rsp+20], eax ; 5. lpOverlapped = NULL (синхронная запись)
call WriteFile
jmp ext_prog
res_dif:
; — Вызов WriteFile для msg_res_n —
mov rcx, rbx
mov rdx, msg_res_n
mov r8d, res_n
mov r9, bytes_written
sub rsp, 32
xor eax, eax
mov [rsp+20], eax
call WriteFile
ext_prog:
; — Выход через ExitProcess(0) —
xor ecx, ecx ; uExitCode = 0
call ExitProcess
; — Объявления внешних функций (WinAPI) —
extern GetStdHandle
extern WriteFile
extern ExitProcess
Сборка:
nasm -f win64 t2.asm -o t2.obj
- Слинковать в .exe (самый простой вариант без Visual Studio — это
golink):golink /console /entry _start kernel32.dll t2.objНа выходе получится
t2.exe.
Отправить ответ
Для отправки комментария вам необходимо авторизоваться.