Skip to content

4.3 机器级代码

字数
750 字
阅读时间
4 分钟

一、循环语句的机器级表示

1. loop指令

扩展:loopx 指令 --- 如:loopnz,loopz

  1. loopnz --- 当 ecx != 0 && ZF == 0 时,继续循环
  2. loopz --- 当 ecx != 0 && ZF == 1 时,继续循环
    1. ZF == 1 --> 运算结果为 0

二、过程调用(函数调用)的机器级表示

  1. 函数的栈帧(Stack Frame):保存函数大括号内(C语言)定义的局部变量、保存函数调用相关信息

1. 如何访问栈帧?

TIP

在x86中,默认以4字节为栈的操作单位,包括push、pop等操作 栈底在高地址,栈顶在低地址,画栈的示意图时,需要从上往下分别画栈底和栈顶;故若是要进栈,则需要将栈顶寄存器esp-4(此处的4指的是4字节)

方法一:

C
push dog // 先让esp减4,再将dog压入栈
pop horse // 先让栈顶元素出栈,将该出栈元素写入horse地址,再让esp加4

// 注:dog 可以是立即数、寄存器、主存地址
// 注:horse 可以是寄存器、主存地址
// 在Intel格式汇编中,若是主存地址,记得加左右括号 "[" "]"

方法二: mov 指令,结合esp、ebp指针访问栈帧数据 注:可以用减法/加法指令,即:sub/add指令修改栈顶指针esp的值,以模仿push、pop的进出栈操作

TIP

ebp:指向当前栈帧的“底部esp:指向当前栈帧的“顶部

2. 一个函数的汇编代码框架(结合栈帧切换相关内容来理解)

保存上一层函数栈帧,设置当前函数栈帧:enter指令

恢复上一层函数的栈帧:leave指令

3. 一个栈帧内可能包含的内容

C
int caller(){
	int temp1 = 125;
	int temp2 = 80;
	int sum = add(temp1,temp2);
	return sum;
}

int add(int x, int y)
{
	return x+y;
}

栈帧示意图:

通常将局部变量集中存储在栈帧底部区域 如:由示意图可见,C语言中局部变量越靠前定义,则越靠近栈顶(低地址)。也就是说,越靠后定义的局部变量,就越靠近栈底(高地址) 将调用参数存储在栈帧顶部区域,越靠前的参数越靠近栈顶(低地址)

  1. 栈帧最底部一定是上一层栈帧基址(ebp旧值)
  2. 栈帧最顶部一定是返回地址(当前函数的栈顶除外)

gcc编译器将每个栈帧大小设置为16B的整数倍(当前函数的栈帧除外)

  • 栈帧具体数据内容分布:

贡献者

The avatar of contributor named as freeway348 freeway348

文件历史

撰写