内联汇编 - 访问本地char *变量 - gcc

时间:2011-12-09 06:41:12

标签: gcc inline-assembly gas

我正在尝试编写一个简单的程序,在不使用linux系统调用或标准C库函数的情况下打印出一个C字符串。这仅用于学习目的,我绝不会在制作中这样做(除非我真的很擅长它=))。

首先我的系统信息:

[mehoggan@fedora sandbox-print_chars]$ uname -a
Linux fedora.laptop 2.6.35.14-106.fc14.i686.PAE #1 SMP Wed Nov 23 13:39:51 UTC 2011 i686 i686 i386 GNU/Linux
[mehoggan@fedora sandbox-print_chars]$ gcc --version
gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

接下来是代码:

#include <unistd.h>
#include <sys/syscall.h>

void main()
{
    char *str = "Hello World";
    while(*(str) != '\0') {
        //printf("%c", *(str++));
        //syscall(__NR_write, 1, *(str++), 1);
        __asm__( "movl %0, %%ecx" :"=c" (str));
        __asm__( "movl $0X4, %eax" );
        __asm__( "movl $0X1, %ebx" );
        __asm__( "movl $0X1, %edx" );
        __asm__( "int $0X80" );
        str++;
    }
    return;
}

使用以下makefile编译:

all: sandbox_c

sandbox_c: sandbox.c
        gcc -Wall -o sandbox_c ./sandbox.c
        gcc -S -Wall -o sandbox_c.asm ./sandbox.c
事情编译得很好,我不能让语法正确,让事情发挥作用。非常感谢您的更正,但如果您还能指出我如何获得可能很棒的解决方案。我正试图更好地使用手册等。


ADDITION 通过gdb运行可执行文件我可以看到ecx没有指向正确的地址:

[mehoggan@fedora sandbox-print_chars]$ gdb ./sandbox_c
GNU gdb (GDB) Fedora (7.2-52.fc14)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/mehoggan/Code/Assembly/sandbox/sandbox-print_chars/sandbox_c...done.
(gdb) break sandbox.c:8
Breakpoint 1 at 0x80483a2: file ./sandbox.c, line 8.
(gdb) run
Starting program: /home/mehoggan/Code/Assembly/sandbox/sandbox-print_chars/sandbox_c 

Breakpoint 1, main () at ./sandbox.c:8
8       while(*(str) != '\0') {
Missing separate debuginfos, use: debuginfo-install glibc-2.13-2.i686
(gdb) step
11          __asm__( "movl %0, %%ecx" :"=c" (str));
(gdb) info registers
eax            0x48 72
ecx            0x34092fad   873017261
edx            0x1  1
ebx            0x567ff4 5668852
esp            0xbffff2a4   0xbffff2a4
ebp            0xbffff2b8   0xbffff2b8
esi            0x0  0
edi            0x0  0
eip            0x80483a4    0x80483a4 <main+16>
eflags         0x200206 [ PF IF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51
(gdb) step
12          __asm__( "movl $0X4, %eax" );
(gdb) info registers
eax            0x48 72
ecx            0x34092fad   873017261
edx            0x1  1
ebx            0x34092fad   873017261
esp            0xbffff2a4   0xbffff2a4
ebp            0xbffff2b8   0xbffff2b8
esi            0x0  0
edi            0x0  0
eip            0x80483ab    0x80483ab <main+23>
eflags         0x200206 [ PF IF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51
(gdb) step
13          __asm__( "movl $0X1, %ebx" );
(gdb) info registers
eax            0x4  4
ecx            0x34092fad   873017261
edx            0x1  1
ebx            0x34092fad   873017261
esp            0xbffff2a4   0xbffff2a4
ebp            0xbffff2b8   0xbffff2b8
esi            0x0  0
edi            0x0  0
eip            0x80483b0    0x80483b0 <main+28>
eflags         0x200206 [ PF IF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51
(gdb) step
14          __asm__( "movl $0X1, %edx" );
(gdb) info registers
eax            0x4  4
ecx            0x34092fad   873017261
edx            0x1  1
ebx            0x1  1
esp            0xbffff2a4   0xbffff2a4
ebp            0xbffff2b8   0xbffff2b8
esi            0x0  0
edi            0x0  0
eip            0x80483b5    0x80483b5 <main+33>
eflags         0x200206 [ PF IF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51
(gdb) step
15          __asm__( "int $0X80" );
(gdb) info registers
eax            0x4  4
ecx            0x34092fad   873017261
edx            0x1  1
ebx            0x1  1
esp            0xbffff2a4   0xbffff2a4
ebp            0xbffff2b8   0xbffff2b8
esi            0x0  0
edi            0x0  0
eip            0x80483ba    0x80483ba <main+38>
eflags         0x200206 [ PF IF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51
(gdb) step
16          str++;
(gdb) info registers
eax            0xfffffff2   -14
ecx            0x34092fad   873017261
edx            0x1  1
ebx            0x1  1
esp            0xbffff2a4   0xbffff2a4
ebp            0xbffff2b8   0xbffff2b8
esi            0x0  0
edi            0x0  0
eip            0x80483bc    0x80483bc <main+40>
eflags         0x200206 [ PF IF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51

2 个答案:

答案 0 :(得分:2)

试试这个:

__asm__ volatile ( "movl $0X4, %eax
                    movl $0X1, %ebx
                    movl $0X1, %edx
                    int $0X80"
                   : /* outputs:  */ /* none */
                   : /* inputs:   */ "c" (str)
                   : /* clobbers: */ "eax", "ebx", "edx");

我没有测试过,但语法看起来不错。如果系统调用覆盖其他任何内容,您可能需要添加更多“clobbers” - 请查看文档。

打破它:

  • 无需将%0移至%ecx,因为"c"约束已经执行了此操作。
  • str是一个输入,但您已将其作为输出。
  • volatile告诉编译器不要删除它 - 它没有输出,所以编译器可能认为它可以。
  • 您需要告诉编译器代码中哪些寄存器被“破坏”。我添加了明显的,但系统调用可能会破坏更多?
  • 您需要将它们放在所有asm中,否则编译器可能认为它可以移动它们。

答案 1 :(得分:0)

无论它值多少,调用“int 0x80” 进行系统调用。

您只是没有使用“printf”,或者使用Linux系统调用的标准C库包装器。

这并没有错::)

无论如何,这里有一个完整的例子,说明你正在追求的是什么:

http://asm.sourceforge.net/intro/hello.html

'希望有帮助......并且玩得开心!