找工作的时候,有些岗位特别是底层开发、嵌入式或者安全方向,面试官总爱问汇编语言的问题。很多人平时写代码用的都是高级语言,突然碰到汇编,脑子就有点发蒙。其实只要摸清常考的方向,准备起来并不难。
为什么还要考汇编?
别看现在都用 Python、Java 写业务,但系统性能优化、反病毒分析、驱动开发这些领域,还是得和寄存器、内存地址打交道。面试官问汇编,其实是想看看你对计算机底层到底有没有概念。
最常被问到的几个问题
比如“函数调用时栈是怎么变化的?”这个问题几乎必考。你可以这样答:当调用一个函数时,返回地址会被压入栈,然后是保存的寄存器、局部变量。函数执行完再依次弹出,恢复现场。
再比如,“EAX、EBX、ECX、EDX 这几个通用寄存器有什么区别?”虽然它们都能存数据,但某些指令有默认习惯。比如 ECX 常用于循环计数(LOOP 指令就默认用它),EAX 通常放返回值。
手写一段简单的汇编代码也是常见题型
比如让你用 x86 汇编写个加法:
mov eax, 5
mov ebx, 10
add eax, ebx
; 此时 eax 的值为 15
看起来简单,但面试官可能会追问:如果结果超过 32 位怎么办?这时候就得提到进位标志 CF 和 ADC 指令了。
理解机器级程序执行流程很重要
有次面试官让我分析下面这段 C 代码对应的汇编逻辑:
int add(int a, int b) {
return a + b;
}
对应的汇编大致长这样:
push ebp
mov ebp, esp
mov eax, [ebp+8] ; 取第一个参数
mov ebx, [ebp+12] ; 取第二个参数
add eax, ebx ; 相加
pop ebp
ret
关键是要说清楚参数怎么传、栈帧怎么建立、返回值怎么带回。这些细节一说,面试官就知道你不是背答案的。
逆向思维题也常出现
给一段汇编代码,让你还原成 C 逻辑。比如看到 test 和 jz,基本就能判断是在做条件判断;看到 loop 或 jmp 回上面的标签,那大概率是个循环。
还有一种题是“如何用汇编实现两个变量交换而不使用临时变量?”除了 XOR 方法,还能用加减法:
mov eax, [a]
mov ebx, [b]
add eax, ebx
sub eax, ebx ; eax 变成原 a
sub ebx, eax ; ebx 变成原 b?等等,这里容易出错!
实际更稳妥的是用异或:
mov eax, [a]
mov ebx, [b]
xor eax, ebx
xor ebx, eax
xor eax, ebx
; 现在 eax 是原 b,ebx 是原 a
这种题考的就是对指令副作用的理解。
调试经验加分
如果你能在回答中提到“我在用 GDB 调试时看过反汇编”,或者说“曾经通过查看栈回溯发现过缓冲区溢出”,那立刻显得真实又靠谱。毕竟,能动手的人比只会背书的强得多。
准备这类面试,不用把整本《Intel 手册》背下来,重点掌握寄存器用途、栈操作、函数调用约定(__cdecl、__stdcall)、常见指令含义就行。多练几道真题,上场就不慌。