刚学汇编语言那会儿,总觉得它离现实太远。键盘敲下的每一条指令都像在和机器“对话”,没有高级语言的便利,也没有图形界面的友好。可当你真正跑通第一个上机练习题时,那种从0到1的成就感,别的语言很难给。
为什么要做汇编上机练习?
很多人觉得汇编过时了,但其实它藏在网络优化、嵌入式系统甚至病毒分析的底层。比如你调试一个网络延迟问题,发现卡在某个硬件中断处理上,这时候懂点汇编,能直接看懂寄存器状态,比等日志输出快得多。
学校常见的上机题,比如“输入一个数字并判断奇偶”,看起来简单,写起来却容易踩坑。下面这个例子用的是8086汇编,运行在DOSBox环境下:
MOV AH, 01h ; 键盘输入功能
INT 21h ; 调用DOS中断
SUB AL, 30h ; ASCII转数字
MOV BL, AL ; 存入BL
AND BL, 01h ; 与1做按位与
JZ EVEN_LABEL ; 为0则跳转到偶数标签
MOV AH, 09h ; 显示字符串功能
LEA DX, ODD_MSG
INT 21h ; 输出'ODD'
JMP END_LABEL
EVEN_LABEL:
MOV AH, 09h
LEA DX, EVEN_MSG
INT 21h ; 输出'EVEN'
END_LABEL:
MOV AH, 4Ch
INT 21h ; 程序退出
ODD_MSG: DB 'ODD$'
EVEN_MSG: DB 'EVEN$'
这段代码的关键在于理解AL寄存器怎么保存输入,以及如何用AND指令做奇偶判断。新手常犯的错是忘了ASCII转换,直接拿字符'5'去运算,结果当然不对。
另一个实用练习:字符串反转
网络传输中有时要校验数据顺序,字符串反转是个经典训练题。思路是用两个指针,一个指向开头,一个指向结尾,逐个交换。
LEA SI, STRING ; SI指向字符串首
MOV CX, LENGTH ; CX为长度
DEC CX ; 最后一个是'$',不参与
REVERSE_LOOP:
MOV DI, SI ; DI也指向当前SI位置
ADD DI, CX ; DI偏移到对称位置
MOV AL, [SI] ; 取左边字符
XCHG AL, [DI] ; 和右边交换
MOV [SI], AL ; 写回左边
INC SI ; 左指针右移
DEC CX ; 长度减一,相当于右指针左移
CMP SI, DI ; 是否交叉
JL REVERSE_LOOP ; 没交叉就继续
RET
STRING DB 'HELLO$', LENGTH EQU 5
这类题目练多了,你会更清楚内存是怎么被操作的。比如为什么用XCHG而不是两次MOV,因为前者是原子操作,效率更高,在底层优化中很关键。
现在很多网优工具其实在后台调用了汇编写的模块,比如抓包时的快速过滤逻辑。虽然你不用从头写,但能看懂相关代码,排查问题时就能更快定位。
平时可以找些公开的上机题库练手,比如高校课程实验题或开源项目里的asm文件。别怕报错,INT 21h调用失败多半是AH没设对,慢慢调几次就熟了。