针对往年题中出现的一些查漏补缺
misc
“Is
leaq(%rbx,%rsp) %r8correct?”rsp不能用作 index register,只能用作 base register"Is
leaq 0x3284738324(%rbx %rbx) %r8correct?"Displament 只能是 1,2,4 bytes 的数,不能是 8-byte number
"Is
leaq (%rbx %rbx) (%r8)correct?"leaq的 destination 只能是 general purpose registerleaq的 source 一定要是 memory addressing operandfloat->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
ah是al的高 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 寄存器更多.
divq和mulq都 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而不使用$. 例如1234,1234(%rbx,%rax,1).union中注意比如一个int和charunion 起来,如果设置了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])=4nm,A扩大的倍数是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')=48,int('a')=97,int('A')=65int-sizeof(..)会 \(\ge 0\) 容易导致变成很大的数然后越界.- 记住 float 有向偶数舍入,加法的时候不要因为一个数可能被舍掉了就忽略掉,可能会有舍入。
2021
- 0x开头写十六进制!!
- jump 的第二位的数值是,目标行减去下一行!
- movabsq 目标只能是寄存器.
2020
错题整理:
union{double d,struct{int x,int y}},将y=0x3ff00000后d=?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 都是会算的,所以不能把可能为空的指针放在这里.