main.c-2

main5.c
#include<stdio.h>
/* 어셈블리 루틴의 원형 */
void calc_sum(int,int *)__attribute__((cdecl));
int main(void){
int n,sum;
printf("Sum integers up to:");
scanf("%d", &n);
calc_sum(n, &sum)
printf("Sum is %d\n",sum);
return 0;
}
sub5.asm
;서브루틴 _calc_sum
;1부터 n까지 정수들의 합을 구한다.
; 인자:
; n -어디까지 합할 지 저장([ebp+8]에 위치)
; sump -sum을 저장할 공간에 대한 int 포인터([[ebp+8] 에 위치)
;의사 C 코드:
;void calc_sum(int n, int *sump){
; int i,sum=0;
; for(i=1;i<=n;i++)
; sum+=i;
; *sump=sum;
;}
segment .text
global _calc_sum
;
; 지역변수:
; [ebp-4]에 위치한 합
_clac_sum:
enter 4,0 ;sum을 위한 스택 공간을 할당
push ebx ;EBX는 바뀌면 안되기 때문에 매우 중요!
mov dword [ebp-4],0 ;sum=0
dump_stack 1,2,4 ;ebp-8에서 ebp+16까지 스택을 출력
mov ecx,1 ;ecx는 의사코드의 i
for_loop:
cmp ecx,[ebp+8] ;cmp i & n
jnle end_for ;if i<=n가 아니면 종료
add [ebp-4],ecx ;sum+=i
inc ecx
jmp short for_loop
end_for:
mov ebx,[ebp+12] ;ebx=sump
mov eax,[ebp-4] ;eax=sum
mov [ebx],eax
pop ebx ;restore ebx
leave
24행은 dump_stack 메크로가 어떻게 작동하는지 보여주고 있다.(asm_io.inc)
첫 번째 인자는 단지 정수 라벨, 두 번째와 세번째 인자는 출력할 EBP의 범위를 설정하는 것이다.
만일 calc_sum이 포인터를 통해서 값을 전달하지 않고
return 시키기 위해서는 아래와 같이 코드를 바꾸어야 한다.
main6.c
#include<stdio.h>
/* 어셈블리 루틴의 원형 */
void calc_sum(int,int *)__attribute__((cdecl));
int main(void){
int n,sum;
printf("Sum integers up to:");
scanf("%d", &n);
sum=calc_sum(n);
printf("Sum is %d\n",sum);
return 0;
}
sub6.asm
;서브루틴 _calc_sum
;1부터 n까지 정수들의 합을 구한다.
; 인자:
; n -어디까지 합할 지 저장([ebp+8]에 위치)
; 리턴값:
; 합한 값
;의사 C 코드:
;void calc_sum(int n){
; int i,sum=0;
; for(i=1;i<=n;i++)
; sum+=i;
; return sum;
;}
segment .text
global _calc_sum
;
; local variable:
; sum at [ebp-4]
_calc_sum:
enter 4,0
mov dword [ebp-4],0
mov ecx,1
for_loop:
cmp ecx,[ebp+8]
jnle end_for
add [ebp-4],ecx
inc ecx
jmp short for_loop
end_for:
mov eax,[ebp-4] ;eax=sum
leave
ret
return 할 값이 int 이므로 EAX에 값을 저장한다.