4.3.1-1 汇编语言中的 地址码

==指令格式 = 操作码 + 地址码==

  • ==探讨的:如何在汇编语言中指明指令的数据(操作码)存放在什么地方。(关注于地址码)==

  • ==下一节:汇编语言指令可以对数据进行哪些处理。(关注于操作码)==

前言

  • 高级语言→汇编语言→机器语言

image-20260226094410975

image-20260226094439829

汇编角度看待指令

image-20260226094818185 image-20260226100055282

关于寄存器

  • 三类常见寄存器
image-20260226100718663

(少见的情况)

  • 通用寄存器 可以把E去掉,用低16bit,甚至用某个低8bit。
  • 其他寄存器固定32bit

image-20260226101035949image-20260226101011430

(补充)

  • 【ebx】指的是ebx所指的主存地址
  • ==未指明默认32bit==
image-20260226101454284

总结

image-20260226101604146


4.3.1-2 汇编语言中的 操作码

==这一节:汇编语言指令可以对数据进行哪些处理。(关注于操作码)==

image-20260226110927202

算术运算

  • destination不可以是常量,只能是寄存器或者主存。source都可。
  • i - integer带符号的整数
  • div s ,s是除数,被除数提前放在edx,eax。(高位存余低位存商)(被除数需要提前扩展(位数*2),所以需要两个寄存器)

image-20260226112343895

逻辑运算

image-20260226113038595

其他指令

image-20260226113310667


4.3.1-3 AT&T 格式 v.s. intel 格式

image-20260226114251144

image-20260226114449792


4.3.2 选择语句的机器级表示

  • PC (program counter)也被称为 IP(instruction pointer)

无条件转移指令jmp

image-20260226130627276

条件转移指令jxxx

image-20260226131300659

(简单例子)

image-20260226131711931image-20260226132102625

扩展:cmp指令底层原理

image-20260226132729951


4.3.3 循环语句的机器级表示

用 条件转移指令 实现循环

image-20260226132931532

用 loop指令 实现循环

  • (ecx是专门用于循环计数器的,eax ebx edx都不行)
  • 理论上只要能用loop指令实现的功能,都可以用条件转移指令实现。(只是 loop指令更简洁,且jxxx第一印象可能是分支而不是循环(但并非如此哈哈哈))

image-20260226133511948


4.3.4 函数调用的机器级表示

待解决的:

  • 函数调用过去和回来的过程 – 1

  • 如何访问栈帧里的数据 – 2

  • 如何传递调用参数,返回值 – 4

  • 栈帧内可能包含哪些内容 – 4

call和ret指令

高级语言视角下的 函数调用

image-20260226134658011

image-20260226134741549

x86汇编语言视角下的 函数调用

image-20260226135247889


如何访问栈帧

函数调用栈 在内存中的位置

image-20260226140709521

==栈帧:==

  • ebp寄存器 指向栈帧“底部”(extend base pointer)
  • esp寄存器 指向栈帧“顶部 (extend stack pointer)
  • ebp和esp之间的内容就是栈帧的范围

其他:

  • 入栈 - 4,因为高地址是栈底,低地址是栈顶
  • 默认4字节为单位
  • 出栈不能pop+元素,原因同destination

访问栈帧数据的方式①:push,pop指令

image-20260226141447650

访问栈帧数据的方式②:mov指令

image-20260226141918737

如何切换栈帧

(栈指针怎么变)

函数调用时,栈指针的变化

image-20260226172951049

image-20260226183721505

函数返回时,栈指针的变化

image-20260226183915571

(注:每一个栈帧的底部,用于保存上一层栈帧的基址)

image-20260226184109023

ret的作用

image-20260226184200050

函数调用时栈指针的变化(总)

(

image-20260226184649617

如何传递参数和返回值+指针包含的内容

指针包含的内容

  • (like [ebp==-==4]这类就是指局部变量

image-20260226192036882

  • (此处是add函数,[ebp==+==8]这类指的是调用函数

image-20260226192332054

  • (有空闲的区域是正常的)

image-20260226192633373

  • 调用参数发生在call(下一fuc)指令之前

image-20260226194506993

实战

  • 压入上一层栈帧基址

image-20260226194645675

  • esp-24,划出了栈帧的范围

image-20260226195154935

  • 局部变量的初始化

image-20260226195512328

  • 调用add的参数发生在add函数call之前
  • (mov指令是不能两个操作数都来自主存的,所以此处需两步)
  • (x的参数调用同y)

image-20260226195925891

  • call指令,把ip的旧值压到栈顶
  • ==同时程序的执行流,转移到add函数的第一条指令==

image-20260226200244224

  • push指令把caller函数的栈帧基地址保存下来(0xA00F…)
  • move指令让ebp指针指向当前函数的基地址(esp所指的)

image-20260226200347709

  • 访问add需要的两个参数x,y
  • 后add,并把结果写回eax

image-20260226200854157

  • leave指令,切换回上层函数的栈帧

image-20260226201027770

  • 执行return指令,让程序的指令流回到上一层函数

image-20260226201111545

  • ==通常用eax返回结果==
  • 用eax把 add函数的返回值 返回到sum变量【ebp-4处】

image-20260226201438311

  • caller函数 把sum的值返回给 上一层函数 【先返回到eax寄存器里】

image-20260226201710656

总结

image-20260226201905123

image-20260226202018379

image-20260226202811025