2011-12-09 2 views
1

리눅스 시스템 호출이나 표준 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. 

다음 코드 :

#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"); 

나는 그것을 테스트하지했습니다,하지만 구문이 바로 보인다. syscall이 다른 것을 덮어 쓰는 경우 "clobbers"를 더 추가해야 할 수도 있습니다. 설명서를 확인하십시오.

하면 무너 뜨 :

  • "c" 제약 조건이 이미를했기 때문에 %ecx%0를 이동할 필요가 없습니다.
  • str은 입력이지만 출력으로 사용했습니다.
  • volatile은 컴파일러가 제거하지 않도록 지시합니다. 컴파일러가 생각할 수 있도록 출력이 없습니다.
  • 코드에 의해 'clobbered'된 레지스터를 컴파일러에 알려줘야합니다. 나는 명백한 것을 추가했지만 시스템 호출이 더 많이 충돌 할 수 있습니까?
  • 당신은 그들을 모두 asm에 넣어야합니다. 그렇지 않으면 컴파일러가 그것들을 움직일 수 있다고 생각할 수도 있습니다.
+0

저를 두렵게하십시오 ;-) _single_'asm()'블록 (예 : _one_'asm' 내에서 여러 줄의 어셈블러 명령어)을 사용하거나 블록 휘발성을 선언하지 않는 한이 모든 점을 수정하십시오. gcc _will_ "optimize "당신의 어셈블리, 그리고 반드시 예상대로 아닙니다. –

0

: 나는 그 ECX가 올바른 주소로 지적되고 있지 볼 수 있습니다 gdb를 통해 실행 파일을 실행 매뉴얼 페이지 등


ADDITION 를 사용하여 더 나은 얻기 위해 노력하고 있어요 가치가있는 것이면 "int 0x80"을 호출하면 시스템 호출을하는이됩니다.

"printf"를 사용하지 않거나 Linux syscall 용 표준 C 라이브러리 래퍼를 사용하고 있습니다.

그리고 그 :)

어쨌든 아무 문제가 없습니다, 여기 당신이있어 정확히 보여주는 완벽한 예입니다 후 :

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

'하는 데 도움이 ... 재미를 희망!

+0

링크를 제공해 주셔서 감사합니다. 안녕하세요! 안녕하세요. 안녕하세요. 인라인 어셈블리를 통해 C 프로그램에서 char *에 액세스하는 방법을 파악하려고합니다. –

관련 문제