第2天 汇编语言学习与Makefile入门
2019.12.28-2019.12.29
1. helloos.nas节选详解
-
helloos.nas
; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址 ; 以下的记述用于标准的FAT12格式的软盘 JMP entry DB 0x90 ---(中略)--- ; 程序核心 entry: ; 0x7c50 MOV AX,0 ; 初始化寄存器 MOV SS,AX MOV SP,0x7c00 MOV DS,AX MOV ES,AX MOV SI,msg putloop: MOV AL,[SI] ADD SI,1 ; 给SI加1 CMP AL,0 JE fin MOV AH,0x0e ; 显示一个文字 MOV BX,15 ; 指定字符颜色 INT 0x10 ; 调用先看BIOS JMP putloop fin: HLT ; 让CPU停止,等待指令 JMP fin ; 无限循环 msg: ; 0x7c74 DB 0x0a, 0x0a ; 换行2次 DB "hello, world" DB 0x0a ; 换行 DB 0
-
ORG指令:这个指令会告诉nask,再开始执行的时候,把这些机器语言指令装载到内存的哪个地址。如果没有它,有几个指令就不能正确地被翻译和执行。另外,有了这条指令的话,美元符
$
的含义也随之变化,它不再是输出文件的第几个字节,而是代表将要读入的内存地址。
ORG指令源自英文origin。它会告诉nask,程序要从指定的这个地址开始,也就是要把程序装载到内存中指定的地址。
这里指定的地址为0x7c00
。这是规定,原因和1+1为什么等于2一样。 -
JMP指令:来源于英文jump,相当于C语言的goto语句。
-
entry:这是标签的声明,用于指定JMP指令的跳转目的地等。
-
MOV指令:最常用的指令。功能:赋值。虽然简单,但是要是完全理解了MOV指令,汇编语言也就理解了一大半了。
MOV AX,0
相当于AX=0
;MOV SS,AX
相当于SS=AX
。后者赋值给前者。- MOV指令的另一种理解是COPY。执行
MOV SS,AX
以后AX
的值并没有空,还是保持原来的值不变。
-
CPU中的寄存器
- AX:accumulator,累加寄存器
- CX:counter,计数寄存器
- DX:data,数据寄存器
- BX:base,基址寄存器
- SP:stack pointer,栈指针寄存器
- BP:base pointer,基址指针寄存器
- SI:source index,源变址寄存器
- DI:destination index,目的变址寄存器
以上寄存器都是16位寄存器,因此可以存储16位的二进制数。
CX是为方便计数而设计的;BX适合作为计算内存地址的基点。
另外,CPU中还有8个8位寄存器:- AL:累加寄存器低位(accumulation low)
- CL:计数寄存器低位(counter low)
- DL:数据寄存器低位(data low)
- BL:基址寄存器低位(base low)
- AH: 累加寄存器高位(accumulation high)
- CH:计数寄存器高位(counter high)
- DH:数据寄存器高位(data high)
- BH: 基址寄存器高位(base high)
AX寄存器有16位,其中0~7位的低8位称为
AL
,8~15位的高8位称为AH
因此,CPU还是那个CPU,依然只能存储16个字节。CPU的存储能力真的是太有限了。为什么BP、SP、SI和DI没有分H和L呢?
比如,要分别取SI的高8位和低8位。嘤特尔的设计人员是这样想的:先用>MOV AX,SI
,将SI
赋值到AX
里面去,再用AH和AL取值。32位CPU寄存器
- EAX
- ECX
- EDX
- EBX
- ESP
- EBP
- ESI
- EDI
EAX的低16位是AX,高16位没有名字也没有寄存器编号。因此,我们可以把EAX当做2个16位寄存器来用,但是只有低16位用起来方便;我们想要用高16位的话,需要使用移位命令,将高16位移到低16位使用。
32位CPU的存储能力也只有32字节,同样小的可怜。
对于64位CPU,我们这次不使用64位模式。段寄存器
ES: 附加段寄存器(extra segment)
CS: 代码段寄存器(code segment)
-