main.c
#include <stdio.h>
int mystery(char *, int);
char *str = "Reference letter";
int main () {
int n = 16;
printf("The return value was: %d.\n", mystery(str,n));
printf("%p\n", (&str));
return 0;
}
mystery.s
.globl _mystery
_mystery:
movl $0, %eax
leaq (%rdi, %rsi), %rcx
loop:
cmpq %rdi, %rcx
jle endl
decq %rcx
cmpb $0x65, (%rcx)
jne loop
incl %eax
jmp loop
endl:
ret
•% rdi - первый аргумент, то есть char * str;
•% esiявляется вторым аргументом, т. е. int n;
•% eax - возвращаемое значение, int.
Я совершенно не понимаю, как работает этот оператор leaq (%rdi, %rsi), %rcx
.Я знаю, что он выполняет некоторую адресную арифметику, и результат будет присвоен %rcx
.%rdi
является начальным адресом char *, который должен указывать на символ "R",% rsi должно быть 16. Допустим,% rdi равно 0x100
,% rcx должно быть 0x10F
.
Главной целью тайны должен быть подсчет числа «е» в строке «Ссылочная буква» в некоторой позиции.Он начинается с (% rdi,% rsi), затем начинается обратный отсчет.
Я тестировал программу в MacOS с использованием XCode.Когда n = 16, mystery возвращает 6. n = 14, возвращает 5, n = 5, 2.
Что меня смущает, так это то, что я ожидаю, что начальное значение% rcx будет 0x10F
(при условии, что% rdi составляет 0x100).Поскольку каждому символу в C требуется 1 байт, адрес памяти также смещается на 1 байт.Так что% rcx должен указывать на 3-й символ в «Ссылочной букве», который должен быть «f».Но результат не кажется таким.Похоже, что это указывает на 16-й символ в строке.Поэтому я не совсем понимаю, как работает эта арифметика с памятью и leaq
.В leaq (% rdi,% rsi),% rcx, (% rdi,% rsi) добавьте 16 к адресу% rdi, верно?Означает ли это, что он смещен на 16 байт или как?