如何在x86中将字符串推入堆栈(AT& T语法)

时间:2016-01-28 05:08:07

标签: x86 att

在x86 AT& T synatax中,如何将ASCII字符串推入堆栈? (或者C程序如何将ASCII字符串压入堆栈?)

我的尝试是创建数据部分,使用.asciz,然后使用LEA和MOV使用置换推送内容。但最终都出现了错误。

2 个答案:

答案 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