2016-05-29 3 views
1

一般的な目的のレジスタ(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を学習目的のツールとして使用しています。

答えて

3

まず第一に、スタックが1つしかないので、スタックの間に何かを共有することはできません(実際は単純化されていますが、初心者であればこのように考えることができます)。

あなたのデータにはある程度のスペースがあります。すべてpushcallまたはretこの場所への読み書きのみ。 eaxのようなレジスタは影響を受けません(pop eaxと呼ぶまで)。

ので、すべてはpushまたはcall(我々はそれがダウンして成長すると言う理由です)espレジスタを低下させ、すべてのはpopまたはretそれを増大させて読むとスタックして書きます。 espは常にスタックの一番上を指します。 espmovで読んだり変更したりすることはできますが、他の登録簿へ/からあなたはあなたがしていることを知っている必要があります。