2011-12-09 15 views
1

linuxシステムコールまたは標準のCライブラリ関数を使用せずにC文字列を出力する簡単なプログラムを作成しようとしています。これは学習目的のみのためであり、私はそれを実際に生産することはありません。インラインアセンブリー - ローカルのchar *変数へのアクセス - gcc

まず私のシステム情報:

[[email protected] 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 
[[email protected] 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. 

次のコード:以下のmakefileでコンパイル

#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; 
} 

:物事がうまくコンパイル

all: sandbox_c 

sandbox_c: sandbox.c 
     gcc -Wall -o sandbox_c ./sandbox.c 
     gcc -S -Wall -o sandbox_c.asm ./sandbox.c 

、私はちょうど得るカント物事を動作させるための文法権あなたの訂正は非常に高く評価されますが、あなたが偉大なソリューションをどのように入手したかを私に指摘することもできます。

[[email protected] 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 
+0

実際にプログラムをx86ターゲットに限定しない限り、これを決して実動コードで実行しないでください。誰もが同じ方法でシステムコールをするわけではありませんし、確かに同じ指示を使用していません! – ams

答えて

2

はこれを試してみてください:

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

私はそれをテストしていませんでしたが、構文が右に見えます。システムコールが他のものを上書きする場合は、さらにいくつかの "clobbers"を追加する必要があります - ドキュメントを確認してください。

は、それを破壊:

  • "c"制約はすでにそれをしたので%ecx%0を移動する必要はありません。
  • strは入力ですが、出力として持っていました。
  • volatileは、コンパイラに出力を出さないように指示します。出力がないため、コンパイラは可能だと思うかもしれません。
  • コードによってどのようなレジスタが「clobbered」であるかコンパイラに伝える必要があります。私は明白なものを追加しましたが、システムコールがもっと壊れるかもしれませんか?
  • あなたはそれらをすべてasmに入れる必要があります。そうしないと、コンパイラはそれらを動かすと考えるかもしれません。
+0

私にそれを打つ;-) _single_ 'asm()'ブロック(つまり、_one_ 'asm'内のアセンブラ命令の複数行)を使用したり、ブロックvolatileを宣言したり、gcc _will_" optimize "あなたのアセンブリ、そして必ずしも予想通りのものではない。 –

0

:私はそのECXは、右のアドレスで指摘されていないことを確認でき、GDBを通じて実行可能ファイルを実行しているmanページなど


ADDITION を使用してのより良い取得しようとしていますそれが価値あるものであれば、 "int 0x80"をと呼ぶのはです。

"printf"を使用していないか、またはLinux syscall用の標準Cライブラリラッパーを使用しています。

そして、それと間違って何もない:)

とにかく、ここにあなたが後にしている正確に何を示す完全な例です:

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

「希望は助け...と楽しみを持っています!

+0

リンクをありがとう、私はすでにhello worldを印刷する純粋なアセンブリプログラムを持っています。私はインラインアセンブラを使用してCプログラムでchar *にアクセスする方法を理解しようとしています。 –

関連する問題