我对汇编仍然相当陌生,在我想要解决的问题中,我很难理解最后一点汇编(找到代码末尾的esp值与保存的返回地址的位置之间的差异(。据我了解,前 5 行是函数"序幕",因为它设置了基本指针和堆栈指针,然后偏离(减去?(值 0xf8(248(,在新堆栈的一部分之间制作任何东西并将一些寄存器推送到它上面。但是,我真的不明白之后会发生什么。我知道它将堆栈指针设置为不同的值,但不明白堆栈指针如何在不破坏程序本身的情况下像这样移动。很抱歉语法或技术问题,但我只是高中三年级,没有 comp sci 的背景,很难解决这个问题。
foo:
pushl %ebp
mov %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
sub $0xf8, %esp
movl $0x1, (%esp)
movl $0x2, 0x4(%esp)
movl $0x3, 0x8(%esp)
movl $0x4, 0xc(%esp)
问题是你让自己受到AT&T语法的可憎之物的影响。
它将英特尔汇编代码硬塞进用于PDP(1959年首次制造的处理器(的格式中。
在理智的语法中,本节如下所示:
foo:
push ebp
mov ebp,esp //set up a stack frame
push edi //save some registers on the stack
push esi
push ebx
sub esp, 0xf8 //push down the stack pointer to make space
//for local variables
mov dword ptr [esp],1 //local int1 = 1
mov dword ptr [esp+4],2 //local int2 = 2
mov dword ptr [esp+8],3 //local int3 = 3
mov dword ptr [esp+12],4 //local int4 = 4
如果您被迫使用 GAS,您可以使用
.intel_syntax noprefix
作为第一个伪指令。
我有一个小小的疑问。问题是要找到代码末尾的esp值与保存的退货地址的位置之间的差异。我是这样想的:
假设x
为退货地址 (ebp(
mov %esp,%ebp // basically x=esp=ebp
pushl %edi //push statement so x+4 (since stack grows towards higher memory address)
pushl %esi // now x+4+4
pushl %ebx //x+4+4+4
sub $0xf8, %esp //x+4+4+4+(0xf8-x)
代码末尾的 esp 值:x+4+4+4+(0xf8-x)
我们假设保存的退货地址的位置为 x
现在这个答案应该是260吧?为什么我们还必须考虑第一次推送(push %ebp
(?