Chapter 1

不同层次的抽象
image.png
经典图例,完美展示了讨论的范畴和抽象层级:

  • process 其实已经算是最高级别的抽象了,它几乎等价于一台完整的计算机。也即是,它是整个计算机的一份 resource mirror。
  • 将 process 剖析开来,则获得经典的三类 resource:
    • I/O device:files
    • memory:virtual memory
    • CPU:instruction set architecture
  • virtual memory 本身其实还涉一重抽象:
    • memory 本身
    • I/O device:files

Chapter 3

整个 assembly code 都是围绕着 CPU、register、memory 打转,特别是 register 值得格外重视,它是整个 instruction 的枢纽中心。

如果按照 instruction 操作来分类,assembly code 的结构其实很简单,仅 6 类:

  1. access data(register、memory)
  2. arithmetic、logical operation
  3. control(if, loop)
  4. procedure(function call)
  5. array(allocation、access)
  6. heterogeneous data structure(struct、union)

image.png
这些 32 位寄存器有多种用途,但每一个都有 “专长”,有各自的特别之处(前缀 e 是因为从 16-bit 扩大到了 32-bit 来标明 extend):

  1. arithmetic operation**:**
    1. eax(accumulator):是 “累加器”,它是很多加法乘法指令的 default 寄存器。
    2. ecx(counter): 是计数器,是重复(rep)前缀指令和 loop 指令的内定计数器。
    3. edx(divider): 则总是被用来放整数除法产生的余数。
    4. ebx(base): 是 “基地址” 寄存器,在内存寻址时存放基地址。
  2. source/destination**:**
    1. esi(source index):分别叫做 “源索引寄存器”(source index),因为在很多字符串操作指令中,DS:ESI 指向源串,而 ES:EDI 指向目标串.
    2. edi(destination index):目标索引寄存器(destination index)
  3. pointer**:**
    1. esp(stack pointer):栈顶(stack top)指针。
    2. ebp(base pointer):是 “基址指针”(base pointer),它最经常被用作高级语言「函数调用」(function call)的 “框架指针”(frame pointer)
  4. PC(program counter)**:**
    1. eip:寄存器存放下一个 CPU 指令存放的内存地址,当 CPU 执行完当前的指令后,从 EIP 寄存器中读取下一条指令的内存地址,然后继续执行。

image.png
可以总结的规律是

  • 「有括号」的表达式,都会被映射为 M [] 操作
    • 最 general 的形态: Imm(Eb, Ei, s) = M[ Imm + R[Eb] + R[Ei] * s ] .
  • 「 没有括号」时,分三种情况:
    • 以 % 开头的,映射为 R [] 操作
    • 以 $ 开头的,映射为常数值
    • 单纯的常数值,映射为 M [] 操作

image.png

  • %eax = R[%eax] = 0x100
  • 0x104 = M[0x104] = 0xAB
  • $0x108 = 0x108
  • (%eax) = M[ R[%eax] ] = M[0x100] = 0xFF
  • 4(%eax) = M[4 + R[%eax]] = M[4 + 0x100] = M[0x104] = 0xAB
  • 9(%eax, %edx) = M[9 + R[%eax] + R[%edx]] = M[9 + 0x100 + 0x3] = M[0x10C] = 0x11
  • 260(%ecx, %edx) = M[260 + R[%ecx] + R[%edx]] = M[260 + 0x1 + 0x3] = M[0x104 + 0x4] = M[0x108] = 0x13
  • 0xFC(, %ecx, 4) = M[0xFC + R[%ecx] 4] = M[0xFC + 0x1 4] = M[0x100] = 0xFF
  • (%eax, %edx, 4) = M[R[%eax] + R[%edx] 4] = M[0x100 + 0x3 4] = M[0x100 + 0xC] = M[0x10C] = 0x11

image.png

可以看到

  • mov 操作的后缀:
    • 仅有数量单位 b, w, l
    • 后缀 s(sign-extended),紧接数量单位转换
    • 后缀 z(zero-extended),紧接数量单位转换
  • pushl 操作,实际是由两步构成的:
    • 将 register % esp 的值,修改为 R [% esp] - 4;(即 memory 中的地址值减 4)
    • 之后,再将 S 的值复写到 register % esp 的值所指向的 memory 区域;(即将 S 复写到 M [R [% esp] ] .)
  • popl 操作,也是由两步构成:
    • 将当前 register % esp 所指向的 memory 区域的值,复写到 D;(即将 M [R [% esp] ] 的值写到 D)
    • 再将 register % esp 保存的地址值,更新,即自增 4。

leal 操作可用于 compactly describe 线性操作,例如:ax+b 可以通过 b leal(%eax, %eax, (a-1)) 来实现。