Skip to content

day3进入32位系统以及C语言

assembly
; haribote-ipl
; TAB=4

		ORG		0x7c00			; 程序的地址

; 

		JMP		entry
		DB		0x90
		DB		"HARIBOTE"		
		DW		512				
		DB		1				
		DW		1				
		DB		2				
		DW		224				
		DW		2880		
		DB		0xf0		
		DW		9		
		DW		18			
		DW		2			
		DD		0			
		DD		2880		
		DB		0,0,0x29	
		DD		0xffffffff	
		DB		"HARIBOTEOS "	
		DB		"FAT12   "	
		RESB	18			

; 

entry:
		MOV		AX,0			; 初始化寄存器
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX			;设置段地址

; 

		MOV		AX,0x0820		
		MOV		ES,AX			;设置读取后的位置
		MOV		CH,0			; 设置柱面
		MOV		DH,0			; 设置柱头
		MOV		CL,2			; 设置扇面

		MOV		AH,0x02			; AH=0x02 : 读盘
		MOV		AL,1			; 1个扇区
		MOV		BX,0			;设置读取文件存放的位置
		MOV		DL,0x00			; A驱动器
		INT		0x13			; 调用BIOS
		JC		error			; 如果进位标志为1, 就进行跳转

; 这里是成功之后的死循环

fin:
		HLT						
		JMP		fin			
; 打印错误信息
error:
		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI,1		
		CMP		AL,0
		JE		fin
		MOV		AH,0x0e			 
		MOV		BX,15		
		INT		0x10			
		JMP		putloop
msg:
		DB		0x0a, 0x0a	
		DB		"load error"
		DB		0x0a		
		DB		0

		RESB	0x7dfe-$		
		DB		0x55, 0xaa

INT0x13: AH=0x02读盘, AH=0x03写盘, AH=0x04校验, AH=0x0c巡道, AL=处理的扇区数, CH=柱面号, DH=磁头号, DL=驱动器号, ES:BX=缓冲地址, 校验以及寻道的时候不需要, 返回值FLACS:CF=0, 没有错误AH=0, FLAGCS:CF=1, 有错误, 存入AH

设置的是软盘的读取, 一个软盘有80个柱面, 2个磁头, 18个扇区

BX设置的是读取的文件存放的位置, 只有16位, 使用的时候可以使用MOV AL,[ES:BX], 实际上是ES*16+BX, 达到1M的大小

这里设置ES=0x8020, 原因是0x8000~0x81ff的位置是启动区的, 之后的内存是随意使用的

0x7c00到0x7dff的位置是启动区, 之后0x7e00到0x9fbff没有规定

在使用的时候, 需要注意段寄存器,DS, 在不表示的情况下一般可以省略, MOV CX,[SI]实际上是MOV AL,[DS:SI]

改进一次

assembly
; 初始化寄存器

entry:
		MOV		AX,0			; レジスタ初期化
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX

; 读磁盘

		MOV		AX,0x0820
		MOV		ES,AX
		MOV		CH,0			; 柱面0
		MOV		DH,0			; 磁头0
		MOV		CL,2			; 扇区0

		MOV		SI,0			; 记录失败的次数
retry:
		MOV		AH,0x02			
		MOV		AL,1			
		MOV		BX,0
		MOV		DL,0x00			
		INT		0x13			
		JNC		fin				
		ADD		SI,1			; SI加一
		CMP		SI,5			; SI比较
		JAE		error			; SI >= 5 出错
		MOV		AH,0x00
		MOV		DL,0x00			; 
		INT		0x13			; 设置系统复位
		JMP		retry

读取到18

assembly
; 读磁盘

		MOV		AX,0x0820
		MOV		ES,AX
		MOV		CH,0			
		MOV		DH,0			
		MOV		CL,2			
readloop:
		MOV		SI,0			
retry:
		MOV		AH,0x02			; AH=0x02 : 读取
		MOV		AL,1			; 一个扇区
		MOV		BX,0
		MOV		DL,0x00			; A驱动器
		INT		0x13			; 调用BIOS
		JNC		next			; 出错跳到next
		ADD		SI,1			; SIに1を足す
		CMP		SI,5			; SIと5を比較
		JAE		error			; SI >= 5 だったらerrorへ
		MOV		AH,0x00
		MOV		DL,0x00			; Aドライブ
		INT		0x13			; ドライブのリセット
		JMP		retry
next:
		MOV		AX,ES			; 内存地址后移
		ADD		AX,0x0020		; 相当于加上0x200
		MOV		ES,AX			; 写入ES
		ADD		CL,1			; CL加1
		CMP		CL,18			; CL与18比较
		JBE		readloop		; CL <= 18 继续读取
  • 增加读取到反面
assembly
CYLS	EQU		10				; 相当于define
.....
; 

		MOV		AX,0x0820
		MOV		ES,AX
		MOV		CH,0			; シリンダ0
		MOV		DH,0			; ヘッド0
		MOV		CL,2			; セクタ2
readloop:
		MOV		SI,0			; 失敗回数を数えるレジスタ
retry:
		MOV		AH,0x02			
		MOV		AL,1			
		MOV		BX,0
		MOV		DL,0x00			
		INT		0x13			
		JNC		next			
		ADD		SI,1			
		CMP		SI,5		
		JAE		error		
		MOV		AH,0x00
		MOV		DL,0x00		
		INT		0x13			; ドライブのリセット
		JMP		retry
next:
		MOV		AX,ES			
		ADD		AX,0x0020
		MOV		ES,AX			
		ADD		CL,1			
		CMP		CL,18			
		JBE		readloop		
		MOV		CL,1			; 归零
		ADD		DH,1			; 更换柱头, 加一, 第二次加一之后会进入后面的程序
		CMP		DH,2			;进行比较
		JB		readloop		; DH<2
		MOV		DH,0			; 设置柱头归零
		ADD		CH,1			; 设置柱面加一
		CMP		CH,CYLS
		JB		readloop		; CH < CYLS だったらreadloopへ

C0-H0-S18到C0-H1-S1再到C9-H1-S18

最初的180KB存入内存

  • 添加其他文件
assembly
fin:
		HLT
		JMP		fin
makefile
TOOLPATH = ../z_tools/
MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
COPY     = copy
DEL      = del

# デフォルト動作

default :
	$(MAKE) img

# ファイル生成規則

ipl.bin : ipl.nas Makefile
	$(NASK) ipl.nas ipl.bin ipl.lst

haribote.sys : haribote.nas Makefile
	$(NASK) haribote.nas haribote.sys haribote.lst

haribote.img : ipl.bin haribote.sys Makefile
	$(EDIMG)   imgin:../z_tools/fdimg0at.tek \
		wbinimg src:ipl.bin len:512 from:0 to:0 \
		copy from:haribote.sys to:@: \
		imgout:haribote.img

# コマンド

img :
	$(MAKE) haribote.img

run :
	$(MAKE) img
	$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
	$(MAKE) -C ../z_tools/qemu

install :
	$(MAKE) img
	$(IMGTOL) w a: haribote.img

clean :
	-$(DEL) ipl.bin
	-$(DEL) ipl.lst
	-$(DEL) haribote.sys
	-$(DEL) haribote.lst

src_only :
	$(MAKE) clean
	-$(DEL) haribote.img

软盘上在0x002600设置的是文件名的位置, 0x004200的位置是文件的内容

程序的调用: 软盘的程序被复制到0x8000之后, 程序在0xc200

assembly
; haribote-os
; TAB=4

		ORG		0xc200			; 偙偺僾儘僌儔儉偑偳偙偵撉傒崬傑傟傞偺偐

		MOV		AL,0x13			; VGA僌儔僼傿僢僋僗丄320x200x8bit僇儔乕
		MOV		AH,0x00
		INT		0x10
fin:
		HLT
		JMP		fin

这里可以设置显示的模式, AH=0x00, AL=模式, 0x30: 16色模式, 0x12VGA图形模式640x480x4, 0x12VGA图形模式320x200x8, 调色板模式, 0x6a扩展VGA模式800x600x4

assembly
		MOV		[0x0ff0],CH		; 记录读取的扇区数
		JMP		0xc200			; 跳转到程序

进入32位

16位的机器码在32位时候不能使用, 32位可以使用的内存变大, 而且可以使用CPU的自我保护模式但是不能使用BIOS

assembly
; haribote-os
; TAB=4

; BOOT_INFO娭學
CYLS	EQU		0x0ff0			; 设定启动区
LEDS	EQU		0x0ff1
VMODE	EQU		0x0ff2			; 设定颜色的数目
SCRNX	EQU		0x0ff4			; 分辨率x
SCRNY	EQU		0x0ff6			; Y
VRAM	EQU		0x0ff8			; 图像缓冲区的位置

		ORG		0xc200			; 程序的保存地址

		MOV		AL,0x13			; 设置显卡
		MOV		AH,0x00
		INT		0x10
		MOV		BYTE [VMODE],8	; 记录画面模式
		MOV		WORD [SCRNX],320
		MOV		WORD [SCRNY],200
		MOV		DWORD [VRAM],0x000a0000

; 使用BIOS获取键盘上的各种LED的状态

		MOV		AH,0x02
		INT		0x16 			; keyboard BIOS
		MOV		[LEDS],AL		; 保存状态

fin:
		HLT
		JMP		fin

不同模式下的VRAM的位置不同

正式进入C语言

assembly
; haribote-os boot asm
; TAB=4

BOTPAK	EQU		0x00280000		; 设置地址
DSKCAC	EQU		0x00100000		; 
DSKCAC0	EQU		0x00008000		; 

; BOOT_INFO记录
CYLS	EQU		0x0ff0			
LEDS	EQU		0x0ff1
VMODE	EQU		0x0ff2			
SCRNX	EQU		0x0ff4			
SCRNY	EQU		0x0ff6			
VRAM	EQU		0x0ff8			

		ORG		0xc200			

; 设置显示

		MOV		AL,0x13			; VGA僌儔僼傿僢僋僗丄320x200x8bit僇儔乕
		MOV		AH,0x00
		INT		0x10
		MOV		BYTE [VMODE],8	; 夋柺儌乕僪傪儊儌偡傞乮C尵岅偑嶲徠偡傞乯
		MOV		WORD [SCRNX],320
		MOV		WORD [SCRNY],200
		MOV		DWORD [VRAM],0x000a0000

; 读取键盘

		MOV		AH,0x02
		INT		0x16 			; keyboard BIOS
		MOV		[LEDS],AL



		MOV		AL,0xff
		OUT		0x21,AL
		NOP						; 
		OUT		0xa1,AL

		CLI						; 

; 

		CALL	waitkbdout
		MOV		AL,0xd1
		OUT		0x64,AL
		CALL	waitkbdout
		MOV		AL,0xdf			; enable A20
		OUT		0x60,AL
		CALL	waitkbdout

; 

[INSTRSET "i486p"]				; 486

		LGDT	[GDTR0]			; 
		MOV		EAX,CR0
		AND		EAX,0x7fffffff	; 
		OR		EAX,0x00000001	; 
		MOV		CR0,EAX
		JMP		pipelineflush
pipelineflush:
		MOV		AX,1*8			;  
		MOV		DS,AX
		MOV		ES,AX
		MOV		FS,AX
		MOV		GS,AX
		MOV		SS,AX

; bootpack偺揮憲

		MOV		ESI,bootpack	; 
		MOV		EDI,BOTPAK		; 
		MOV		ECX,512*1024/4
		CALL	memcpy

; 

; 

		MOV		ESI,0x7c00		; 
		MOV		EDI,DSKCAC		; 
		MOV		ECX,512/4
		CALL	memcpy

; 

		MOV		ESI,DSKCAC0+512	; 
		MOV		EDI,DSKCAC+512	; 
		MOV		ECX,0
		MOV		CL,BYTE [CYLS]
		IMUL	ECX,512*18*2/4	; 
		SUB		ECX,512/4		; 
		CALL	memcpy

; 
;	

; 

		MOV		EBX,BOTPAK
		MOV		ECX,[EBX+16]
		ADD		ECX,3			; 
		SHR		ECX,2			; 
		JZ		skip			; 
		MOV		ESI,[EBX+20]	; 
		ADD		ESI,EBX
		MOV		EDI,[EBX+12]	; 
		CALL	memcpy
skip:
		MOV		ESP,[EBX+12]	; 
		JMP		DWORD 2*8:0x0000001b

waitkbdout:
		IN		 AL,0x64
		AND		 AL,0x02
		JNZ		waitkbdout		; 
		RET

memcpy:
		MOV		EAX,[ESI]
		ADD		ESI,4
		MOV		[EDI],EAX
		ADD		EDI,4
		SUB		ECX,1
		JNZ		memcpy			; 
		RET
; 

		ALIGNB	16
GDT0:
		RESB	8				; 
		DW		0xffff,0x0000,0x9200,0x00cf	; 
		DW		0xffff,0x0000,0x9a28,0x0047	; 

		DW		0
GDTR0:
		DW		8*3-1
		DD		GDT0

		ALIGNB	16
bootpack:
c
void HariMain(void)
{

fin:
	/* C语言不能使用HLT, 这里是一个循环 */
	goto fin;

}

编译

  1. cc1.exe从bootpack.c生成bootpack.gas, 使用C编译器, 转换为汇编
  2. gas2nask.exe从bootpack.gas生成bootpack.nas, 机器语言
  3. nask.exe从bootpack.nas生成bootpack.obj, 目标文件, 是一种特殊的机器语言文件, 需要链接使用
  4. 使用obj2bim.exe从bootpack.obj生成bootpack.bim, 二进制镜像文件, 需要针对不同的操作系统加上头文件以及压缩等
  5. 使用bim2hrb.exe从bootpack.bim生成bootpack.hrb为机器语言
  6. 最后使用copy把bootpack.hrb和bootpack.hrb文件粘贴起来, 生成haribote.sys
makefile
TOOLPATH = ../z_tools/
INCPATH  = ../z_tools/haribote/

MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
RULEFILE = $(TOOLPATH)haribote/haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
COPY     = copy
DEL      = del

# 

default :
	$(MAKE) img

# 生成文件

ipl10.bin : ipl10.nas Makefile
	$(NASK) ipl10.nas ipl10.bin ipl10.lst

asmhead.bin : asmhead.nas Makefile
	$(NASK) asmhead.nas asmhead.bin asmhead.lst

bootpack.gas : bootpack.c Makefile
	$(CC1) -o bootpack.gas bootpack.c

bootpack.nas : bootpack.gas Makefile
	$(GAS2NASK) bootpack.gas bootpack.nas

bootpack.obj : bootpack.nas Makefile
	$(NASK) bootpack.nas bootpack.obj bootpack.lst

naskfunc.obj : naskfunc.nas Makefile
	$(NASK) naskfunc.nas naskfunc.obj naskfunc.lst

bootpack.bim : bootpack.obj naskfunc.obj Makefile
	$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
		bootpack.obj naskfunc.obj
# 3MB+64KB=3136KB

bootpack.hrb : bootpack.bim Makefile
	$(BIM2HRB) bootpack.bim bootpack.hrb 0

haribote.sys : asmhead.bin bootpack.hrb Makefile
	copy /B asmhead.bin+bootpack.hrb haribote.sys

haribote.img : ipl10.bin haribote.sys Makefile
	$(EDIMG)   imgin:../z_tools/fdimg0at.tek \
		wbinimg src:ipl10.bin len:512 from:0 to:0 \
		copy from:haribote.sys to:@: \
		imgout:haribote.img

# コマンド

img :
	$(MAKE) haribote.img

run :
	$(MAKE) img
	$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
	$(MAKE) -C ../z_tools/qemu

install :
	$(MAKE) img
	$(IMGTOL) w a: haribote.img

clean :
	-$(DEL) *.bin
	-$(DEL) *.lst
	-$(DEL) *.gas
	-$(DEL) *.obj
	-$(DEL) bootpack.nas
	-$(DEL) bootpack.map
	-$(DEL) bootpack.bim
	-$(DEL) bootpack.hrb
	-$(DEL) haribote.sys

src_only :
	$(MAKE) clean
	-$(DEL) haribote.img

实现HLT

assembly
; naskfunc
; TAB=4

[FORMAT "WCOFF"]				; 文件格式
[BITS 32]						; 32位操作系


; 制作目标文件的名字

[FILE "naskfunc.nas"]			; 此文件名

		GLOBAL	_io_hlt			; 函数名


; 

[SECTION .text]		; 目?文件中写入?些再?行

_io_hlt:	; void io_hlt(void);
		HLT
		RET		; 相当于return

JiaoOS

  • 移植OLED
  • 触摸屏
  • LED
  • 串口

出现问题, 没有定义

  • 使用__inline在C99模式下前面加static
  • 文件没有添加
c
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "bsp_ili9341_lcd.h"
#include "bsp_xpt2046_lcd.h"
void Hareware_Init(void);


int main()
{
	int i;
	Hareware_Init();
	while(1){
	XPT2046_TouchEvenHandler();
		
		for(i=0;i<10000;i++);
		
	}
	
}

void Hareware_Init(void)
{
	//初始化串口
	USART_Config();
	LED_GPIO_Config();
	printf("你好\n");
	//初始化屏幕
	ILI9341_Init();
	printf("初始化屏幕\n");
	ILI9341_Clear(0, 0, ILI9341_LESS_PIXEL, ILI9341_MORE_PIXEL);
	
	//从FLASH里获取校正参数,若FLASH无参数,则使用模式3进行校正
	Calibrate_or_Get_TouchParaWithFlash(3,0);
	XPT2046_Init();
	printf("初始化触摸屏\n");

}