在Linux上进行C内联汇编,将字符串从堆栈写入stdout

时间:2010-07-16 09:32:19

标签: c linux string assembly inline-assembly

如何从堆栈中向stdout写一个字符串(例如“Hello”)?没有,数据段,即。

void main() {
    __asm__(
                "movl  $0x4, %eax   \n\t"
                "movl  $0x1, %ebx   \n\t"
            //   put "Hello" on the stack and load its address into %ecx
                "movl  $0x5, %edx   \n\t"
                "int   $0x80        \n\t"

                "movl  $0x1, %eax   \n\t"
                "movl  $0x0, %ebx   \n\t"
                "int   $0x80        \n\t"
             );
}

提前致谢

3 个答案:

答案 0 :(得分:3)

答案1:

int main()
{
    const char* string = "hello";  // string is not in a data segment, it's in the text segment
    fputs(string, stdout);
    return 0;
}

答案2:

int main()
{
    char[6] string = "hello";  // Space for string allocated on stack
    fputs(string, stdout);
    return 0;
}

使用gcc,第二个答案似乎产生以下结果:

main:      
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    subl    $36, %esp
    movl    $1819043176, -10(%ebp) ;<< hell
    movw    $111, -6(%ebp)         ;<< o\0
    movl    stdout, %eax
    movl    %eax, 4(%esp)
    leal    -10(%ebp), %eax
    movl    %eax, (%esp)
    call    fputs
    movl    $0, %eax
    addl    $36, %esp
    popl    %ecx
    popl    %ebp
    leal    -4(%ecx), %esp

显然只使用堆栈。

答案 1 :(得分:0)

int main() {
        char *hello = "Hello world!\n";
        __asm__("\
                movl $4, %%eax\n\
                movl $0, %%ebx\n\
                push %0\n\
                pop %%ecx\n\
                movl $13,%%edx\n\
                int $0x80" : :"g"(hello));
        return 0;
}

我不明白堆栈部分。为什么不使用`movl%0,%% ecx'?

答案 2 :(得分:0)

  

如何从堆栈中向stdout写一个字符串(例如“Hello”)?没有,数据段,即。

有些事情:

  1. 在堆栈上分配缓冲区,比如说8个字节。 (查看GCC alloca()如何做到这一点。)
  2. 在缓冲区中创建字符串。 “Hello”字节为48 65 6c 6c 6f 00 00 00(对齐,用零填充)。两个32位常量 - 0x6c6c6548和0x0000006f - 应足以表示字符串。
  3. 将缓冲区的地址传递给write syscall。
  4. 将堆栈指针恢复到以前的位置(如果需要)。
  5. 不能更准确,因为我不是最新的GCC内联asm和x86 ABI。