2016-01-28 4 views
1

В x86 AT & T синтаксис, как вы нажимаете строку ASCII в стек? (Или как программа C вставляет строку ASCII в стек?)Как нажимать строку в стек в x86 (синтаксис AT & T)

Моя основная попытка состояла в том, чтобы создать раздел данных, использовать .asciz, а затем нажать на вещи, используя LEA и MOV, используя смещение. Но все закончилось ошибками.

+0

Подождите, вы имели в виду стек ('% rsp') или какой-либо другой стек? (т. е. структура данных стека) –

ответ

0

C программ не нажимают строки, они нажимают указатели на строки.

Программы Asm могут перемещать вещи переменной длины в стек, но это странно и редко полезно. При оптимизации кода учитывайте это только после, учитывая обычный способ.

Это может быть полезно для выделения пространства для ввода с переменным размером, доступного только по одному байту за раз, например, для чтения ввода. (Как и локальный массив с переменным размером, за исключением того, что вы увеличиваете его при чтении ввода, вместо того, чтобы выбирать размер до того, как вы закончите чтение.)

В любом случае, обычный способ (нажатие указателя) выглядит так: :

static const char str[] = "Hello World!"; 
void foo(const char*p); 
int hello(void) { 
    foo(str); 
    return 0; 
} 

and compiles to the following 32bit code (where the calling convention uses the stack)

hello: 
     subl $24, %esp  # keep the stack aligned for foo() 
     pushl $str   # push-immediate with the address of the string 
     call foo 
     xorl %eax, %eax  # return value 
     addl $28, %esp  # pop the arg and the padding 
     ret 

.section  .rodata 
     .align 8 
str: 
     .string "Hello World!" 

Обратите внимание, что я использовал const char str[] вместо const char *str поэтому адрес символа будет адрес строкового-Constant, а не адрес указателя. Использование const char *str приводит к загрузке (нажатию содержимого памяти), вместо push-instant, для настройки аргументов для foo. Использование static const char *str позволяет компилятору разрешить косвенность во время компиляции и push $.LC0, %edi, никогда не утруждая себя указателем на .LC0 в разделе .rodata.

В 64-битном режиме компиляция с помощью -fPIC заставит компилятор использовать RIP-relative lea вместо mov-instant. В 32-битном коде -fPIC создайте некоторые неуклюжие вещи, чтобы получить текущее значение EIP и найти адрес символа в глобальной таблице смещения.

Я сделал hello return 0 вместо того, чтобы быть недействительным, поэтому мне не пришлось объяснять оптимизацию хвостового вызова (jmp вместо call). (Что не происходит в 32-битном режиме, потому что вызывающий должен вызывать аргумент arg после возврата foo.Когда я впервые написал этот ответ, я забыл, что вопрос был о стеке, а не просто передает строки функциям. args в регистрах.)

-1

Это из учебника, который я написал, вам просто нужно определить вашу строку, а затем переместить строку в стек. В действительности он перемещает только начальный адрес, а затем, когда вы хотите распечатать, вы указываете длину для смещения.

Compiling assembler: nasm -felf64 "helloworld.asm"... 
Linking object helloworld.o: ld -melf_x86_64 -o helloworld helloworld.o ... 
Displaying helloworld.asm asm source: 
section  .text 
global  _start        ;must be declared for linker (ld) 

_start:           ;tell linker entry point 

    mov  rdx,len        ;message length 
    mov  rcx,msg        ;message to write 
    mov  rbx,1        ;file descriptor (stdout) 
    mov  rax,4        ;system call number (sys_write) 
    int  0x80        ;call kernel 

    mov  rax,1        ;system call number (sys_exit) 
    int  0x80        ;call kernel 

section  .data 

msg  db 'Hello, world!',0xa     ;our dear string 
len  equ $ - msg        ;length of our dear string 

Executing linked helloworld executable! ./helloworld | figlet .. 
_ _  _ _        _  _ _ 
| | | | ___| | | ___ __  _____ _ __| | __| | | 
| |_| |/ _ \ | |/ _ \ \ \ /\// _ \| '__| |/ _` | | 
| _ | __/ | | (_) | \ V V/(_) | | | | (_| |_| 
|_| |_|\___|_|_|\___() \_/\_/ \___/|_| |_|\__,_(_) 
        |/         
./helloworld: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped 
+0

это не синтаксис AT & T –