Пирогов Владислав Юрьевич

О программировании, ИТ и обо всем по немногу

Previous Entry Share Next Entry
64-битовое программирование в Linux на ассемблере
pirogov_vju


Для вызова системных функций в Unix-системах на ассемблере можно использовать системный вызов (шлюз) 0x80. Однако, во-первых, нотация вызова может меняться от версии к версии, во-вторых, от одной Unix-системы, к другой. Изначально, в качестве прослойки, наподобие  функций API в Unix-системах использовались функции из стандартных библиотек языка C.

В 64-битных Unix-системах также произошел переход к соглашению о передаче параметров по средством регистров. Для передачи параметров, представляющих целые числа (в том числе и ссылки)  используются последовательно шесть регистров: rdi, rsi, rdx, rcx, r8, r9. Если количество параметров превышает шесть, то оставшиеся параметры передаются через стек. При этом, как и раньше следует помнить о выравнивании стека по границе кратной 16 байтов. 
В качестве примера того, как параметры передаются системным функциям, приведем пример, в котором используются две системные функции gets, exit,  printf. Для того, чтобы рассмотреть возможность использования стека, нами был взят случай с большим количеством параметров (см. вызов функции printf).

;вызов системных функций на ассемблере Unix64
format ELF64 executable 3
entry start
include 'import64.inc'
interpreter '/lib64/ld-linux-x86-64.so.2'
needed 'libc.so.6'
import exit, gets, printf
segment readable executable
start:
;в начале организуем стек
push rbp
mov  rbp,rsp
;выделить стек, чтобы в дальнейшем передать через него параметры
sub  rsp,32
;получить строку
mov rdx,1
mov  rsi,100
mov  rdi, buf
call [gets]
;вывод данных с помощью функции printf
;в начале выделим стек для стековых параметров (их будет три)
;параметры
mov  rdi,frmt
mov  rsi,buf
mov  rdx,32
mov  rcx,64
mov  r8,128
mov  r9,256
mov rax,512
mov  [rsp],rax
mov rax,1024
mov [rsp+8],rax
mov rax,2048
mov [rsp+16],rax
call [printf]
;восстановить стек
mov rsp,rbp
pop rbp
;выход из программы
mov  rdi,0
call [exit]
segment readable writeable
buf   db 100 dup(0)
frmt  db "%s %d %d %d %d %d %d %d ",10,0

Остановимся на некоторых важных моментах программы.
1. Для доступа к стеку, мы используем не команды push, а прямой доступ к области стека.
2. Для трех параметров (этим параметрам не хватило регистров и они будут передаваться через стек) мы выделяем 32 байта (команда sub rsp,32), так чтобы стек был выровнен по адресу, кратному 16 (Команды push rbp/sub rsp,32 плюс вызов процедуры (еще 8 байтов) в результате дают смещение в стеке равное 48 байтов, что кратно 16).
Для передачи параметров имеющих вещественный тип (64-х битовый) также как и в случае операционной системы Windows используются регистры группы xmm. Для возвращения данных из функции используются  регистры rax и xmm0.
 


Как и раньше для трансляции достаточно написать fasm prog.asm и получаем исполняемый модуль.

Продолжение следует...

Пирогов В.Ю. (http://asm.shadrinsk.net

  • 1
Я так и не смог даже самое малое что-то предпринять в FASM. Всё-таки он оставляет ощущение поделки. Посмотрите JWASM.
www.japheth.de

...
xor rax, rax
call printf
...

Книга

(Anonymous)
Здравствуйте. Так когда выйдет Ваша книга про 64-битовое программирование?

+1, как говорится. Вы ещё пишете?

  • 1
?

Log in

No account? Create an account