通俗易懂的汇编语言(王爽老师的书)_哔哩哔哩_bilibili
评价
- 百度网盘有点乱
- 这是一本我曾数次拿起又放下的书
- 这是我看过的最好的汇编语言的书,真的是循序渐进,学起来无压力,爱不释手,我还专门买了一本
- 之前拿头把哈工大的os啃完了,这边看汇编,感觉好像都通了,嘎嘎爽
- 我也是,看了李治军老师讲的引导启动程序课程,过来补习汇编知识
- 这本书真的好。我大学看完这本书后,才正式看的懂汇编,更重要的是对内存结构有更加深入的理解了
- 我感觉这是我听到的最好的汇编课程了,唉,20年前我学汇编的时候,怎么就没有这样的老师。
- 哥们因为计组,操作系统和单片机都不会才来学的汇编的
- 字正腔圆!声音清脆!一听就喜欢!
- 这本书就是入门神作,我看过清华的绿灰皮,也看过王爽老师的这本,从初学者来讲,王爽老师的著作才是从让学生真正了解汇编的原理出发。清华那边比较适合在实践中当字典用。
- 感觉做逆向不需要学习那么深吧,只要能把反汇编代码用高级语言写出来就行了,能看懂就行,现在不是固定方向比如做驱动啥的,一般不需要学习那么深吧 ——不清楚,我最近也刚开始学逆向,感觉要补的基础知识太多了|我感觉不用学太深
- 想问一下期末考单片机原理与应用,后面的汇编大题不会。学这个可以吗?|学这个能看懂汇编,但是arm汇编和x86指令上有些不一样
- 全网都找不到很好的入门 教学视屏,都是照本宣读式都学,如果我来都就从0到1,从最初工程师为什么经发明汇编语言和各种结构的由来 | 他们这样的视屏需要有一定的基础才能完全听懂。比如什么叫寄存器,有些什么功能,原理是如何触发存取数据的,为什么要寄存器,寄存器取名的原则,英文全称等,这样有助于记忆。再比如说二进制和8进制,10进制和16进制,为什么要这么多的进制?工程师发明这些东西最初的动机等。他们没有一个讲原理,而是格式化式的让初学者根本没有法理解。我看网络上在学老师出来讲视屏都是拿他们用了几年才完全理解的原理直接强加给初学者,没有基础的初学者很难理解的|汇编语言学习前本身就要有一点计算机组成原理和高级语言编程基础,新手如果没有这种基础的话,建议还是去补一下,我是因为要学操作系统才来学的汇编
授课老师:贺利坚-计算机与控制工程学院 (ytu.edu.cn)
导学
运行效率高,适用于驱动程序、OS内核、嵌入式开发
学习意义:加深计算机原理和OS的理解;体会机器的逻辑功能;理解硬件结构,掌握指令集,理解程序的运行过程
学习内容:采用8088,8086指令集与汇编语言设计(作为教学系统而非实用系统降低学习难度,抓住本质);延申:80X86,Linux,ARM
书的检测点通过再学下一部分
机器语言是机器指令的集合
汇编指令是机器指令的助记符,便于记忆的书写格式
学习计算机组成当然不需要深入了解计算机组装各部件的电气特性
如何判断二进制信息是数据还是指令
2地址总线宽度=寻址能力B;数据总线宽度/8=一次传送数据B
CPU对存储器的读写:存储单元地址(地址信息);器件选择,读写命令(控制信息);读写数据(数据信息)
把各类存储器看作一个逻辑存储器——统一编址
MS DOS在Win XP中(DOS虚拟机)DOS模拟器
DOSBox
自动挂载.conf中添加mount c: d:\MASM 换行 c:
参考
之前评论分享的有0105汇编语言实践环境搭建,放入D盘MASM
调整DOSBox的窗口大小:跨过三连坑_windowresolution-CSDN博客
地址:"C:\Users\han\AppData\Local\DOSBox\dosbox-0.74-3.conf"
windowresolution=original
output=surface
替换为
windowresolution=1028x1024
output=opengl
此外还有DOSbox的不能滚动问题
第二部分
寄存器是CPU内部的信息存储单元
学习==爽
8086CPU中有14个寄存器
- 通用寄存器:AX,BX,CX,DX
- 变址寄存器:SI,DI
- 指令寄存器:SP,BP
- 指令指针寄存器:IP
- 段寄存器:CS,SS,DS,ES
- 标志寄存器:PSW
8086上一代CPU寄存器是8位的,如何保证程序兼容性:
通用寄存器分为两个独立的8位寄存器使用;AX可分为AH和AL高八位与低八位
字长word取决于机器的CPU
mov指令:
add指令:add al,93H(ax==00C5H)–>ax=0058H //只是低八位运算,不进位
溢出问题,直接截断溢出
确定物理地址的方法 //感觉老师讲的比较基础,也可能因为自己学过了OS和计组(老师讲一些概念特性时,自己会感觉比较显然)
Debug的使用
a 地址:写入汇编指令
d 地址:查看数据
u 地址:查看代码
t 执行CS:IP处的指令
q 退出debug
CS、IP与代码段
CS 代码段寄存器
IP 指令指针寄存器
CS:IP CPU将此指向的内容作为当前指令执行
指令三字节,执行后IP+3
JMP指令
如何修改CS,IP
R命令修改,rcs,rip
jmp 短地址:偏移地址:同时修改CS、IP内容
jmp 某一合法寄存器 :仅修改IP内容
可以把课本上的代码放到debug运行一遍
内存中字的存储
低位字节存放在低地址单元,注重内存的高地址,放到直接的高位,放前面(不考虑上下顺序)
用DS和[address]实现字的传送
用DS寄存器存放要访问的数据的段地址;偏移地址用[…]形式直接给出
必须是数据–>一般寄存器–>段寄存器的方式传送mov bx,1000H; mov ds,bx;
跑了一下,先设置内存,配置指令,t运行
DS和数据段
cs是值cpu执行的当前指令的段地址,ds是数据开始的段地址。 CS是告诉CPU,去哪个位置找内容当成指令去执行; DS是告诉CPU,去哪个位置找内容当成数据被使用。
add al,[0] [1] [2]累加数据段的前三个单元数据(注:这里是al)
add ax,[0] [2] [4]累加数据段的前三个字型数据
后面讲了寄存器、内存单元、数据之间能否用于mov、add操作的操作关系
栈及栈操作实现
CPU提供的栈机制,支持栈的方式访问内存空间
editplus
由源程序到程序运行
compile link
运行直接输入:文件名(.exe)
用debug跟踪程序的执行
debug p4-1.exe
r 查看寄存器
确实,自己听着听着乱了,内存地址什么的,有着高中物理的感觉
[…] (…)
(…)为方便学习约定:表示一个内存单元或寄存器的内容(看案例更清晰
idata表示常量
汇编代码-内存单元-寄存器画出来就很清晰了
Loop指令
实现循环(计数型循环)
assume cs:code
code segment
mov ax, 2
mov cx, 11
s:
add ax, ax
loop s ; 跳转到标号s并重复执行cx次
mov ax, 4C00h
int 21h
code ends
end
不知道GPT哪里加个空格,换行,masm成功;不然OUT OF MEMORY
cx和loop指令组合实现循环:
- cx中存放循环次数
- 标号指定循环开始位置
- 标号和loop指令中间,写上循环执行的程序段(循环体)
汇编程序中,数据不能以字母开头,前加0
段前缀
mov al,[0] : (al)=0 等同于mov al,0
mov al,ds:[0] : (al)=((ds)*16+0) 常量直接作为偏移地址时,设置段前缀
访问连续的内存单元–loop和[bx]联手
计算ffff:0~ffff:b的和,结果存储到dx中(直接用dx取出的是字16位;dl的话长度只有8位)取出8位数据,加到16位寄存器
mov al,ds:[addr]
mov ah,0
add dx,ax
确实有点像PY的列表
避免数据被解释为代码;设置数据从CS:0000开始,代码从CS:0010开始
代码外围加上start end start ,CS:IP指向start处 | 确实相当于main函数
在代码段中使用栈
通过栈的后入先出实现数据逆序存放
把数据、代码、栈放入不同段
assume cs:code,ds:data,ss:stack
data segment
data
data ends
stack segment
stack
stack ends
coed segment
start:
code
code ends
end start
内存寻址方式
字符大小写转换,不需要分支结构,而是位运算
and al,11011111b 小写字母转换为大写字母
or al,00100000b 大写转小写
[bx+idata]的含义
偏移地址的加减法,形式理解类似于数组
汇编的讲解有很多高级语言的影子
变址寄存器 SI、DI
字符串复制的例子,
源数据起始地址:datasg:0
目标数据起始地址:datasg:16
所以和通用寄存器的区别到底是什么呢
[bx+si]和[bx+di]方式寻址
bx作为基址,更多的变化交给si变址来做
多字节数据在内存(或显存)和寄存器上存放顺序_双字节数在存储器中的存放规律-CSDN博客
高位高地址
不懂内存中字的字节顺序,到寄存器中要颠倒一下
在取数据的时候,数据总线中的内容,高位在前低位在后, 在取指令的时候,低位在前高位在后
不同的寻址方式的灵活应用
[idata]直接寻址
[bx]寄存器间接寻址
[bx+idata]寄存器相对寻址(相对于立即数idata;自己以为是相对于寄存器呢)
[bx+si]基址变址寻址
[bx+si+idata]相对基址变址寻址
上面的名字,之前计组书上看过;内存寻址方式总结,看了汇编略微通透一点点呵呵
先确定行bx,bx+3确定到列
前三个都改变,[bx+si],类似二重循环,二重循环的实现:
只有一个cx控制循环的寄存器,可以将外层的cx值保存到dx中,内存循环结束一次后再恢复赋值回来
寄存器只有14个;解决:
采用固定的内存空间保存数据(cx值)mov ds:[40h],cx
用栈保存数据(ss,sp;栈能设置几个呢)
其实C语言里大括号的本质就是栈
不同寻址方式演示
pdf展示 动画
用于内存寻址的寄存器
bx,bp,si,di可对内存单元寻址(指令集设计时只包含这些)
bx默认ds段,bp默认ss段 | 默认[bp];单独设置es:[bp]
建议写出段,提高可读性
处理的数据在哪,有多长
位置的表达:
- immediate data立即数:直接包含在机器指令中的数据
- 寄存器:指令要处理的数据在寄存器中
- 内存:段地址SA和偏移地址EA;指令要处理的数据在内存中,由SA:EA确定内存单元
数据有多长
- 字word操作
- 字节byte操作
- 用word ptr或byte ptr指明 显性
寻址方式的综合应用
修改编程中的过时数据
类比结构体
div指令实现除法
被除数 | AX | DX和AX |
---|---|---|
除数 | 8位内存或寄存器 | 16位内存或寄存器 |
商 | AL | AX |
余数 | AH | DX |
debug g命令是算到指定内存单元之前
除法命令的设计真节省啊
在内存单元实施除法
data segment
dd 100001 两个字大小
dw 100 一个字
dw 0
data ends
mov ax,data
mov ds,ax//取段地址
mov ax,ds:[0]//低位
mov dx,ds:[2]
div word ptr ds:[4];dw 100的位置
mov ds:[6],ax//商存在ds:[6] ax;存商,ds存余数只是规定的运算规则
用dup设置内存空间
dup和db、dw、dd等数据定义伪指令配合使用,用来实现数据的重复
例如:db 3 dup(0) 定义三个字节,值均为0
语法糖
流程转移与子程序
转移综述
有时需要改变程序的执行流程
可以控制CPU执行内存中某处代码的指令
转移指令分类:
- 段内转移:只修改IP,如jmp ax
- 段间转移:同时修改CS和IP,如jmp 1000:0
IP修改的范围:
- 段内短转移:IP范围:-128到127(8位)
- 段内近转移:IP修改范围:-32768到32767
按转移指令:
- 无条件转移指令 JMP
- 条件转移指令 jcxz CX寄存器的值是否为zero
- 循环指令 loop
- 过程
- 中断
操作符offset
用操作符offset取得标号的偏移地址 | 格式:offset 标号
assume cs:codesg
codesg segment
s: mov ax,bx
mov si,offset s;存到si
mov di,offset s0
mov ax,cs:[si];取出si,放到ax中
mov cs:[di],ax;ax的内容存到di中
s0: nop;一字节,仅占位用
nop
codesg ends
ends
jmp指令
jmp立即数在机器指令中有所体现
jmp short 的机器指令中包含的是跳转到指令的相对位置,而不是转移的目标地址(下一指令的偏移量)
jmp 标号,jmp 寄存器,jmp 内存单元
jcxz指令
jcxz 标号
如果(cx)==0,转移到标号处执行;反之,程序向下执行
讲了loop指令 位移正负均可
call ret指令
ret,retf 仅IP和CS:IP
call和ret的组合使用
mul指令
mov al,100
mov bl,10
mul bl
结果:(ax)=1000
汇编语言的模块化程序设计
函数的参数和结果的传递问题
用寄存器、内存单元、栈传递参数
寄存器的冲突问题
要听懂倍速还是要慢一点
标志寄存器
SF:补码 负数取反加一
CF:记录运算结果最高有效位向更高位的进位值或借位值
OF:有符号数的溢出
带进借位的加减法
abc带进位加减法
(ax)=(ax)+(bx)+CF
mov al,98h
add al,al
结果(ax)+CF=30H+1=31h [98h+98h==130h 最前面的1舍去]
sbb减法
cmp与条件转移指令
检测比较结果的条件转移指令
jxxx系列指令和cmp指令配合实现高级语言的if语句
条件转移指令应用
统计数值为8的字节的个数
jne next 或 je ok
DF标志和串传送指令
DF=0递增 cld指令clear
DF=1递减 std指令setup
movsb和movsw :inc si,inc di同步递增或递减字节/字长的si、di
rep根据cx的值,重复执行后面的指令
中断及外部设备操作
移位操作
逻辑左移、循环左移、算数左移、带进位循环左移
操作显存数据
显示缓冲区
描述内存单元的标号
已经不理解什么是标号了
数据的直接定址表
查表的方法解决问题
坏了,听不懂(代码讲解部分)
三角函数表
代码的直接定址表
中断及其处理
内中断:CPU内部发生的事件引起的中断
外中断:外部设备发生的事件引起的中断
编制中断处理程序
编写一个除数为0的中断处理程序
单步中断
单步中断与调试
TF陷阱标志 Trap flag
IF中断标志 Interrupt flag 用于实现原语
由int指令引发的中断
汇编语言实验13(1) int 7ch 中断例程-CSDN博客
中断处理程序
- 保存用到的寄存器push
- 处理中断
- 恢复用到的寄存器pop
- 用iret指令返回
BIOS和DOS中断处理
BIOS中断 设置显示XX属性的字符,有点像库函数
端口的读写
端口对应与外设的控制器
操作CMOS RAM芯片
视频的PPT不如书好理解、能自行把握节奏,想到:PPT的目的是为了说服,文档能更好地帮助理解
外设连接与中断
外中断
可屏蔽中断 IF=0不响应中断
不可屏蔽中断
PC机键盘的处理过程
键盘状态字节 例如记录Capslock
- 键盘产生扫描码
- 扫描码送入60H端口
- 引发9号中断
- CPU执行int 9中断例程,处理键盘输入
定制键盘输入处理
ESC的保存、设置中断例程入口听不懂,最后讲了总体的大概懂了
保留原有程序,编写ESC变色程序,结束后恢复到原有程序
改写中断例程的方法
安装一个新的int 9中断例程,中断例程常驻内存,永久改变
原有和新的的int 9中断例程 地址保存在0:200单元处和0:204
用中断响应外设
应用:字符串的输入处理
设计一个基本的字符串输入程序
呵呵,有点数据结构与算法的感觉
实现字符栈的入栈出栈和显示
磁盘读写
感觉不重要,碎,自己只是学习帮助理解底层知识,不看了
让计算机唱歌
微机原理与接口技术,突然感觉学校的课程真的很枯燥死板
最后一讲让计算机唱歌,无聊,不过一想,可以设置开机时唱歌哈哈,不过应该设置里就有吧
哈哈老师挺幽默
最后的1/3自己快进着看完了,完结撒花