2015-11-18 3 views
1

Я пытаюсь понять, как монтажные работы, делая основную программу для отображения environement переменных какОтображение переменной среды в ассемблере

код C:

int   main(int ac, char **av, char **env) 
    { 
    int  x; 
    int  y; 

    y = -1; 
    while (env[++y]) 
     { 
     x = -1; 
     while (env[y][++x]) 
      { 
      write(1, &(env[y][x]), 1); 
      } 
     } 
    return (0); 
    } 

Я скомпилировал, что с GCC -S (на cygwin64), чтобы увидеть, как это сделать, и написал ему свой собственный путь (подобный, но не то же самое), но это не сработало ...

$>gcc my_av.s && ./a.exe 

    HOMEPATH=\Users\hadrien▒2▒p 

Мой код сборки:

 .file "test.c" 
    .LC0: 
     .ascii "\n\0" 
    .LC1: 
     .ascii "\033[1;31m.\033[0m\0" 
    .LC2: 
     .ascii "\033[1;31m#\033[0m\0" 
    .LCtest0: 
     .ascii "\033[1;32mdebug\033[0m\0" 
    .LCtest1: 
     .ascii "\033[1;31mdebug\033[0m\0" 
    .LCtest2: 
     .ascii "\033[1;34mdebug\033[0m\0" 

     .def main; .scl 2; .type 32; .endef 
    main: 
     /* initialisation du main */ 
     pushq %rbp 
     movq %rsp, %rbp 
     subq $48, %rsp 
     movl %ecx, 16(%rbp) /* int argc */ 
     movq %rdx, 24(%rbp) /* char **argv */ 
     movq %r8, 32(%rbp) /* char **env */ 

     /* saut de ligne */ 
     /* write init */ 
     movl $1, %r8d /* write size */ 
     movl $1, %ecx /* sortie standart */ 
     leaq .LC0(%rip), %rdx 
     /* write */ 
     call write 

     /* debut du code */ 
     movl $-1, -8(%rbp) /* y = -1 */ 
     jmp .Loop_1_condition 

    .Loop_1_body: 
     movl $-1, -4(%rbp) 
     jmp .Loop_2_condition 

    .Loop_2_body: 
     /* affiche le charactere */ 
     movl $1, %r8d 
     movl $1, %ecx 
     call write 

    .Loop_2_condition: 
     addl $1, -4(%rbp) /* x = -1 */ 
     movl -8(%rbp), %eax 
     cltq 
     addq 32(%rbp), %rax 
     movq (%rax), %rax 
     movq %rax, %rdx 
     movl -4(%rbp), %eax 
     cltq 
     addq %rdx, %rax 
     movq %rax, %rdx 
     movq (%rax), %rax 
     cmpq $0, %rax 
     jne .Loop_2_body 

     /* saut de ligne */ 
     movl $1, %r8d /* write size */ 
     movl $1, %ecx /* sortie standart */ 
     leaq .LC0(%rip), %rdx 
     call write 

    .Loop_1_condition: 
     addl $1, -8(%rbp) /* ++y */ 
     movl -8(%rbp), %eax 
     cltq /* passe eax en 64bits */ 
     addq 32(%rbp), %rax 
     movq (%rax), %rax 
     cmpq $0, %rax 
     jne .Loop_1_body 

     movl $1, %r8d /* write size */ 
     movl $1, %ecx /* sortie standart */ 
     leaq .LC0(%rip), %rdx 
     call write 

     /* fin du programme */ 
     movl $0, %eax /* return (0) */ 
     addq $48, %rsp 
     popq %rbp 
     ret 
     .def write; .scl 2; .type 32; .endef 

Может кто-нибудь объяснить мне, что не так с этим кодом, пожалуйста?

Кроме того, пытаясь решить проблему, я устал, чтобы заменить $ 0 на $ 97 на операцию cmpq, думая, что она остановится на символе 'a', но это не так ... Почему?

+0

Они, как вы используете 'y' компенсировать' env' в вашем ассемблере не выглядит правильно. Символ 'char *' больше одного байта. – Michael

+0

Кроме того, окружающая среда отличается, когда вы собираете с или gcc. Gcc добавляет «C-интерфейс» к прологу программы. – turboscrew

+0

См. Https://www.dropbox.com/s/pdcvw8q9ypxtapg/filexor.s.txt?dl=0 – turboscrew

ответ

0

У вас есть несколько вопросов. В этом коде (Loop2) у вас есть:

addq %rdx, %rax 
    movq %rax, %rdx 
    movq (%rax), %rax 
    cmpq $0, %rax 

movq (%rax), %rax прочитал следующие 8 символов в % бараков. Вас интересует только первый персонаж. Одним из способов достижения этой цели является сравнение младший байт в % RAx с 0. Вы можете использовать CMPB и использовать% Аl регистр:

cmpb $0, %al 

Самая большая проблема, хотя понимание того, что char **env является указатель на массив из char *. Сначала вам нужно получить базовый указатель для массива, тогда этот указатель базы индексируется с помощью y. Индексирование выглядит примерно так: basepointer + (y * 8). Вам нужно умножить y на 8, потому что каждый указатель имеет ширину 8 байтов. Указатель в этом месте будет char * для конкретной строки среды. Затем вы можете индексировать каждый символ в массиве строк до тех пор, пока не найдете нулевой символ NUL (0).

Я слегка изменен код и добавил комментарии на несколько строк, я изменил:

.file "test.c" 
.LC0: 
    .ascii "\x0a\0" 
.LC1: 
    .ascii "\033[1;31m.\033[0m\0" 
.LC2: 
    .ascii "\033[1;31m#\033[0m\0" 
.LCtest0: 
    .ascii "\033[1;32mdebug\033[0m\0" 
.LCtest1: 
    .ascii "\033[1;31mdebug\033[0m\0" 
.LCtest2: 
    .ascii "\033[1;34mdebug\033[0m\0" 

    .def main; .scl 2; .type 32; .endef 
main: 
    /* initialisation du main */ 
    pushq %rbp 
    movq %rsp, %rbp 
    subq $48, %rsp 
    movl %ecx, 16(%rbp) /* int argc */ 
    movq %rdx, 24(%rbp) /* char **argv */ 
    movq %r8, 32(%rbp) /* char **env */ 

    /* saut de ligne */ 
    /* write init */ 
    movl $1, %r8d /* write size */ 
    movl $1, %ecx /* sortie standart */ 
    leaq .LC0(%rip), %rdx 
    /* write */ 
    call write 

    /* debut du code */ 
    movl $-1, -8(%rbp) /* y = -1 */ 
    jmp .Loop_1_condition 

.Loop_1_body: 
    movl $-1, -4(%rbp) 
    jmp .Loop_2_condition 

.Loop_2_body: 
    /* affiche le charactere */ 
    movl $1, %r8d 
    movl $1, %ecx 
    call write 

.Loop_2_condition: 
    addl $1, -4(%rbp) /* x = -1 */ 
    movl -8(%rbp), %eax  /* get y index */ 
    cltq 
    movq 32(%rbp), %rbx  /* get envp (pointer to element 0 of char * array) */ 
    movq (%rbx,%rax,8), %rdx /* get pointer at envp+y*8 
            pointers are 8 bytes wide */ 

    movl -4(%rbp), %eax  /* get x */ 
    cltq 
    leaq (%rdx, %rax), %rdx /* Get current character's address */ 
    cmpb $0, (%rdx)   /* Compare current byte to char 0 
            using cmpq will compare the next 8 bytes */ 
    jne .Loop_2_body 

    /* saut de ligne */ 
    movl $1, %r8d /* write size */ 
    movl $1, %ecx /* sortie standart */ 
    leaq .LC0(%rip), %rdx 
    call write 

.Loop_1_condition: 
    addl $1, -8(%rbp) /* ++y */ 
    movl -8(%rbp), %eax 
    cltq /* passe eax en 64bits */ 
    movq 32(%rbp), %rbx  /* get envp (pointer to element 0 of char * array) */ 
    movq (%rbx,%rax,8), %rax /* get pointer at envp+y*8 
            pointers are 8 bytes wide */ 
    cmpq $0, %rax    /* Compare to NULL ptr */ 
    jne .Loop_1_body 

    movl $1, %r8d /* write size */ 
    movl $1, %ecx /* sortie standart */ 
    leaq .LC0(%rip), %rdx 
    call write 

    /* fin du programme */ 
    movl $0, %eax /* return (0) */ 
    addq $48, %rsp 
    popq %rbp 
    ret 
    .def write; .scl 2; .type 32; .endef 
+0

Спасибо ОЧЕНЬ много! Спасибо, что потратили время на исправление моего кода! Вы решили проблему и объяснили, что было не так и почему ... отлично! люблю тебя <3 Знаю, что я понимаю, почему gcc -S делал что-то вроде: leaq 0 (,% rax, 8),% rdx, похоже на ваше: movq (% rbx,% rax, 8),% rax , правильно ? – Hadrien

+0

Если бы я разбирал массив int вместо массива char, я бы это изменил: leaq (% rdx,% rax),% rdx, to: leaq (% rdx,% rax, 4),% rdx? – Hadrien

+0

@Hadrien: Вы правы –

Смежные вопросы