汇编引导区和测试

LBA_ADDR	equ 250
section bootload align=16 vstart=0x7c00
start:
	
	mov ax, 0
	mov ss, ax
	mov sp, ax
	
	mov ax, [cs:phy_addr]
	mov dx, [cs:phy_addr + 2]
	mov bx, 16
	div bx
	
	mov ds, ax
	mov es, ax
	
	push 0xe0
	push 0
	push 0
	push LBA_ADDR 
	push 0x01
	
	xor bx, bx
	call _readHd
	
	;jmp   showTest   ;本句话可以测试是否先从硬盘的250扇区开始的用户读到内存地址0x10000
	
	;接下来准备设置地址0x10000后面用户程序的各种段的地址
	
	;用户程序长度
	mov bx, 0
	mov ax, [ds:bx]
	mov dx, [ds:bx+2]
	
	
	;填充开始执行的地址即0x04的两个字节
	;计算原来的地址
	;code段地址
	;mov ax, 4098
	;mov [ds:0x06], ax
	;mov ax, 4098
	;mov [ds:0x0c], ax
	;mov ax, 4101
	;mov [ds:0x10], ax
	;jmp far [0x04]
	
	;计算入口点代码段基址 
	direct:
		mov dx,[0x08]
		mov ax,[0x06]
		call _calc_segment_base
		mov [0x06],ax                   ;回填修正后的入口点代码段基址 
		;开始处理段重定位表
		mov cx,[0x0a]                   ;需要重定位的项目数量
		mov bx,0x0c                     ;重定位表首地址

	realloc:
		mov dx,[bx+0x02]                ;32位地址的高16位 
		mov ax,[bx]
		call _calc_segment_base
		mov [bx],ax                     ;回填段的基址
		add bx,4                        ;下一个重定位项(每项占4个字节) 
		loop realloc 
		
		;jmp far [0x04]
		
	
		;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;用于测试,测试加载到内存0x10000开始后用户程序地址
		mov ax, 0xb800
		mov es, ax
		mov ax,[cs:number]
        
        ;计算各个数位
        mov bx,ax
        mov cx,5                      ;循环次数 
        mov si,10                     ;除数 
		mov ax, [ds:0x12]
	digit: 
		xor dx,dx
		div si
		mov [bx],dl                   ;保存数位
		inc bx 
		loop digit

		;显示各个数位
		mov bx,[cs:number]
		mov si,4         
		xor di, di
	show:
		mov al,[bx+si]
		add al,0x30
		mov ah,0x04
		mov [es:di],ax
		add di,2
		dec si
		jns show

		mov word [es:di],0x0744

	jmp near $
	
	;-------------------------------------------------------------------------------
	_calc_segment_base:                 ;计算16位段地址 ;输入:DX:AX=32位物理地址 ;返回:AX=16位段基地址 
		push dx                          

		add ax,[cs:phy_addr]
		adc dx,[cs:phy_addr + 0x02]
		shr ax,4
		ror dx,4
		and dx,0xf000
		or ax,dx

		pop dx
		ret
		
	;@showTest:
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;mov cx, 512
	;xor si, si
	;xor di, di
	
	;mov ax, 0xb800
	;mov es, ax
	
	;@showStr:
	;	mov al, [ds:si]
	;	mov [es:di], al
	;	inc si
	;	inc di
	;	mov byte [es:di], 0x07
	;	inc di
	;	loop @showStr
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	_readHd:
		push bp
		mov bp, sp
		
		mov dx, 0x1f2
		mov al, [bp+4]
		out dx, al
		
		mov dx, 0x1f3
		mov al, [bp+6]
		out dx, al
		
		mov dx, 0x1f4
		mov al, [bp+8]
		out dx, al
		
		mov dx, 0x1f5
		mov al, [bp+10]
		out dx, al
		
		mov dx, 0x1f6
		mov al, [bp+12]
		out dx, al
		
		mov dx, 0x1f7
		mov al, 0x20
		out dx, al
		
		@wait:
			in al, dx
			and al, 0x88
			cmp al, 0x08
			jnz @wait
		
		mov cx, 512
		mov dx, 0x1f0
		@readHd:
			in al, dx
			mov [bx], al
			inc bx
			loop @readHd
			
		pop bp
		ret
		
	phy_addr dd 0x10000
	number db 0,0,0,0,0,0,0
	times 510 - ($ - $$) db 0
	dw 0xaa55
	
	
	
	section header align=16 vstart=0
	prog_length dd prog_end 					;0x00
	
	code_entry	dw start						;0x04
				dd section.code.start			;0x06
				
	table_size  dw (header_end - codeSegAddr)/4	;0x0a
		
	codeSegAddr dd section.code.start			;0x0c
	dataSegAddr dd section.data.start			;0x10
	
	header_end:
	
;用户程序	
section code align=16 vstart=0
	start:
		mov ax, [dataSegAddr]
		mov ds, ax
		
		mov ax, 0xb800
		mov es, ax
		mov si, 0
		mov di, 0
		mov bx, szInfor
		mov cx, data_end - szInfor
		
		@ShowStr:
			mov al, [ds:si+bx]
			mov [es:di], al
			inc si
			inc di
			mov byte [es:di], 0x07
			inc di
			loop @ShowStr
	@Hlt:
		hlt 
		jmp @Hlt
		
section data align=16 vstart=0
	szInfor db "Now we are in user space Fuck!"
	data_end:
	
section trail align=16
	prog_end:

你可能感兴趣的:(汇编引导区和测试)