2015-12-23 2 views
2

Итак, я пытаюсь использовать функцию scanf в 32-битной ATT-сборке и продолжать получать ошибки сегментации, несмотря на то, что использует почти такой же код, как пример, показанный в Computer Systems: A Programmer's Perspective, и сборку, созданную из моего собственного простого C входной программы. Я понятия не имею, что я делаю неправильно и буду признателен за помощь в выяснении этого.32b x86 сборка scanf использование

Мой код Контрольное устройство (которое возвращает ошибку сегментации):

.data 
    .align 4 
fmt: .string "%d" 
str: .string "Input a number: " 
    .text 

    .global main 
    .type main, @function 
main: 
    pushl %ebp 
    movl %esp, %ebp 

    subl $40, %esp 

    movl $str, (%esp) 
    call printf 

    leal 36(%esp), %eax 
    movl %eax, 4(%esp) 
    movl $fmt, (%esp) 
    call scanf 

    pushl -4(%ebp) 
    call printf 

    movl %ebp, %esp 
    popl %ebp 
    ret 

код C, и это сборка:

C:

#include <stdio.h> 

int main() 
{ 
    int i, j; 
    printf("%s\n","Enter 2 numbers:"); 
    scanf("%d %d",&i,&j); 
    printf("i = %d and j = %d\n",i,j); 
    return 0; 
} 

сборки:

.file "scan.c" 
    .section .rodata 
.LC0: 
    .string "Enter 2 numbers:" 
.LC1: 
    .string "%d %d" 
.LC2: 
    .string "i = %d and j = %d\n" 
    .text 
    .globl main 
    .type main, @function 
main: 
.LFB0: 
    .cfi_startproc 
    pushl %ebp 
    .cfi_def_cfa_offset 8 
    .cfi_offset 5, -8 
    movl %esp, %ebp 
    .cfi_def_cfa_register 5 
    andl $-16, %esp 
    subl $32, %esp 
    movl $.LC0, (%esp) 
    call puts 
    leal 28(%esp), %eax 
    movl %eax, 8(%esp) 
    leal 24(%esp), %eax 
    movl %eax, 4(%esp) 
    movl $.LC1, (%esp) 
    call __isoc99_scanf 
    movl 28(%esp), %edx 
    movl 24(%esp), %eax 
    movl %edx, 8(%esp) 
    movl %eax, 4(%esp) 
    movl $.LC2, (%esp) 
    call printf 
    movl $0, %eax 
    leave 
    .cfi_restore 5 
    .cfi_def_cfa 4, 4 
    ret 
    .cfi_endproc 
.LFE0: 
    .size main, .-main 
    .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4" 
    .section .note.GNU-stack,"",@progbits 

пример в книге (в обрезанный снимок экрана): http://i.imgur.com/zYaHZP5.jpg

+0

Для чего это платформа? – fuz

+1

@DavidHoelzer '$ fmt' - это значение символа' fmt', 'fmt' - это значение по адресу' $ fmt'. У вас это не так. – fuz

+0

Если компилятор не делает это неправильно, я действительно хочу '$ fmt'. – Sunspawn

ответ

5

Вы просто забыли строку формата для printf. Вы фактически делаете printf(i) вместо printf("%d", i). Таким образом изменится:

pushl -4(%ebp) 
call printf 

To:

pushl -4(%ebp) 
pushl $fmt 
call printf 

PS: научиться использовать отладчик.

+1

Я собирался написать это. – fuz

+0

Поскольку я могу вытолкнуть строки из сегмента данных таким образом без строки форматирования, я думал, что могу сделать это с помощью случайных чисел. Очевидно нет. – Sunspawn

+1

Когда вы передаете строку, которая ** является ** строкой формата. Вы можете сделать 'printf (« hello »);' который имеет 'hello' как строку формата без каких-либо спецификаций. Обратите внимание, что прототип (как будет указано вам любой ссылкой на C): 'int printf (const char * format, ...);' – Jester

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