0

我正在尝试学习 x86 AT&T 语法,但我总体上有点困惑。我知道堆栈上有帧,当调用时,该函数中发生的第一件事是某种帧更新,然后获取参数。所以,如果我在我的主要代码区域的寄存器 eax 中有某种值,比如 5 并调用函数,我仍然可以访问 eax 中的值 5 对吗?或者为了把它作为一个参数,我必须做这样的事情。我在其他地方看到您在调用函数之前将参数推送到堆栈,这是真的吗?我想某些东西必须位于 8(ebp) 才能将它移入 eax,但是在我用 movl 将某些东西移入之前,eax 的值是多少?是5吗?我知道这是很多问题,我 我只是在调用函数并返回某些东西时感到困惑。任何帮助将不胜感激。我敢肯定这对于一些装配大师来说就像小菜一碟!

Function:
pushl %ebp
movl %esp, %ebp

movl 8(ebp), eax
4

1 回答 1

1

这个页面应该基本上把它包起来。

使用cdecl你会喜欢

; I'm not comfortable with AT&T syntax, but it's not relevant here

; void *processData(void *firstParam, void *secondParam)
proc processData
    push ebp
    mov ebp,esp

    mov eax,[dword ptr ss:ebp + 8]    ; firstParam
    mov edx,[dword ptr ss:ebp + 12]   ; secondParam

    ; do something with the data and put the result into EAX

    mov esp,ebp
    pop ebp
    ret
endp processData

你调用它就像

lea eax,[ds:bufferOfSecondParam]
push eax
lea eax,[ds:bufferOfFirstParam]
push eax
call processData
add esp,8

; Here you can do with the return value anything you want

首先,您需要决定要使用的调用约定。例如,Win32 使用一个名为stdcall的cdecl变体,其中被调用者负责清理堆栈——这实现起来不太方便,并且不允许使用可变参数。

[SS:EBP + 8]指向第一个参数,因为

  • 参数从右到左传递到堆栈([SS:EBP + 12]指向第二个参数)
  • DWORDS 是 4 个字节
  • [SS:EBP + 0]指向在创建堆栈帧时保存的上一个EBP
  • [SS:EBP + 4]指向ret时读入EIP的返回地址
于 2013-04-13T15:16:05.773 回答