Я на самом деле изучаю ассемблер, и моя актуальная проблема - реализовать функцию в ассемблере с 7 аргументами, используя соглашение о вызовах c.Правило гласит, что первые 6 аргументов передаются rdi
, rsi
, rdx
, rcx
, r8
и r9
.Остальные аргументы (справа налево) помещаются в стек.
Итак, если у меня есть такая функция:
extern void* asm_func(void *arg1, void *arg2, void *arg3, void *arg4,
void *arg5, void *arg6, void *arg7);
Затем вызовите ее следующим образом:
asm_func(1, 2, 3, 4, 5, 6, 7);
Если я правильно угадал, ассемблер сгенерирует что-то вроде этого:
mov $1, %rdi
mov $2, %rsi
mov $3, %rdx
mov $4, %rcx
mov $5, %r8
mov $6, %r9
push $7
call asm_func
Теперь 7-й аргумент помещается в стек.Это где я запутался.Куда это идет?
Моим первым предположением было просто сделать pop
.Но это мне не кажется правильным.Мое второе предположение состояло в том, чтобы получить адрес rsp
, вычитаемый из 0x10
.Итак, моя реализация выглядит следующим образом:
asm_func: # asm_func as a linux system call interface
mov %rdi, %rax
mov %rsi, %rdi
mov %rdx, %rsi
mov %rcx, %rdx
mov %r8, %r10
mov %r9, %r8
mov -0x10(%rsp), %r9
syscall
ret
Это правильная реализация?
Эти предположения основаны на моем понимании того, как работают push и pop.Я понимаю, что всякий раз, когда я помещаю значение в стек, это означает, что я помещаю значение ниже (в смещение) rsp
.Итак, я подозреваю, что значение push
ed в стек пойдет.Я прав?Инструкция push
действительно помещает туда значение?