笔记

原版全

计算机系统

定点数的加减运算

img

ZF & SF

无符号数溢出 & CF

无符号数都为正数

综合来说

=CF=SubCout+SubCout=SubCout

带符号数溢出 & OF

采用一位符号位

=OF=CnCn1

假设机器字长为 4(n = 4),能表示的有符号数范围为 -8 ~ 7,那么就有:

[5]补 = 0101,[4]补 = 0100;

[-5]补 = 1011,[-4]补 = 1100;

[5 + 4]补 = 0101 + 0100 = 1001 = [-7]补; (正溢出)

[5 - 4]补 = [5 + (-4)]补 = 0101 + 1100 = 1 0001 = [1]补;

[4 - 5]补 = [4 + (-5)]补 = 0100 + 1011 = 1111 = [-1]补;

[-5 - 4]补 = [-5 + (-4)]补 = 1011 + 1100 = 1 0111 = [7]补; (负溢出)

采用两位符号位

=OF=SnSn1

[5]补 = 00 101,[4]补 = 00 100;

[-5]补 = 11 011,[-4]补 = 11 100;

[5 + 4]补 = 00 101 + 00 100 = 01 001 = [1]补; (正溢出)

[5 - 4]补 = [5 + (-4)]补 = 00 101 + 11 100 = 1 00 001 = [1]补;

[4 - 5]补 = [4 + (-5)]补 = 00 100 + 11 011 = 11 111 = [-1]补;

[-5 - 4]补 = [-5 + (-4)]补 = 11 011 + 11 100 = 1 10 111 = [-1]补; (负溢出)

浮点数的表示

img

image-20240623182619807

img

img

img

程序的机器级表示

寻址方式

IA32汇编指令

通用寄存器

img

前四个:a -> add, b -> base, c -> count, d -> 'data'

si: s -> source -> 源地址, di -> destination -> 目的地址

bp -> base pointer, sp -> stack pointer

ATT & Intel

img

寻址方式

img

常用指令

数据传输指令
  • mov指令

数据传递方向

ATT ->

Intel <-

img

  • lea:load effective address,加载有效地址,将一个内存地址加载到目的寄存器;

  • push:将数据压入栈,同时 esp 减去数据长度;

  • pop:将栈顶数据弹出栈,同时 esp 加上数据长度;

算术和逻辑运算指令

img

除法指令,它们都只有一个操作数,表示除数,被除数则放在 edx : eax 中;得到的结果商放在 eax 中,余数放在 edx 中:

  • div:无符号除

  • idiv:有符号除

转移指令

img

  • 重置条件码

img

e.g

选择结构机器级表示

C程序

使用goto

汇编

img

使用vs2022 x86反汇编

循环结构机器级表示
do - while循环

C程序

使用goto

汇编

img

while循环

img

for循环

img

过程调用的机器级表示
使用栈实现

img

流程

img

  • 程序代码和数据:主要包括 只读代码段读写段(.data 和 .bss)。对所有进程来说,代码都是从固定地址开始,紧接着就是 C 语言中的全局和静态数据。其中 .data 中是已初始化的全局和静态 C 变量,而 .bss 中是未初始化的全局和静态变量。

  • 堆(Heap):用于运行时的动态内存分配,向上(高地址)生长。代码和数据区,在进程开始运行时就被指定了大小;而通过调用 malloc 和 free 这样的 C 标准库函数,可以让堆区动态地扩展和收缩。

  • 共享库的内存映射区:用户区的中间部分是一块内存映射区域,用来存放像 C 标准库这样的共享库。(printf)

  • 用户栈(Stack):位于虚拟地址空间用户区顶部,向下(低地址)生长。一般用来存储局部变量和函数参数,结合堆栈指针可以方便地实现函数的调用和返回。

img

  1. 从可执行文件加载

    image-20240622154330031

  2. 执行P指令

    1. P函数局部变量入栈

      image-20240622154512855

    2. 调用Q函数

      问题:

      1. 参数能够传递给Q函数

      2. 执行完Q函数能够返回到跳转语句的下一句

      3. P函数中使用的寄存器的值应该被保存

      依次由如下解决方案:

      1. 在P函数的栈帧中压入参数构造区和调用指令的下一条指令

        image-20240622195348350

        image-20240622195404685

        eip寄存器传入跳转的指令的位置

      2. 在Q函数的栈帧中P寄存器的值入栈

main栈帧

EAX = 0050C008 EBX = 02636000 ECX = 0050C008 EDX = 00000001 ESI = 02636000

EDI = 028FF6BC EIP = 00501904 ESP = 028FF5CC EBP = 028FF6BC EFL = 00000246

EAX = 0000001F EBX = 02636000 ECX = 00000017 EDX = 00000001 ESI = 02636000

EDI = 028FF6BC EIP = 0050190C ESP = 028FF5C4 EBP = 028FF6BC EFL = 00000246

栈顶指针对应的内存地址

image-20240622201110421

ESP = 028FF5C0

image-20240622201732128

ESP = 028FF5BC EBP = 028FF6BC

image-20240622202224089

Q的栈帧开始

初态: ESP = 028FF5BC EBP = 028FF6BC

末态: ESP = 028FF5BC EBP = 028FF5BC

ESP = 028FF4F0

P寄存器值

EBX = 02636000 ESI = 02636000 EDI = 028FF6BC

image-20240622203334719

此时:ESP = 028FF4E4

image-20240622204158738

image-20240622204922635

image-20240622205049461

实践(归并排序的机器级表示)
C
main

ECX = 0x00AFF75C

image-20240622215803198

printArray

打印第一个数:

image-20240622221525302

image-20240622221923369

image-20240622221944873

main
mergeSort

image-20240622223748067

merge