1

我正在尝试编写一个简单的程序来打印出一个 C 字符串,而不使用其中一个 linux 系统调用或标准 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

事情编译得很好,我只是无法正确使用语法来让事情正常工作。非常感谢您的更正,但如果您也可以指出您是如何获得解决方案的,那就太好了。我正在尝试更好地使用手册页等。


添加通过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
4

2 回答 2

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 中,否则编译器可能会认为它可以移动它们。
于 2011-12-09T09:59:18.243 回答
0

不管它值多少钱,调用“int 0x80”就是进行系统调用。

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

这没有什么问题:)

无论如何,这是一个完整的示例,可以准确说明您所追求的:

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

'希望这会有所帮助......玩得开心!

于 2011-12-09T06:51:04.383 回答