ICS-复习1

2025-10-04

ICS

针对往年题中出现的一些查漏补缺

misc

  • “Is leaq(%rbx,%rsp) %r8 correct?”

    rsp 不能用作 index register,只能用作 base register

  • "Is leaq 0x3284738324(%rbx %rbx) %r8 correct?"

    Displament 只能是 1,2,4 bytes 的数,不能是 8-byte number

  • "Is leaq (%rbx %rbx) (%r8) correct?"

    leaq 的 destination 只能是 general purpose register

    leaq 的 source 一定要是 memory addressing operand

  • float->int 截断/向0取整,int->float 向偶数取整,int->double不失精度

  • OF:看作 signed 时候出现正+正=负/负+负=正的情况,例如 \((+127)+(+1)=-128\)

    CF:看作 unsigned 的时候出现了给 \(2^{w}\) 位进位的情况,例如 \((-1)+(-1)=-2\).

    INC 和 DEC 不会改变 CF,但是会设置 OF 和 ZF

  • 没有 movzlq

  • 栈帧的边界地址需要是 16 倍数

  • I(Rb,Ri,k) 的 Rb 和 Ri 必须是 64 位寄存器

  • zwq 这种的 mov 指令目标都只能是寄存器

  • set 的目标只能是内存或者低位寄存器

  • cmov 目标只能是寄存器,并且不支持单字节寄存器

2014

  • ahal 的高 8 位

    b=byte,指 8 位;w=word,指 16 位, l=long,指 32 位,q=quad,指 64 位

    movz 是 0 扩展,movs 是符号扩展

    熟背寄存器列表!

  • 两个相同类型的地址相减会自动除以 size,不同类型的则不会.

  • switch 跳转为间接跳转,需要用 jmp *.L3(,%eax,8)(如果是 64 位系统)

  • CISC 为复杂指令集计算机(eg x86/AMD),RISC 为简明指令集计算机 (eg. ARM)

    CISC 采用变长指令,指令很多,最短的可以 1byte(如 ret),而 RISC是定长指令,指令较少. 所以 CISC 取指内部实现比较复杂. RISC 寄存器更多.

  • divqmulq 都 imply 是 unsigned 运算,rdx 直接设为 \(0\) 也如此. 请一定注意是否表明一个变量是 signed / unsigned.

    jnl, jge 这种都是 signed 比较,ja, jbe 这种是 unsigned 比较,请一定注意有没有坑表明可能有类型转换或者是否是 signed.

    (那个很坑的读汇编题目,unsigned x 和 (int)x > 0)

  • 运算和比较的时候,如果同时存在,int 都会被转为 unsigned,但是 unsigned 会被转为 long long.

  • Sun, PPC MAC, Internet 是 Big Endian,其余大概都是 Small Endian,即小位存在小地址.

2015

  • 寻址时直接使用 1234 而不使用 $. 例如 12341234(%rbx,%rax,1).

  • union 中注意比如一个 intchar union 起来,如果设置了 char 的,那么 int 的其他位有可能有垃圾数据而不确定.

  • IA32 下 longlong 和 double 的 aligned 都按 4. IA64 下都按 8.

  • 判断是否 \(>0\) 的时候要注意是否可能 \(=0\).

2017

  • (%...) 地址寄存器必须是 64 位寄存器,只能是 r 不能是 e

  • 机器在计算指针与常数的运算时,会将常数乘以指针指向的元素大小

    eg. 对于 int A[n][m]&A 扩大的倍数是 sizeof(A[n][m])=4nmA 扩大的倍数是 sizeof(A[0])=4m*A 扩大的倍数是 sizeof(A[0][0])=4.

  • RISC 没有条件码.

2019

  • 间接跳转一定要有 *...,例如 *%rax.

  • 算术位移为 sar.

  • 访问栈中的值都是靠 -...(%rsp)

  • int * x ();:x 是一个返回值为 int* 的函数

    int *(*f[3]) ();:f 是数组,数组元素是指针,指针指向一个返回值为 int* 的函数

    int (*f)[3]:f 是指针,指针指向一个数组

  • 跳转相关,机器代码中要填相对偏移量(可能是负数),然后小端法!

  • 一定一定注意十六进制计算是十六进制计算!!!!!!!

2023

  • 算术右移是下取整,除法是向 0 取整.
  • 条件传送指令不支持单字节传送
  • set* 的目标一定是低位单字节寄存器
  • 字符串 01234567 由于最后会有 \0 ;m.l,k所以实际长度是 9.
  • int('0')=48int('a')=97int('A')=65
  • int-sizeof(..)\(\ge 0\) 容易导致变成很大的数然后越界.
  • 记住 float 有向偶数舍入,加法的时候不要因为一个数可能被舍掉了就忽略掉,可能会有舍入。

2021

  • 0x开头写十六进制!!
  • jump 的第二位的数值是,目标行减去下一行!
  • movabsq 目标只能是寄存器.

2020

  • 错题整理:

    union{double d,struct{int x,int y}},将 y=0x3ff00000d=?

    ans=1

    d=0x 0100 0000 0000 0080 时,x,y=?

    ans: \(1,-2^{31}\)

2018

  • movabsq 目标只能是寄存器.
  • movswq 是 signed from w to q,zwq 是零扩展.

2022

  • short to unsigned 是 符号扩展.

2024

  • cmov 无论 condition 是什么,Src 都是会算的,所以不能把可能为空的指针放在这里.