C fonksiyonunun montaj kodunu anlamaya çalışıyorum. Neden andl -16
ana bilgisayarda yapıldığını anlayamadım. Yerel değişkenler için yer ayırmak için mi? Eğer öyleyse, ana için subl 32
neden yapılır.c fonksiyonunun montaj kodu
Ben func1
sökülmesi anlayamadık. Okunduğunda yığın, 8086 işlemcilerinin yüksek sipariş adresinden düşük sipariş adresine büyür. Öyleyse neden ebp'nin pozitif tarafındaki erişim (parametreler ofset) ve neden ebp'nin negatif tarafında olmasın. Func1 içindeki yerel değişkenler 3 + dönüş adresi + kaydedilmiş kayıtlardır - Yani 20 olmalı, ama neden 24? (subl $24,esp
)
#include<stdio.h>
int add(int a, int b){
int res = 0;
res = a + b;
return res;
}
int func1(int a){
int s1,s2,s3;
s1 = add(a,a);
s2 = add(s1,a);
s3 = add(s1,s2);
return s3;
}
int main(){
int a,b;
a = 1;b = 2;
b = func1(a);
printf("\n a : %d b : %d \n",a,b);
return 0;
}
montaj kodu: Ben C kaynağıyla interlisting verecektir objdump -S
çıkışında da böyle çalışan öneririm
.file "sample.c"
.text
.globl add
.type add, @function
add:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $0, -4(%ebp)
movl 12(%ebp), %eax
movl 8(%ebp), %edx
leal (%edx,%eax), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
ret
.size add, .-add
.globl func1
.type func1, @function
func1:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl 8(%ebp), %eax
movl %eax, 4(%esp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call add
movl %eax, -4(%ebp)
movl 8(%ebp), %eax
movl %eax, 4(%esp)
movl -4(%ebp), %eax
movl %eax, (%esp)
call add
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl -4(%ebp), %eax
movl %eax, (%esp)
call add
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
leave
ret
.size func1, .-func1
.section .rodata
.LC0:
.string "\n a : %d b : %d \n"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl $1, 28(%esp)
movl $2, 24(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call func1
movl %eax, 24(%esp)
movl $.LC0, %eax
movl 24(%esp), %edx
movl %edx, 8(%esp)
movl 28(%esp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call printf
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
.section .note.GNU-stack,"",@progbits
GCC manuel Bu alıntı faydalı olabilir: -mpreferred-yığın sınır = num: a 2 hizalanmış istif sınır tutmak için girişimi num yükseltilmiştir bayt sınırı. -mpreferred-stack-border belirtilmemişse, varsayılan 4'dür (16 bayt veya 128 bit). – teppic
8 bayt hizalamayı hızlandırdığınız için teşekkür ederiz. Benim şüphem eklenti -> 1 (yerel değişken) + dönüş adresi => 2 * 8 = 16 doğrudur. Fakat func1 -> 3 (yerel değişkenler) + dönüş adresi => 4 * 8 = 32 orada olmalıdır. neden 24'tür? neden ana alt 32'de temel işaretçi için yapılır. Yapılan hesaplamalarla biraz kafam karıştı. – Angus
@Angus: 'func1' boyutunun hesaplanmasında, neden 8 ile çarpıyorsunuz? Bu 32-bit mimaride, '' '' func1'' içindeki '' '' 'nesneleri ve adresleri dört bayttır. 'func1', s1 için dört bayt, s2 için dört bayt, s3 için dört bayt,' add''e iki baytlık iki parametre, ve dört tane daha bayt hizalama için kullanır. Bu 24 bayt. –