2016-02-13 4 views
-1
.text 
    .global main 
main: 
    pushq $10 
    popq %rdx 
    movq $formatString, %rdi 
    call printf 
    mov $0,%rax 
    ret 
.data 
formatString: 
.string "%d\n" 

Этот код дает мне ошибку сегментации. Это очень просто. Нажмите 10 на стопку. Поп 10 со стека и поместите его в rdx. Переместите мой форматString в rdi. Вызовите printf. Вот и все.Сегментация Неисправность вызова printf

Почему это дает мне ошибку сегментации?

Спасибо!

+2

Вы знаете, что можете «mov $ 10,% edx', правильно? Теперь это всего лишь дубликат многих забытых до нуля-rax, прежде чем вызывать вопрос функции var-args. Я связал один из них как возможный дубликат по вашему предыдущему вопросу. 'push'ing dummy register - полезный способ выровнять стек перед' вызовом', в функции, которая иначе не требует резервирования какого-либо пространства. Также прочитайте документы ABI. Второй аргумент не входит в '% rdx'. –

+1

Возможный дубликат [Попытка добавления двух ints, в x86, однако, когда я добавляю, я получаю мусор вместо значения. что я делаю неправильно?] (http://stackoverflow.com/questions/28706080/trying-to-add-two-ints-in-x86-however-when-i-add-i-get-garbage-instead- of-a-val) –

+3

Стек также должен быть выровнен по 16-байтовой границе, _RAX_ должен быть равен нулю в этом случае, потому что вы не используете векторные регистры. –

ответ

1

Этот код может работать:

.text 
    .global main 
main: 
    add $-8, %rsp    # Stack is misaligned by 8 after call to main 
          # Subtract 8 to align it on 16-byte boundary 
    xor %rax, %rax   # RAX = 0 since no vector registers used for calling printf 
          # This is important for functions that take variable 
          # number of arguments 
    movq $formatString, %rdi # First parameter (format) in RDI 
    movq $10, %rsi   # second parameter in RSI not RDX 
    call printf 

    add $8, %rsp    # Restore stack to proper state 
    ret 

.data 
formatString: 
.string "%ld\n"    # If printing longs use %ld 

Вместо add $-8, %rsp и add $8, %rsp для выравнивания стека можно использовать все, что настраивает стек на 8 байт. push %rbx и pop %rbx тоже сработали бы.

В качестве альтернативы можно заменить:

movq $formatString, %rdi # First parameter (format) in RDI 

С:

leaq formatString(%rip), %rdi 

Последний использует RIP-относительной адресации, а не абсолютным.

Дополнительную информацию о 64-разрядной системе Linux V ABI можно найти в этом document.

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