jay
jay

Reputation: 55

Assembly Language - Sub program

I have a question: if General Purpose Registers(GPRs) are shared between stacks (I think they are), would it be true that the only way to pass the address of stack space is to use GPRs?

Any advice would be very appreciated. Thanks in advance.

      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)

shows a stack frame. I attached the result of the execution program. I got this result just in case you don't understand dump_stack.

BTW: I use NASM and gcc as tools for learning purposes.

Upvotes: 1

Views: 998

Answers (1)

Michał Walenciak
Michał Walenciak

Reputation: 4369

First of all, there is only one stack, so You cannot share anything between stacks as there is only one (actually it is a simplification, but you can think about it this way as long as you are beginner).

Think of stack like of some space for your data. Every push call or ret just reads/writes to this place. Registers like eax are not affected (until you call pop eax :) ).

So every write to stack with push or call decreases esp register (this is why we say it grows down), and every read with pop or ret increases it. esp always points to the top of the stack. You can read or modify esp by moving it to/from another register but you must know what you are doing.

Upvotes: 3

Related Questions