需要帮助解读Ada 95程序中的GNU程序集

时间:2012-02-02 22:18:39

标签: assembly x86 gnu ada

所以,我得到了一个Ada 95程序,以及编译器吐出的汇编代码。我无法理解编译器/运行时环境如何实现非本地访问。任何熟悉GNU程序集的人都可以帮助我吗?我在Intel汇编和Ada 95中编写了很多代码,并且理解了GNU汇编的基本语法。

这是Ada计划:

PROCEDURE Main_2 IS
   X : Integer := 1;
   PROCEDURE Bigsub IS
      A : Integer := 2;
            B : Integer := 3; 
            C : Integer := 4;
      PROCEDURE Sub1 IS
         A : Integer := 5; 
                  D : Integer := 6;
      BEGIN -- of Sub1
         A := B + C;  -- point 1
      END; -- of Sub1
      PROCEDURE Sub2 (X : Integer) IS
         B : Integer := 7;
                  E : Integer := 8;
         PROCEDURE Sub3 IS
            C : Integer := 9;
                        E : Integer := 10;
         BEGIN -- of Sub3
            Sub1;
            E := B + A;  -- point 2
         END; -- of Sub3
      BEGIN -- of Sub2
         Sub3;
         A := C + E; -- point 3
      END; -- Sub2
   BEGIN -- of Bigsub
      Sub2(11);
   END; -- of Bigsub
BEGIN -- of Main_2
   Bigsub;
END; -- of Main_2

这是装配程序:

    .file   "main_2.adb"
    .text
    .align 2
    .def    _main_2__bigsub__sub1.2238; .scl    3;  .type   32; .endef
_main_2__bigsub__sub1.2238:                                 ;;SUB_1 RIGHT HERE
LFB3:
    pushl   %ebp                                            ;;Push current frame pointer onto stack
LCFI0:
    movl    %esp, %ebp                                      ;;assign the current stack point to the current frame pointer
LCFI1:
    subl    $40, %esp                                       ;;Subtract 40 from the stack pointer, making room for 10 longs of data(frame is 10 longs long)
LCFI2:
    movl    %ecx, -28(%ebp)                                 ;;Whatever is in ECX is moved to 28 bytes ahead of the frame pointer
    movl    $5, -12(%ebp)                                   ;;Storing A in Sub1 // A = 5
    movl    $6, -16(%ebp)                                   ;;Storing B in Sub1 // B = 6
    movl    $7, -12(%ebp)                                   ;;Storing A in Sub1 // A = 3 + 4
    leave                                                   ;;Assign the current frame pointer to the current stack pointer. Pop the old frame pointer
LCFI3:
    ret                                                     ;;Returning from SUB_1. Pops the return address off and jumps to it.
LFE3:
    .align 2
    .def    _main_2__bigsub.2231;   .scl    3;  .type   32; .endef
_main_2__bigsub.2231:                                       ;;BIG SUB RIGHT HERE
LFB2:
    pushl   %ebp                                            ;;Push current frame pointer onto stack
LCFI4:
    movl    %esp, %ebp                                      ;;Assign the current stack point to the current frame pointer
LCFI5:
    subl    $56, %esp                                       ;;Subtract 56 from the stack pointer, making room for 14 longs of data(frame is 14 longs long)
LCFI6:
    movl    %ecx, -28(%ebp)                                 ;;Whatever is in the ecx is moved to 28 bytes ahead of the frame pointer
    movl    $2, -20(%ebp)                                   ;;Storing A in BIGSUB // A = 2
    movl    $3, -12(%ebp)                                   ;;Storing B in BIGSUB
    movl    $4, -16(%ebp)                                   ;;Storing C in BIGSUB
    leal    -20(%ebp), %eax                                 ;;Saves the address 20 bytes deep into the frame, and loads it into the EAX
    movl    $11, (%esp)                                     ;;Putting x on top of the stack for sub2
    movl    %eax, %ecx                                      ;;Stores the address 20 bytes deep into the stack frame in the ECX
    call    _main_2__bigsub__sub2.2241                      ;;calling sub2 from bigsub
    leave                                                   ;;Assign the current frame pointer to the current stack pointer. Pop the old frame pointer
LCFI7:
    ret                                                     ;;Returning from BIGSUB. Pops the return address off and jumps to it.
LFE2:
    .align 2
.globl __ada_main_2                                         ;;MAIN_2 RIGHT HERE
    .def    __ada_main_2;   .scl    2;  .type   32; .endef
__ada_main_2:
LFB1:
    pushl   %ebp                                            ;;Push current frame pointer onto the stack
LCFI8:
    movl    %esp, %ebp                                      ;;Assign the current stack pointer to the current frame pointer
LCFI9:
    subl    $24, %esp                                       ;;Subtract 24 from the stack pointer, making room for 6 longs of data(frame is 6 longs long)
LCFI10:
    movl    $1, -12(%ebp)                                   ;;Storing x in Main_2
    leal    -12(%ebp), %eax                                 ;;Saves the address 12 bytes deep into the frame, and loads it into the EAX
    movl    %eax, %ecx                                      ;;Stores the address 12 bytes deep into the stack frame in the ECX
    call    _main_2__bigsub.2231                            ;;calling bigsub from main_2
    leave                                                   ;;Assign the current frame pointer to the current stack pointer. Pop the old frame pointer
LCFI11:
    ret                                                     ;;Returning from MAIN_2. Pops the return address off and jumps to it.
LFE1:
    .align 2
    .def    _main_2__bigsub__sub2__sub3.2250;   .scl    3;  .type   32; .endef
_main_2__bigsub__sub2__sub3.2250:                           ;;SUB_3 RIGHT HERE
LFB5:
    pushl   %ebp                                            ;;Push current frame pointer onto the stack
LCFI12:
    movl    %esp, %ebp                                      ;;Assign the current stack pointer to the current frame pointer
LCFI13:
    pushl   %ebx                                            ;;push whatever is in the EBX onto the stack
LCFI14:
    subl    $36, %esp                                       ;;Subtract 36 from the stack pointer, making room for 9 longs of data(frame is 9 longs long)
LCFI15:
    movl    %ecx, %ebx                                      ;;Whatever is in the ecx is moved to the ebx for storage
    movl    %ecx, -28(%ebp)                                 ;;Whatever is in the ecx is moved to the address 28 deep into the frame
    movl    $9, -12(%ebp)                                   ;;Storing C in Sub3 // C = 9
    movl    $10, -16(%ebp)                                  ;;Storing E in Sub3 // E = 10
    movl    (%ebx), %eax                                    ;;The contents of the address in the EBX is moved to the EAX
    movl    %eax, %ecx                                      ;;The contents of the EAX is moved to the ECX
    call    _main_2__bigsub__sub1.2238                      ;;calling sub1 from sub3
    movl    (%ebx), %eax                                    ;;The contents of the address in the EBX is moved to the EAX
    movl    (%eax), %eax                                    ;;The contents of the address in the EAX is moved to the EAX
    addl    $7, %eax                                        ;;Adding 7 and 2, and storing it in the EAX
    movl    %eax, -16(%ebp)                                 ;;Move the contents of the EAX to the address 16 bytes deep into the current frame
    addl    $36, %esp                                       ;;add 36 back to the stack pointer, erasing what was the current frame
    popl    %ebx                                            ;;Pop whatever used to be in EBX back into EBX
LCFI16:
    popl    %ebp                                            ;;Pop the old frame pointer back into EBP
LCFI17:
    ret                                                     ;;Pop the return address off the stack and jump to it
LFE5:
    .align 2
    .def    _main_2__bigsub__sub2.2241; .scl    3;  .type   32; .endef
_main_2__bigsub__sub2.2241:                                 ;;SUB_2 RIGHT HERE
LFB4:
    pushl   %ebp                                            ;;Push the old frame pointer onto the stack
LCFI18:
    movl    %esp, %ebp                                      ;;Assign the current stack pointer to the current frame pointer
LCFI19:
    pushl   %ebx                                            ;;Push Whatever is in the EBX onto the stack
LCFI20:
    subl    $36, %esp                                       ;;Subtract 36 from the stack pointer, making room for 9 longs of data(frame is 9 longs long)
LCFI21:
    movl    %ecx, %ebx                                      ;;Move whatever is in the ECX to the EBX
    movl    %ecx, -28(%ebp)                                 ;;Whatever is in the ECX is assigned to the address 28 bytes deep into the current frame
    movl    %ebx, -20(%ebp)                                 ;;Assign the contents of EBX to 20 deep into the stack frame
    movl    $7, -12(%ebp)                                   ;;Storing B in Sub2 // B = 7
    movl    $8, -16(%ebp)                                   ;;Storing E in Sub2 // E = 8
    leal    -20(%ebp), %eax                                 ;;Saves the address 20 bytes deep into the frame, and loads it into the EAX
    movl    %eax, %ecx                                      ;;Assign the contents of the EAX to the ECX
    call    _main_2__bigsub__sub2__sub3.2250                ;;calling sub3 from sub2
    movl    $12, (%ebx)                                     ;;Assigning 12 to A in Sub2, A is the address held within the EBX
    addl    $36, %esp                                       ;;Add 36 back into the stack pointer, erasing what was the current frame
    popl    %ebx                                            ;;Pop whatever used to be in the EBX back into the EBX
LCFI22:
    popl    %ebp                                            ;;Pop the old frame pointer back into EBP
LCFI23:
    ret                                                     ;;Pop the return address off the stack and jump to it

如果我需要清除任何问题,请问:)

3 个答案:

答案 0 :(得分:2)

看起来外部例程正在将对本地堆栈帧的引用传递给ECX中的被调用例程。但是请发一个较短的例子,因为这个很难遵循 - 源中执行的一些数学似乎是由编译器扩展的。

答案 1 :(得分:2)

关注ECX注册表。如果您注意到指令leal,则每次调用函数时,都会拉取并存储每个示波器参考帧的地址(用作这些本地的偏移量)。

这可能足以让Meehan给你信用

答案 2 :(得分:2)

- 不是答案 -

您可以使用END PROCEDURE_NAME;编码形式

来简化评论
  PROCEDURE Sub1 IS
     A : Integer := 5; 
              D : Integer := 6;
  BEGIN -- of Sub1
     A := B + C;  -- point 1
  END; -- of Sub1

变为:

  PROCEDURE Sub1 IS
     A : Integer := 5; 
              D : Integer := 6;
  BEGIN -- of Sub1
     A := B + C;  -- point 1
  END Sub1;

与“卷括号”语言相比,我觉得Ada非常好看。