【问题标题】:32b x86 assembly scanf usage32b x86 程序集 scanf 用法
【发布时间】:2016-03-30 09:37:54
【问题描述】:

所以,我尝试在 32 位 ATT 程序集中使用 scanf 函数并不断出现分段错误,尽管使用的代码与 Computer Systems: A Programmer's Perspective 中显示的示例几乎相同,并且程序集由我自己的简单 C 输入生成程序。我不知道我做错了什么,希望能得到一些帮助。

我的测试汇编代码(段错误):

    .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

书中的例子(截屏):

【问题讨论】:

  • 这是用于什么平台的?
  • @DavidHoelzer $fmt 是符号fmt 的值,fmt 是地址$fmt 的值。你弄错了。
  • 除非编译器做错了,否则我确实想要$fmt
  • @FUZxxl 如果我没看错你的问题,那是针对 unix 的。
  • @Sunspawn 不同的 Unices 有不同的调用约定和符号命名方案。如果您能将其缩小到一个系统,那将会有所帮助。

标签: c assembly segmentation-fault scanf


【解决方案1】:

您只是忘记了printf 的格式字符串。 您有效地使用printf(i) 而不是printf("%d", i)。 从而改变:

pushl   -4(%ebp)
call    printf

收件人:

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

PS:学习使用调试器。

【讨论】:

  • 我正要写这个。
  • 因为我可以以这种方式从数据段中推送字符串而无需格式字符串,所以我想我可以只使用随机数来做到这一点。显然不是。
  • 当你传递一个格式字符串的字符串。您可以使用 printf("hello");hello 作为格式字符串,而无需任何说明符。请注意,原型(任何 C 参考都会告诉您)是:int printf(const char *format, ...);
猜你喜欢
  • 2015-01-21
  • 2023-03-03
  • 1970-01-01
  • 2021-04-24
  • 1970-01-01
  • 1970-01-01
  • 2012-03-11
  • 2011-05-26
相关资源
最近更新 更多