如何在 MASM 中使用 pop 和 ret
How to use pop and ret in MASM
我最近开始使用 MASM 语言学习 x86 汇编。
我正在使用 Isreal Gbati 的 Udemy 课程 "x86 Assembly Language From Ground Up" 来学习。
下面的代码来自课程中的一课,(这不是我想出的代码)。该函数由 C 程序中的 main 调用。在这里:
#include <stdio.h>
#include <stdlib.h>
extern int AdderASM(int a, int b, int c);
int main(void)
{
int a = 17;
int b = 11;
int c = 14;
int sum = AdderASM(a, b, c);
printf("A = %d\n", a);
printf("B = %d\n", b);
printf("C = %d\n", c);
printf("SUM FROM ASSEMBLY FUNCTION = %d\n", sum);
return 0;
}
这里是程序集:
.386
.model flat, c
.code
AdderASM PROC
PUSH EBP
MOV EBP, ESP
MOV EAX, [EBP+8]
MOV ECX, [EBP+12]
MOV EDX, [EBP+16]
ADD EAX, ECX
ADD EAX, EDX
POP EBP
RET
AdderASM ENDP
END
我不明白以下内容:
当我们使用 pop
时,据我所知有点像在 C 中使用 free()
。如果我错了请纠正我
那么为什么我们只在 EBP 寄存器上使用 pop?我们不应该也弹出 ECX 和 EDX 寄存器吗?
我知道在 C 函数中,由 malloc()
分配内存的指针需要在函数结束前释放。使用的寄存器都是通用的 32 位寄存器,但 EBP 作为堆栈帧指针有特殊用途。这就是它需要被释放的原因吗?
此外,我知道在过程结束时使用了 ret
,但是我们怎么知道这个函数返回了一个值呢?
为了更好地解释我的问题,这里是用 C 编写的相同函数:
int AdderClang(int a, int b, int c)
{
return a + b + c;
}
如果我只输入 return;
而不是 return a + b + c;
我不知道会发生什么,但这不是预期的结果。我们还可以告诉我们这个 C 函数 returns 是一个 int,因为它在声明中告诉我们。
所有这些都可能在课程的后面解释,我相信我的问题的答案很简单。但是,我正在尝试慢慢来以确保我了解自己在做什么。是的,我知道 Assembly 不是 C,所以像我这样比较这两种语言可能不是正确的方法,但我正在学习 Assembly 以更好地理解 C 中的内存管理内容。
谢谢大家的宝贵时间!
When we use pop
, from what I understand is kind of like using free()
in C.
事实并非如此。 push x
将 x
复制到栈顶,并移动栈指针,使新的栈顶低于压入的值(请记住,在 x86 上,栈在内存中向下增长)。 pop x
做相反的事情:将堆栈的顶部复制到 x
,然后移动堆栈指针,使新的顶部位于弹出值之上(即从堆栈中删除该值)。
实际上,pseudo-C 等价物是这样的:
void push(int x) {
--esp;
*esp = x;
}
void pop(int *x) {
*x = *esp;
++esp;
}
因此,pop ebp
并不意味着 "clean the ebp
register",而是 "pop a value from the stack and store it in the ebp
register." 因为我们之前推送了 ebp
,所以这只是将其还原为结束我们函数的一部分.
Also, I understand that ret
is used at the end of the procedure, but how do we know that this function is returning a value at all?
您可以说在汇编程序世界中,每个函数都是 returning 一个值。调用约定指定如何 returned 值。在 x86 上,return 值存储在 eax
寄存器中。所以 ret
跳转到调用函数的地方,当时 eax
中的任何内容都是调用者获得的 return 值。这就是该函数在 eax
中计算总和的原因,因此它就在调用者期望的位置。
同样,在 pseudo-C 中,您可以想象一个普通的 C return
语句是这样实现的:
void return(int x) {
eax = x;
ret;
}
我最近开始使用 MASM 语言学习 x86 汇编。
我正在使用 Isreal Gbati 的 Udemy 课程 "x86 Assembly Language From Ground Up" 来学习。
下面的代码来自课程中的一课,(这不是我想出的代码)。该函数由 C 程序中的 main 调用。在这里:
#include <stdio.h>
#include <stdlib.h>
extern int AdderASM(int a, int b, int c);
int main(void)
{
int a = 17;
int b = 11;
int c = 14;
int sum = AdderASM(a, b, c);
printf("A = %d\n", a);
printf("B = %d\n", b);
printf("C = %d\n", c);
printf("SUM FROM ASSEMBLY FUNCTION = %d\n", sum);
return 0;
}
这里是程序集:
.386
.model flat, c
.code
AdderASM PROC
PUSH EBP
MOV EBP, ESP
MOV EAX, [EBP+8]
MOV ECX, [EBP+12]
MOV EDX, [EBP+16]
ADD EAX, ECX
ADD EAX, EDX
POP EBP
RET
AdderASM ENDP
END
我不明白以下内容:
当我们使用 pop
时,据我所知有点像在 C 中使用 free()
。如果我错了请纠正我
那么为什么我们只在 EBP 寄存器上使用 pop?我们不应该也弹出 ECX 和 EDX 寄存器吗?
我知道在 C 函数中,由 malloc()
分配内存的指针需要在函数结束前释放。使用的寄存器都是通用的 32 位寄存器,但 EBP 作为堆栈帧指针有特殊用途。这就是它需要被释放的原因吗?
此外,我知道在过程结束时使用了 ret
,但是我们怎么知道这个函数返回了一个值呢?
为了更好地解释我的问题,这里是用 C 编写的相同函数:
int AdderClang(int a, int b, int c)
{
return a + b + c;
}
如果我只输入 return;
而不是 return a + b + c;
我不知道会发生什么,但这不是预期的结果。我们还可以告诉我们这个 C 函数 returns 是一个 int,因为它在声明中告诉我们。
所有这些都可能在课程的后面解释,我相信我的问题的答案很简单。但是,我正在尝试慢慢来以确保我了解自己在做什么。是的,我知道 Assembly 不是 C,所以像我这样比较这两种语言可能不是正确的方法,但我正在学习 Assembly 以更好地理解 C 中的内存管理内容。
谢谢大家的宝贵时间!
When we use
pop
, from what I understand is kind of like usingfree()
in C.
事实并非如此。 push x
将 x
复制到栈顶,并移动栈指针,使新的栈顶低于压入的值(请记住,在 x86 上,栈在内存中向下增长)。 pop x
做相反的事情:将堆栈的顶部复制到 x
,然后移动堆栈指针,使新的顶部位于弹出值之上(即从堆栈中删除该值)。
实际上,pseudo-C 等价物是这样的:
void push(int x) {
--esp;
*esp = x;
}
void pop(int *x) {
*x = *esp;
++esp;
}
因此,pop ebp
并不意味着 "clean the ebp
register",而是 "pop a value from the stack and store it in the ebp
register." 因为我们之前推送了 ebp
,所以这只是将其还原为结束我们函数的一部分.
Also, I understand that
ret
is used at the end of the procedure, but how do we know that this function is returning a value at all?
您可以说在汇编程序世界中,每个函数都是 returning 一个值。调用约定指定如何 returned 值。在 x86 上,return 值存储在 eax
寄存器中。所以 ret
跳转到调用函数的地方,当时 eax
中的任何内容都是调用者获得的 return 值。这就是该函数在 eax
中计算总和的原因,因此它就在调用者期望的位置。
同样,在 pseudo-C 中,您可以想象一个普通的 C return
语句是这样实现的:
void return(int x) {
eax = x;
ret;
}