Добавить в корзинуПозвонить
Найти в Дзене
Old Programmer

GNU assembler x86-64 Linux. Стек и команды ассемблера

Доброго времени суток, это снова канал Old Programmer и снова о программировании и только о программировании. Сегодня опять ассемблер, а здесь обзор материалов только по языку ассемблер
Язык ассемблера (x86-64, Linux). Путеводитель по ресурсам канала Old Programmer
Некоторые фишки ассемблера x86-64
У меня была статья на канале:
Оглавление

Доброго времени суток, это снова канал Old Programmer и снова о программировании и только о программировании. Сегодня опять ассемблер, а здесь обзор материалов только по языку ассемблер

  • Язык ассемблера (x86-64, Linux). Путеводитель по ресурсам канала Old Programmer

См. также

  • И снова ассемблер (GAS x86-64) для Linux. Продолжаем работать со стеком, локальные переменные

Некоторые "фишки" ассемблера x86-64

У меня была статья на канале на Old Programmer:

  • Программирование. Некоторые "фишки" языка C

Ну вот сегодня, несколько "фишек" языка ассемблер. Разумеется речь идет об x86-64. Сегодня, как и следует из названия, фишки касаются стека. Эти фишки я еще помню с тех времен, когда в 80-е годы я анализировал тексты компьютерных вирусов. Вот некоторые такие штуки использовались для того, чтобы затруднить анализ кода.

Вызов функции при помощи команды jmp

Поскольку мы теперь знаем. как устроен стек, то легко заменим команду call, вызова подпрограммы, на команду jmp, при условии, что в стеке будет лежать адрес возврата:

...
push $l2
jmp l1
l2:
...
l1:
...
ret

Возврат из функции с помощью команды jmp

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

...
pop %rax
jmp *%rax
...

Обратим внимание на команду jmp *%rax. Это косвенный переход по адресу, который лежит в регистре rax. Символ '*' обязателен.

Еще один вызов функции с помощью команды jmp

Вызов функции с помощью команды jmp возможен с помощью еще одного способа косвенного перехода. Если адрес лежит в памяти, а rax содержит адрес области памяти, где лежит адрес функции, то jmp *(%rax) это переход по адресу, который лежит в памяти

...
push $l2
mov $l1, %rax
mov %rax, addr
mov $addr, %rax
jmp *(%rax)
l2:
...
l1:
...
ret

Использование команды ret вместо jmp

Мы использовали jmp вместо call и ret, можно и наоборот, например ret использовать вместо jmp.

...
mov $10, %r15
l1:
# что-то делаем
...
dec %r15
jz l2
push $l1
ret # т.е. на самом деле просто jmp
l2:
...

Ну вот пока все. Таких интересных разностей на ассемблере довольно много и мы еще будем о них говорить.

Заканчиваем, но ассемблер на нашем канале Old Programmer продолжается. Подписывайтесь на мой канал, ставьте лайки и комментируйте.

Assembler forever
Assembler forever