汇编语言 - 子程序

时间:2016-05-29 08:42:39

标签: assembly x86 stack nasm

我有一个问题:如果堆栈之间共享通用寄存器(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

顺便说一句:我使用NASMgcc作为学习目的的工具。

1 个答案:

答案 0 :(得分:3)

首先,只有一个堆栈,所以你不能在堆栈之间共享任何东西,因为只有一个(实际上它是一个简化,但只要你是初学者就可以这样考虑)。

将堆栈视为数据的某些空间。每个push callret只会读取/写入此地点。像eax这样的注册不会受到影响(直到你调用pop eax :)。

所以每次写入到pushcall的堆栈都会减少esp寄存器(这就是为什么我们说它会逐渐减少),每次使用pop或{{ 1}}增加它。 ret始终指向堆栈顶部。您可以esp通过esp来读取或修改mov来自另一个注册表,但您必须知道自己在做什么。