アプリ版:「スタンプのみでお礼する」機能のリリースについて

(mainadd.c)
#include <stdio.h>
void intadd(int, int, int*);
void main()
{
int a,b,c;
printf("Enter a,b : ");
scanf("%d %d", &a, &b);
intadd(a, b, &c);
printf("Answer = %d\n", c);
}

(intadd.s)
.file "intadd.s"
.text
.align 4
.globl intadd
.type intadd,@function
intadd:
pushl %ebp
movl %esp, %ebp
bpoint1:
movl 16(%ebp), %ebx
movl 8(%ebp), %edx
addl 12(%ebp), %edx
movl %edx, (%ebx)
bpoint2:
#
movl %ebp, %esp
popl %ebp
ret

(comfile)
break main
display/i $pc
display/x $ebx
display/x $edx
display/x $esp
display/x $ebp

>gcc -m32 -o mainadd mainadd.c intadd.s
>gdb -x comfile mainadd

として、
a=1
b=2
を入力してデバッグを行うと、Cのprintf("Answer = %d\n", c);の中で、Segmentation faultがおきてしまいます。一応、以下に示すように%ebxが示すアドレス(cのアドレスが入っている)には、0x3(cの値)が正しく入っている様なのですが、何故か以下の箇所でSegmentation faultが起きてしまう理由が分かりかねています。似たようなご経験のある方で、アドバイス頂けると助かります。

(ここから途中からのデバッグ情報です)
0x56556030 in printf@plt ()
1: x/i $pc
=> 0x56556030 <printf@plt>: jmp *0xc(%ebx)
2: /x $ebx = 0xffffd834
3: /x $edx = 0x3
4: /x $esp = 0xffffd81c
5: /x $ebp = 0xffffd848
(gdb) si
0xffffd860 in ?? ()
1: x/i $pc
=> 0xffffd860: add %eax,(%eax)
2: /x $ebx = 0xffffd834
3: /x $edx = 0x3
4: /x $esp = 0xffffd81c
5: /x $ebp = 0xffffd848
(gdb) si
0xffffd862 in ?? ()
1: x/i $pc
=> 0xffffd862: add %al,(%eax)
2: /x $ebx = 0xffffd834
3: /x $edx = 0x3
4: /x $esp = 0xffffd81c
5: /x $ebp = 0xffffd848
(gdb) si
0xffffd864 in ?? ()
1: x/i $pc
=> 0xffffd864: hlt
2: /x $ebx = 0xffffd834
3: /x $edx = 0x3
4: /x $esp = 0xffffd81c
5: /x $ebp = 0xffffd848
(gdb) si

Program received signal SIGSEGV, Segmentation fault.
0xffffd864 in ?? ()
1: x/i $pc
=> 0xffffd864: hlt
2: /x $ebx = 0xffffd834
3: /x $edx = 0x3
4: /x $esp = 0xffffd81c
5: /x $ebp = 0xffffd848
(gdb) x/x $ebx
0xffffd834: 0x00000003

質問者からの補足コメント

  • movl $ebp, %esp
    で行っていると思うのですが。
    ただ、この場合は、
    mov $esp, %ebp
    以下で$espの値は変更していません。

    No.1の回答に寄せられた補足コメントです。 補足日時:2021/03/11 18:14
  • ecxかedxを使うと言うことですか?

    No.2の回答に寄せられた補足コメントです。 補足日時:2021/03/12 00:08
  • (1)ebx -> ecx
    にするとOKになるのですが、
    (2)ebxをそのまま使って、
    pushl %ebp
    pushl %ebx
    .
    .
    .
    popl %ebx
    popl %ebp
    ret
    としても動きそうに思うのですが、Segmentation fault
    になってしまうようなのですが、どうしてなのでしょうか?

    No.3の回答に寄せられた補足コメントです。 補足日時:2021/03/12 01:23
  • intadd:
    pushl %ebp
    push %ebx
    movl %esp, %ebp
    bpoint1:
    movl 16(%ebp), %ebx
    movl 8(%ebp), %edx
    addl 12(%ebp), %edx
    movl %edx, (%ebx)
    bpoint2:
    #
    movl %ebp, %esp
    pool %ebx
    popl %ebp
    ret

    No.4の回答に寄せられた補足コメントです。 補足日時:2021/03/12 01:47
  • intadd:
    pushl %ebp
    push %ebx
    movl %esp, %ebp
    bpoint1:
    movl 20(%ebp), %ebx
    movl 12(%ebp), %edx
    addl 16(%ebp), %edx
    movl %edx, (%ebx)
    bpoint2:
    #
    movl %ebp, %esp
    pool %ebx
    popl %ebp
    ret

    No.5の回答に寄せられた補足コメントです。 補足日時:2021/03/12 09:33

A 回答 (5件)

ebx をぶち壊したのが敗因のような気がする... あ, デバッグ情報にも書いてあった.

この回答への補足あり
    • good
    • 0

そうなってるんじゃないかなぁと想像はしてた.



スタックのどこにどのようなデータがあるのか, 図にしてみてみよう. そして「16(%ebp)」や「8(%ebp)」などがなにに対応しているのか, 元の質問文のプログラムと書き換えたあとのプログラムとでそれぞれ考えてみてください.
この回答への補足あり
    • good
    • 0

pushl %ebx



popl %ebx
の間, そこだと
「.
.
.」
となっている部分をどうしたのか, 全部書いてください.
この回答への補足あり
    • good
    • 0

どのレジスタを壊してよくってどのレジスタを壊しちゃダメなのかは, 調べればわかるはず. 通常 edx は壊しても問題ないんだけど, 「どんなシステムでも問題ない」とはいわないので調べてくれ.



あと, 「ebx をぶち壊した」のがなぜ敗因なのかは理解できているんですよね?
この回答への補足あり
    • good
    • 0

intaddでespを元に戻していないからでは。

この回答への補足あり
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!