所以,我得到了一个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
如果我需要清除任何问题,请问:)
答案 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非常好看。