어셈블리어 관련질문

esaram5의 이미지

c언어를 어셈블리로 번역하는 과정에서 막혔습니다
ㅜㅜ
현재 할려고 하는 작업은 최대 공약수를 구하려는 것이고
원본인 c언어 소스코드는 이겁니다.

int gcd (int n, int m, int l)
{
	int i, j;
 
	if (n > m)	j = n;
	else		j = m;
 
	if (j > l)	j = l;
 
	for (i=j; i>0; i--)
		if (n%i == 0 && m%i == 0 && l%i == 0)
			break;
	return i;
}

Floating point exception (core dumped)라는 오류가 발생하는데 왜 그런지 알 수 있을까요?
그리고 idivl에 대해서 한번 설명해주시면 감사하겠습니다ㅜㅜ
 
movl %esi, %r15d # j=m
cmpl %edi, %esi # ===if (n>m)
cmovg %edi, %r15d  # j=n
 
cmpl %r15d, %edx # j > l
cmovg %edx, %r15d #j = l
 
 
movl %r15d, %r14d # i=j 초기조건 구현
 
.L1:
cmpl $0, %r14d # i= 0
je .L2 #for문 구현
 
movl $0, %edx
movl %edi, %eax
 
idivl %r14d
 
cmpl $0, %edx # n%i==0
decl %r14d # i--
jne .L1
 
movl %esi, %eax
idivl %r14d
cmpl $0, %edx # n%i==0
decl %r14d # i--
jne .L1
 
movl %edx, %eax
idivl %r14d
cmpl $0, %edx # n%i==0
decl %r14d # i--
jne .L1
 
.L2:
movl %r14d, %eax # return 만들기
ret
익명 사용자의 이미지

1. C 코드 로직이 이상하군요.

위 코드대로라면 j = min(max(m, n), l)이 됩니다. 그걸 의도한 게 맞나요?
아마도 j = min(m, n, l)이어야 할 텐데요.

2. 어셈블리도 이상합니다.

1)

movl %esi, %r15d # j=m
cmpl %edi, %esi # ===if (n>m)
cmovg %edi, %r15d  # j=n

이렇게 되면 esi > edi일 때, 즉 m > n일 때 j = n이 되는 것 아닌가요?

인텔 어셈블리의 AT&T 문법은 늘 헷갈리는군요. 제가 Intel 문법으로 처음 공부해서 그런 것 같습니다만
한번 더 확인해보시길.

2)

cmpl $0, %edx # n%i==0
decl %r14d # i--
jne .L1

위 코드가 세 번 반복되는데, 나머지가 0일 경우에는 밑으로 흐르면서 i가 무조건 감소하는군요.

그게 원했던 코드인가요? 아닐 텐데요.

3. 예시 답안을 참고하세요.

어셈블리를 배울 때 효과적인 방법은 컴파일러의 출력을 보는 것입니다.
요즘 컴파일러 정말 좋거든요.

gcd:
        movl    %edi, %ecx
        movl    %esi, %r8d
        movl    %edx, %edi
        cmpl    %esi, %ecx
        cmovge  %ecx, %r8d
        cmpl    %edx, %r8d
        cmovg   %edx, %r8d
        testl   %r8d, %r8d
        jle     .L1
.L4:
        movl    %ecx, %eax
        cltd
        idivl   %r8d
        testl   %edx, %edx
        jne     .L3
        movl    %esi, %eax
        cltd
        idivl   %r8d
        testl   %edx, %edx
        jne     .L3
        movl    %edi, %eax
        cltd
        idivl   %r8d
        testl   %edx, %edx
        je      .L1
.L3:
        subl    $1, %r8d
        jne     .L4
.L1:
        movl    %r8d, %eax
        ret

x86-64 gcc 11.1에 -O3 주고 돌린 결과입니다.

4. x86-64 어셈블리는 인터넷에 자료가 정말 많습니다.

idiv 설명은 대충 뭐 https://www.felixcloutier.com/x86/idiv 정도로 갈음하지요.

esaram5의 이미지

많은 도움 감사합니다. 덕분에 고칠 수 있었어요!