Я буду писать в этой теме каждый день (и при возможности) обучение языку ассемблер. 32-битный, но он вполне подойдет под 64 битный с нюансами, например, сейчас расскажу про тот случай, когда нужно применять костыль в одно слово в одну строчку, чтобы код не упал. Если в eax лежало отрицательное число, просто так сменить eax на rax нельзя. Для того, чтобы это решить, просто сделайте так:
mov eax, -5 ; задаем регистру EAX отриц значение -5, записывается как 0xFFFFFFFB
cdqe ; Теперь rax = 0xFFFFFFFFFFFFFFFB (честные 64-битные -5)
add rax, 10 ; Корректно прибавит 10, получим 5
Если вы ничего не поняли - то тут и нет стремления понять. Просто помните про cdqe и держите это в уме! (P.S работа рассчитана на x86, но будет работать на x64. пишется под Linux)
В разделе .text мы указываем ядру, с какого места начать выполнение, передав ему глобальную метку _start:, обозначающую точку входа программы. В секции .data мы создаем переменную msg, задаем ей дерективу db (Define Byte - 8 бит; Символы строк, флаги (0/1), числа 0–255) В разделе .text мы указываем ядру, с какого места начать выполнение, передав ему глобальную метку _start:, обозначающую точку входа программы.
SECTION .data
msg db 'Hello, world', 0Ah ; 0Ah - аналог \n
SECTION .text
global _start
_start:
; sys_write, т.е запись данных в ОЗУ
mov edx, 13 ; кол-во сиволов в msg + \n (1 символ)
mov ecx, msg ; адрес строки
mov ebx, 1 ; куда пишем - в stdout, т.е в терминал проще говоря
mov eax, 4 ; вызываем sys_write, запись данных
int 80h ; передаем управление ядру Linux
; если мы не напишем код ниже, то код заработает но выплюнет ошибку сегментации
mov ebx, 0 ; sys_exit, выход из программы
mov eax, 1 ; завершаем программу со статусом 0, т.е "Ошибок нет".
int 80h ; передаем управление ядру
Расписал как мог. Надеюсь, вы всё поняли. Ждите второго урока, а вопросы пишите сюда же!
Не рекомендую в слепую CTRL+C, CTRL+V копировать кож. Пишите его вручную.
Забыл:
~$ nasm -f elf helloworld.asm
~$ ld -m elf_i386 helloworld.o -o helloworld
~$ ./helloworld
Вот так компиляция идёт UPD: Это компилирует 32-битное приложение. Если вы попытаетесь собирать под 64-битный elf64, пихать туда cdqe или чередовать бездумно eax с rax, то у вас компиляция упадёт. Но не волнуйтесь — x86_64 по своей логике не сильно отличается. Я просто привык к классическим 32-битным регистрам (eax, ecx и т.д.), с них и начнем.
Если отупить – подпрограммы это функции, к которым мы переключаемся через jmp (jump; перейти/прыгнуть к чему-либо)
SECTION .data
msg db "Hello, World", 0Ah
msg1 db "Cute boy!", 0Ah
SECTION .text
global _start
_start:
first:
mov edx, 13
mov ecx, msg
mov ebx, 1
mov eax, 4
int 80h
mov ebx, 0
mov eax, 1
int 80h
jmp two
two:
mov edx,
mov ecx, msg1
mov ebx, 1
mov eax, 4
int 80h
mov ebx, 0
mov eax, 1
int 80h
Привычный с первого урока нам код внезапно оброс first и two. first - функция, которая выполняется первой потому что… Она стоит самой первой. Ко two вы уже переходим через jmp, при этом в first если мы напишем:
mov ebx, 0
mov eax, 1
jmp two
То переход к two не начнётся, ибо mov eax, 1 говорит ядру, что надо выполнят syscall_exit, т.е закончить программу. Заканчиваем мы её и выводим код выполнения 0 “Успешно” только в подпрограмме two.
А для отступов можно что угодно использовать? Или только TAB? Или только пробелы?
можно хоть пробелы хоть TAB, а можно ваще без них, похрен вообще
Чтобы ответить, войдите.