Встроенная сборка - Доступ к локальной переменной char * - gcc - PullRequest
1 голос
/ 09 декабря 2011

Я пытаюсь написать простую программу, которая печатает строку 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;
}

Скомпилирован со следующим make-файлом:

all: sandbox_c

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

Вещи компилируются просто отлично, я просто не могу получить правильный синтаксис, чтобы заставить это работать.Мы очень ценим ваши исправления, но если бы вы могли также указать мне, как вы получили решение, это было бы здорово.Я пытаюсь улучшить работу с man-страницами и т. Д.


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 ]

2 голосов
/ 09 декабря 2011

Попробуйте:

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

Я не проверял, но синтаксис выглядит правильно.Возможно, вам придется добавить еще несколько «клобберов», если системный вызов перезаписывает что-то еще - проверьте документацию.

Разбивка:

  • Нет необходимости перемещать %0 в %ecx, потому что ограничение "c" уже сделало это.
  • str является входом, но вы получили его как выход.
  • volatile говорит компилятору не удалять его -у него нет выходных данных, поэтому компилятор может подумать, что он может.
  • Вы должны сообщить компилятору, какие регистры «засорены» кодом.Я добавил очевидные из них, но системный вызов может затормозить больше?
  • Вам нужно поместить их в один ассемблер, иначе компилятор может подумать, что он может их перемещать.
0 голосов
/ 09 декабря 2011

Во что бы то ни стало, вызов «int 0x80» означает системный вызов.

Вы просто не используете "printf" или не используете стандартные оболочки библиотеки C для системных вызовов Linux.

И в этом нет ничего плохого:)

В любом случае, вот полный пример, иллюстрирующий ТОЧНО, что вы ищете:

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

Надеюсь, это поможет ... и повеселиться!

...