Добрый день! Ковыряясь в сорцах ядра Linux, под ARM архитектуру, нашел такой код, использующийся в функции copy_from_user:
#define __range_ok(addr,size) ({ \<br/>
unsigned long flag, roksum; \<br/>
__chk_user_ptr(addr); \<br/>
__asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \<br/>
: "=&r" (flag), "=&r" (roksum) \<br/>
: "r" (addr), "Ir" (size), "" (current_thread_info()->addr_limit) \<br/>
: "cc"); \<br/>
flag; })<br/>
Никак не могу в нем до конца разобраться. Я уже задавал вопрос на stackoverflow, там мне дали ссылку на документацию и пару полезных советов, это немного прояснило ситуацию. Дело в том, что тут используется вычитание с переносом, соответственно активно используется Carry flag.
Как я понимаю данный код:
Складываем значение addr и size, результат попадает в roksum (?)
Вычитаем с переносом значение addr_limit из roksum, но только если carry flag чист (?), результат попадает. По итогу операции устанавливаем или не устанавливаем этот же carry flag.
Если carry flag не был установлен — перемещаем значение 0, в регистр r0.
Что не понятно: где и как используется flag, а так же как интерпретируется результат sbcccs, т.е. если произошло переполнение — ставим флаг carry? И какое значение, по итогу, отдается в качестве результата?
Надеюсь, что кто-то поможет разобраться в данном вопросе.
Спасибо!