在x86 AT& T synatax中,如何将ASCII字符串推入堆栈? (或者C程序如何将ASCII字符串压入堆栈?)
我的尝试是创建数据部分,使用.asciz,然后使用LEA和MOV使用置换推送内容。但最终都出现了错误。
答案 0 :(得分:0)
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
,因此符号地址将是字符串常量的地址,而不是指针的地址。使用const char *str
导致加载(推送内存的内容),而不是push-immediate,为foo设置args。使用static const char *str
让编译器在编译时解析间接,push $.LC0, %edi
,从不打算在.rodata节中放置指向.LC0
的指针。
在64位模式下,使用-fPIC
进行编译将强制编译器使用RIP相对lea
而不是mov-immediate。在32位代码-fPIC
中,生成一些非常笨重的东西来获取EIP的当前值并在全局偏移表中找到符号地址。
我让hello
返回0而不是无效,所以我不必解释尾调用优化(jmp
而不是call
)。 (在32位模式下不会发生这种情况,因为调用者必须在foo返回后弹出arg。当我第一次写这个答案时,我忘记了问题是关于堆栈,而不仅仅是将字符串传递给函数.64位ABI通过寄存器中的args。)
答案 1 :(得分:-1)
这是我写的一个教程,你只需要定义你的字符串然后将字符串移动到堆栈。实际上它只移动起始地址,然后当你想要打印时指定偏移的长度。
wildcard query