Спасибо всем за развёрнутые ответы. В общем для себя некоторые выводы сделал. Пока понял, более или менее, механизм занесения переменных в стек. Если я верно понял, это происходит последовательно, каждая следующая переменная смещает стек, на 4 позиции, в данном случае (видимо, смещение в байтах). Получается, что смещение для переменной вычисляется легко в небольших программах.
В общем случае, не совсем так. Как правило, пролог функции (т.е. инструкции в начале) поднимает стек сразу на необходимое количество байт, чтобы поместились все локальные переменные, после чего уже им присваиваются начальные значения. Но это не всегда так, может быть и такое что если переменная больше не используется или потеряла видимость, стек опустится. Все зависит от компилятора и его опций. Если речь об аргументах функции, то (опять же - в общем случае) те, что передаются на стеке, будут помещены последовательно перед вызовом.
Ассемблер в гцц умеет в интеловский синтаксис (параметр -masm=intel или как-то так). Ты главную свою ошибку про инлайн асм понял? Тебе не надо ничего высчитывать никаких смещений на стеке, тебе надо передать переменные через списки инпутов и/или аутпутов. Переменной в коде вообще может не быть на стеке, если функция достаточно простая, чтобы держать переменную в только регистре, оптимизатор это сделает.
Ага, а еще к переменным в примере можно обращаться по rbp потому, что компилятор сформировал так называемый "bp-based stack frame". Это опять же необязательно, оптимизирующие компиляторы чаще формируют "sp-based frame", с обращением к локальным переменным по указателю стека.
"В общем случае, не совсем так. Как правило, пролог функции (т.е. инструкции в начале) поднимает стек сразу на необходимое количество байт, чтобы поместились все локальные переменные". Примерно так и понял. И помещается они, как я понял, в порядке следования друг за другом. --- Сообщение объединено, 23 дек 2022 --- То есть, допустим, переменная 1 единственная и она не попадет в стек, соответственно в коде не будет доступна для изменения через регистр rbp?! Примерно понял, о чем речь. Спасибо ещё раз, видимо, надо было ковырнуть код, чтобы понять, сколько есть в асме нюансов, и сколько всего я не знаю. --- Сообщение объединено, 23 дек 2022 --- Нашёл. Искал по ключевым словам: variable C in Assembler. Тема на stack Overflow: "manipulating c variable via inline assembly". --- Сообщение объединено, 23 дек 2022 --- В итоге получилось что-то вроде такого: Код (Text): /*Порождение перестановок*/ #include <stdio.h> int main(){ char a[] = "4321"; /*array*/ int i, j, f; asm("movl $24, %0;" :"=r"(f)) ; /*f=24*/ char c; while (f--) { printf("%s\n", a); asm ("movl $1, %0;" :"=r"(i)); /*i=1*/ while(a[i] >= a[i-1]) i++; asm ("movl $0, %0;" :"=r"(j)); /*i=1*/ while(a[j] <= a[i])j++; c=a[j]; a[j]=a[i]; a[i]=c; i--; for (j = 0; j < i; i--, j++) { c = a[i]; a[i] = a[j]; a[j] = c; } } } Если я верно перевёл: Код (Text): asm ("movl $1, %0;" /*Значение 1 помещается в аргумент 0*/ :"=r"(i)); /*i=1*/ /*Здесь указывается, с какой переменной связан аргумент 0*/ --- Сообщение объединено, 23 дек 2022 --- Вычитал где-то, что если требуется переменную в 0, то можно так, используя оператор xor: Код (Text): asm ("xor %0, %0;" :"=r"(j)); /*j=0*/ --- Сообщение объединено, 23 дек 2022 --- https://gitflic.ru/project/dcc0/mix-c-89-php/blob?file=permutations_iterative.c
Фантастика: синтаксис inline позволяет делать обмен (swap) переменными. Обнаружил также на Stack Overflow. --- Сообщение объединено, 24 дек 2022 --- То есть, если мне требуется сделать декремент переменной, то я должен делать его так: Код (Text): asm( "movl %[arg_a],%%eax\n\t" "decl %%eax\n\t" :"=a"(a) :[arg_a]"r"(a) :"cc"); В целом понятно. Только зачем два знака % перед регистром?! Почему я не могу использовать для операнда запись %0?! --- Сообщение объединено, 24 дек 2022 --- Финальный код в целом интересный получился: Код (Text): /*Порождение перестановок*/ #include <stdio.h> int main(){ int a[5] = {4,3,2,1}; /*Массив целых*/ int i, j, f, c; asm("movl $24, %0;" :"=r"(f)); /*f=24 факториал - !4*/ while (f--) { printf("%d%d%d%d\n", a[0], a[1], a[2], a[3]); asm ("movl $1, %0;" :"=r"(i)); /*i=1*/ while(a[i] >= a[i-1]) i++; asm ("xor %0, %0;" :"=r"(j)); /*j=0 Обнулим через строгую дизъюнкцию*/ while(a[j] <= a[i])j++; asm("" : "=r" (a[j]), "=r" (a[i]) : "0" (a[i]), "1" (a[j]) :); /*Обмен*/ asm( "movl %[arg_i],%%eax\n\t" "decl %%eax\n\t" :"=a"(i) :[arg_i]"r"(i) :"cc"); /*i-- 0 декремент i*/ for (j = 0; j < i; i--, j++) { asm("" : "=r" (a[j]), "=r" (a[i]) : "0" (a[i]), "1" (a[j]) :); /*Обмен хвоста*/ }}}