C программ не нажимают строки, они нажимают указатели на строки.
Программы Asm могут перемещать вещи переменной длины в стек, но это странно и редко полезно. При оптимизации кода учитывайте это только после, учитывая обычный способ.
Это может быть полезно для выделения пространства для ввода с переменным размером, доступного только по одному байту за раз, например, для чтения ввода. (Как и локальный массив с переменным размером, за исключением того, что вы увеличиваете его при чтении ввода, вместо того, чтобы выбирать размер до того, как вы закончите чтение.)
В любом случае, обычный способ (нажатие указателя) выглядит так: :
static const char str[] = "Hello World!";
void foo(const char*p);
int hello(void) {
foo(str);
return 0;
}
and compiles to the following 32bit code (where the calling convention uses the stack)
hello:
subl $24, %esp # keep the stack aligned for foo()
pushl $str # push-immediate with the address of the string
call foo
xorl %eax, %eax # return value
addl $28, %esp # pop the arg and the padding
ret
.section .rodata
.align 8
str:
.string "Hello World!"
Обратите внимание, что я использовал const char str[]
вместо const char *str
поэтому адрес символа будет адрес строкового-Constant, а не адрес указателя. Использование const char *str
приводит к загрузке (нажатию содержимого памяти), вместо push-instant, для настройки аргументов для foo. Использование static const char *str
позволяет компилятору разрешить косвенность во время компиляции и push $.LC0, %edi
, никогда не утруждая себя указателем на .LC0
в разделе .rodata.
В 64-битном режиме компиляция с помощью -fPIC
заставит компилятор использовать RIP-relative lea
вместо mov-instant. В 32-битном коде -fPIC
создайте некоторые неуклюжие вещи, чтобы получить текущее значение EIP и найти адрес символа в глобальной таблице смещения.
Я сделал hello
return 0 вместо того, чтобы быть недействительным, поэтому мне не пришлось объяснять оптимизацию хвостового вызова (jmp
вместо call
). (Что не происходит в 32-битном режиме, потому что вызывающий должен вызывать аргумент arg после возврата foo.Когда я впервые написал этот ответ, я забыл, что вопрос был о стеке, а не просто передает строки функциям. args в регистрах.)
Подождите, вы имели в виду стек ('% rsp') или какой-либо другой стек? (т. е. структура данных стека) –