了解汇编语言
我想了解与上面的C代码有关的汇编代码。我不确定我是否在正确的轨道上,所以也许有人可以帮助我更好地理解这一点。了解汇编语言
int silly(int n, int *p)
{
int val, val2;
if (n > 0)
val2 = silly(n << 1, &val);
else
val = val2 = 0;
*p = val + val2 + n;
return val + val2;
}
我们得到以下的机器代码:
silly:
pushl %ebp // Here I am making space for the function on the stack
movl %esp,%ebp // Moving the stack pointer where the base pointer is
subl $20,%esp // Subtracting 20 from the stack pointer to allocate more space
pushl %ebx // Pushing the %ebx register on top of the stack
movl 8(%ebp),%ebx // Getting the first argument(which is n) and store it in register %ebx
testl %ebx,%ebx // The first if-statement which compares if n > 0
jle .L3 // Jump if less or equal - meaning if n < 0 then jump to .L3
addl $-8,%esp // Add -8 to %esp to allocate more space
leal -4(%ebp),%eax // Storing the first local variable (which is val) in %eax
pushl %eax // Pushing the register %eax on top of the stack
leal (%ebx,%ebx),%eax // n + n and stores it as 2n in %eax
pushl %eax // Pushing register %eax on top of the stack (Which I find strange
// considering that I've just pushed %eax onto the stack above
call silly // Call the function silly
jmp .L4 // Jump to .L4 (Unconditionally)
.p2align 4,,7 // Don't know what this means.
.L3: // .L3 is the else-statement
xorl %eax,%eax // Basically making %eax = 0
movl %eax,-4(%ebp) // Moving the value in %eax which is 0 to the first local variable
// meaning val = 0
.L4: // .L4 is the section after the else-statement
movl -4(%ebp),%edx // Getting val again and now storing it in %edx
addl %eax,%edx // Adding what is in %eax (which is 0) to %edx
movl 12(%ebp),%eax // Getting the second parameter (*p) and storing it in %eax
addl %edx,%ebx // Adding value from %edx to %ebx - meaning val + n
movl %ebx,(%eax) // Moving what is in %ebx and storing it in memory location of %eax
movl -24(%ebp),%ebx // Getting the second local variable (val2) and moving it to %ebx
movl %edx,%eax // Move val to %eax - and the return value will be in %eax
movl %ebp,%esp
popl %ebp
ret
我想换我解决这个头,我刚开始想组装等主题的指针将是非常好的。我有几个我需要问这个汇编代码,可以帮助栈我的理解的问题:
(a)是存储在堆栈上的变量val?
(b)如果是这样,在什么字节oset(相对于%ebp)被存储?
(c)为什么需要将它存储在堆栈中?(a)变量val2是否存储在堆栈中?
(b)如果是这样,在什么字节oset(相对于%ebp)被存储?
(c)为什么需要将它存储在堆栈中? (a)什么(如果有的话)存储在-24(%ebp)?
(b)如果有东西存储在那里,为什么需要存储它? (a)什么(如果有的话)存储在-8(%ebp)?(0127)
(b)如果有东西存储在那里,为什么需要存储它?
感谢提前:)
在回答您的问题之前。我没有评论代码在做什么,我评论了所有值都在寄存器或堆栈中的位置。
参数在堆栈上,返回值为%eax
。
寄存器%eax
,%ecx
和%edx
被保存。所有其他寄存器,包括%ebx
,%ebp
和%esp
,都被调用保存(%edi
和%esi
未使用)。
我的堆栈符号一次是4个字节,我使用;
作为ebp点的位置(如果已知)。
silly: ; eax: ?, ebx: ebx0, edx: ?, stack: [eip0, n, p]
pushl %ebp ; eax: ?, ebx: ebx0, edx: ?, stack: [ebp0, eip0, n, p]
movl %esp,%ebp ; eax: ?, ebx: ebx0, edx: ?, stack: [; ebp0, eip0, n, p]
subl $20,%esp ; eax: ?, ebx: ebx0, edx: ?, stack: [?, ?, ?, ?, ?; ebp0, eip0, n, p]
pushl %ebx ; eax: ?, ebx: ebx0, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p]
movl 8(%ebp),%ebx ; eax: ?, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p]
testl %ebx,%ebx ; set flags from n
jle .L3 ; if flags indicates <= 0, goto .L3, else fallthrough
; set up for calling the function
addl $-8,%esp ; eax: ?, ebx: n, edx: ?, stack: [?, ?, ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p]
leal -4(%ebp),%eax ; eax: &val, ebx: n, edx: ?, stack: [?, ?, ebx0, ?, ?, ?, ?, (stackeax); ebp0, eip0, n, p]
pushl %eax ; eax: &val, ebx: n, edx: ?, stack: [&val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p]
leal (%ebx,%ebx),%eax ; eax: 2*n, ebx: n, edx: ?, stack: [&val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p]
pushl %eax ; eax: 2*n, ebx: n, edx: ?, stack: [2*n, &val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p]
call silly ; pushes eip; args: (2*n, &val); val will be initialized on return
jmp .L4 ;
;
.p2align 4,,7 ; request alignment (there should be one before `silly:` too)
.L3: ;
xorl %eax,%eax ; eax: val=0, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p]
movl %eax,-4(%ebp) ; eax: val=0, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p]
;
.L4: ; eax: val2=φ(function result, 0), ebx: n, edx: ?, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p]
movl -4(%ebp),%edx ; eax: val2, ebx: n, edx: val, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p]
addl %eax,%edx ; eax: val2, ebx: n, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p]
movl 12(%ebp),%eax ; eax: p, ebx: n, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p]
addl %edx,%ebx ; eax: p, ebx: n+val+val2, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p]
movl %ebx,(%eax) ; *p = n+val+val2
movl -24(%ebp),%ebx ; eax: p, ebx: ebx0, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p]
movl %edx,%eax ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p]
movl %ebp,%esp ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [; ebp0, eip0, n, p]
popl %ebp ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [eip0, n, p]
ret ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [n, p]
STOP。
返回并重新读取代码。如果你不自己想出答案,你只会伤害自己。我写的评论应该很容易。
但无论如何...
- 一个。
val
通常位于堆栈上,位于-4(%ebp)
。唯一不是的是xorl %eax,%eax
b。它存储在-4(%ebp)
,如线路leal -4(%ebp),%eax
,movl %eax,-4(%ebp)
和movl -4(%ebp),%edx
所示。此外,前一帧的val
是*p
c。val
必须位于堆栈上,以便其地址可以被接受并传递给递归调用。 - a。
val2
永远不会存储在堆栈中,尽管很可能其中一些?
是为其保留的空间。 b。它存储在regixtereax
中.L4
,它在phi函数的第一个分支上是递归调用的返回值,在第二个分支上是值0
,它也存储在val
中。
c。val2
永远不需要在堆栈上,因为它的地址没有被占用,它在递归调用之前不存在,所以它不需要被保存,并且没有足够的寄存器在使用,因此不需要溢出。 - a。
-24(%ebp)
是保存的值%ebx
,从行pushl %ebx
b。%ebx
是一个被调用者保存的寄存器,所以它的值必须保留。 - a。不,没有什么。 b。如果有必要泄漏,最有可能是
val2
。我最好的猜测是其他三个?
被保留用于递归调用呼叫者保存的未使用寄存器:%eax
,%ecx
和%edx
。
你已经问了很多。
我会用这部分开始...
.p2align 4,,7 // Don't know what this means.
明白了;模糊,不是吗!
程序员(在你的情况下看起来像编译器)想要L3:
的指令位于所谓的“16字节边界”。
你可以阅读关于那东西HERE的细节。如果这没有意义,请回到这里,我会解释一些。
你的问题到底是什么? – o11c 2014-10-09 21:36:10
我刚刚更新了这个问题。对不起:) – drleifz 2014-10-09 21:41:38
注意:'val2'是未初始化的。有时。有时候'val'也是如此。 – wildplasser 2014-10-09 22:34:45