我一直在努力解决我在大学实验室收到的IA32汇编语言问题。我不能完全理解如何去做,并想知道这里是否有人可以帮助我。
问题是:在执行期间从以下几点绘制运行时堆栈,从传递给fact_do的参数开始,到堆栈顶部结束。在每种情况下标记每个4字节的存储位置并在已知时指示内容。显示%ebp和%esp指向的位置。
我无法完全绘制堆栈跟踪的观点是:“就在事实中的离开指令之前(离开相当于movl%ebp,%esp后跟popl%ebp)。”
我认为所期望的是:
_____________
| | <- %ebp
| . |
| . |
| . |
|_____________|
|_5___________|
|_Rtn_Address_| <- %esp
以下是要跟踪的代码:
.file "fact.c"
.section .rodata
.LC0:
.string "%d! = %d\n" #string is initialized
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl $5, (%esp) #(%esp) <- 5 [(%esp) = n]
call fact_do
movl $.LC0, %edx #set up print statement
movl %eax, 8(%esp) #8(%esp) <- %eax [%eax = 120, return value of fact_do]
movl $5, 4(%esp) #4(%esp) <- 5
movl %edx, (%esp) #print statement location
call printf #print output
movl $0, %eax #%eax <- 0
leave
ret
.size main, .-main
.globl fact_do
.type fact_do, @function
fact_do:
pushl %ebp #push %ebp onto stack
movl %esp, %ebp #%ebp <- %esp
subl $16, %esp #%esp <- %esp - 16
movl $1, -4(%ebp) #-4(%ebp) <- 1 [-4(%ebp) = result]
.L4:
movl -4(%ebp), %eax #%eax <- -4(%ebp)
imull 8(%ebp), %eax #%eax <- %eax * 8(%ebp) [8(%ebp) = n]
movl %eax, -4(%ebp) #-4(%ebp) <- %eax [result <- result*n]
subl $1, 8(%ebp) #8(%ebp)-- [n--]
cmpl $1, 8(%ebp) #8(%ebp) > 1 ? [n > 1]
jg .L4 #Repeat loop if 8(%ebp) > 1
movl -4(%ebp), %eax #%eax <- -4(%ebp) [%eax <- 120, result]
leave
ret
.size fact_do, .-fact_do
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-4)"
.section .note.GNU-stack,"",@progbits
Optimized:
.file "fact.c"
.text
.globl fact_do
.type fact_do, @function
fact_do:
pushl %ebp #push %ebp (for return)
movl %esp, %ebp #%ebp <- %esp
movl 8(%ebp), %edx #%edx <- 8(%ebp) [%edx = n]
movl $1, %eax #%eax <- 1 [%eax = result]
.L2:
imull %edx, %eax #%eax <- %edx * %eax [result <- n * result]
subl $1, %edx #%edx-- [n--]
cmpl $1, %edx #%edx > 1 ? [n > 1]
jg .L2 #repeat if %edx > 1 [if n > 1]
popl %ebp #%ebp <- top value on stack (for return)
ret
.size fact_do, .-fact_do
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d! = %d\n" #prepare string
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl $5, (%esp) #%esp <- 5
call fact_do
movl %eax, 8(%esp) #8(%esp) <- %eax [%eax = result]
movl $5, 4(%esp) #4(%esp) <- 5
movl $.LC0, (%esp) #set up print statement
call printf #print
movl $0, %eax #%eax <- 0
leave
ret
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-4)"
.section .note.GNU-stack,"",@progbits
在C中转换为以下内容:
#include <stdio.h>
int fact_do(int n);
int main(){
printf("%d! = %d\n", 5, fact_do(5));
return 0;
}
int fact_do(int n){
int result = 1;
do {
result *= n;
n = n-1;
} while (n > 1);
return result;
}