我有一个问题:如果堆栈之间共享通用寄存器(GPR)(我认为它们是),那么传递堆栈空间地址的唯一方法是使用GPR吗?
任何建议都将非常感谢。提前致谢。
segment .data
prompt db "Enter an integer number (0 to quit): ",0
segment .text
main:
enter 0,0
pusha
mov eax, prompt
call print_string
call print_nl
call read_int
mov dword [ebp+8], eax
dump_stack 1,2,4
call calc_sum
mov eax, [ebp+12]
call print_int
call print_nl
popa
mov eax, 0 ; return value
leave ; deallocate stack frame
ret
; sump [ebp+12] > int ptr
; n [ebp+8] > current number
; return address [ebp+4]
; ebp [ebp]
; sum [ebp-4]
; i [ebp-8]
global calc_sum
calc_sum:
enter 4,0 ; stack space allocated for sum
push ebx ; very important!
mov dword [ebp-4], 0 ; sum = 0
dump_stack 1,2,4 ; print the content of stack from ebp-8 to ebp+16
mov ecx, 1 ; ecx psuedo code i
for_loop:
cmp ecx, [ebp+8] ;cmp i and n
jnle end_for ; if i<= n else , exit
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
Enter an integer number (0 to quit):
10
Stack Dump # 1
EBP = BF86F3D8 ESP = BF86F3B8
+16 BF86F3E8 BF86F47C
+12 BF86F3E4 BF86F474
+8 BF86F3E0 0000000A
+4 BF86F3DC B76134E3
+0 BF86F3D8 00000000
-4 BF86F3D4 00000001
-8 BF86F3D0 BF86F474
Stack Dump # 1
EBP = BF86F3B0 ESP = BF86F3A8
+16 BF86F3C0 BF86F3D8
+12 BF86F3BC 00000000
+8 BF86F3B8 00000000
+4 BF86F3B4 080484AC
+0 BF86F3B0 BF86F3D8
-4 BF86F3AC 00000000
-8 BF86F3A8 B77A0FF4
Segmentation fault (core dumped)
dump_stack 1,2,4(-8~ + 16)
显示堆栈帧。我附上了执行程序的结果。我得到了这个结果,以防您不理解dump_stack
。
顺便说一句:我使用NASM
和gcc
作为学习目的的工具。
答案 0 :(得分:3)
首先,只有一个堆栈,所以你不能在堆栈之间共享任何东西,因为只有一个(实际上它是一个简化,但只要你是初学者就可以这样考虑)。
将堆栈视为数据的某些空间。每个push
call
或ret
只会读取/写入此地点。像eax
这样的注册不会受到影响(直到你调用pop eax
:)。
所以每次写入到push
或call
的堆栈都会减少esp
寄存器(这就是为什么我们说它会逐渐减少),每次使用pop
或{{ 1}}增加它。 ret
始终指向堆栈顶部。您可以esp
通过esp
来读取或修改mov
来自另一个注册表,但您必须知道自己在做什么。