Skocz do zawartości
Serchio

[assembler]adresowanie W Trybie Chronionym Intel 386

Rekomendowane odpowiedzi

Witam,

 

Siedzę od 2 dni nad problemem adresowania w trybie chronionym procesora Intel 386 :/

 

Mam do wykonania zadanie:

Początek bufora strony tekstowej w trybie PM znajdował się pod offsetem logicznym = 0x10000* + 0xB8000. Należy utworzyć/zmodyfikować istniejącą strukturę deskryptora aby w wyniku następującej modyfikacji instrukcji:

 

z <<<<< add edi,0b8000h ; physical address of text screen

na >>>>> add edi,0

 

znajdującej się w procedurze write_msg_pm zachować pierwotny efekt działania programu. W procedurze write_msg_pm dopuszcza się jedynie modyfikację linii:

mov ax,core32_idx ; in protected mode, we have to use

Kod programu:

;****************************************************************************;* this file contains a simple PM switcher to illustrate the examples shown *;* in PMTUT.TXT. Please do not spread this file without PMTUT.TXT!		  *;* USE AT YOUR OWN RISK!							*;*										*;* Written by Till Gerken							*;*	(Internet: tig@ngo.ol.ni.schule.de)					*;****************************************************************************idealP386;----------------------------------------------------------------------------STACK16_SIZE	=	100h; stack size for Real ModeSTACK32_SIZE	=	100h; stack size for Protected Modestruc segment_descriptor  seg_length0_15	dw	?; low word of the segment length  base_addr0_15		dw	?; low word of base address  base_addr16_23	db	?; low byte of high word of base addr.  flags			db	?; segment type and misc. flags  access		db	?; highest nibble of segment length				; and access flags  base_addr24_31	db	?; highest byte of base addressends segment_descriptorstruc interrupt_descriptor  offset0_15		dw	?; low word of handler offset  selector0_15		dw	?; segment selector  zero_byte		db	0; unused in this descriptor format  flags			db	?; flag-byte  offset16_31		dw	?; high-word of handler offsetends interrupt_descriptor;****************************************************************************segment code16 para public use16; this segment contains all 16-bitassume cs:code16, ds:code16; code and data stuff;----------------------------------------------------------------------------stack16		db	STACK16_SIZE dup (?); 16-bit Real Mode stacklabel	stack16_end	wordidt_real	dw	3ffh,0,0; Real Mode IDT;----------------------------------------------------------------------------; quick and dirty exit; In:	DS:DX - pointer to '$' terminated exit message; Out:	Difficult to say, the function never returns :)proc	err16exit	mov	ah,9; select DOS' print string function	int	21h; print the msg	mov	ax,4cffh; exit with exit-code 0ffh	int	21h; good bye...endp	err16exit;----------------------------------------------------------------------------; checks if the processor is at least a 80386no386e		db	'Sorry, at least a 80386 is needed!',13,10,'$'proc	check_processor	pushf; save flags for later	xor	ah,ah; clear high byte	push	ax; push AX on the stack	popf; pop this value into the flag register	pushf; push flags on the stack	pop	ax; ...and get flags into AX	and	ah,0f0h; try to set the high nibble	cmp	ah,0f0h; on a 80386, the high nibble can never be 0f0h	je	no386	mov	ah,70h; now try to set NT and IOPL	push	ax	popf	pushf	pop	ax	and	ah,70h; if they couldn't be modified, no 386 is installed	jz	no386	popf; restore flags	ret; and returnno386:	mov	dx,offset no386e; if there is no 386, exit with error msg	jmp	err16exitendp	check_processor;----------------------------------------------------------------------------; checks if we are running in Real Modenrme		db	'You are currently running in V86 mode!',13,10,'$'proc	check_mode	mov	eax,cr0; get CR0 into EAX	and	al,1; check if PM bit is set	jnz	not_real_mode; it is set, so exit	ret; nope, it isn't, Real Mode is good!not_real_mode:	mov	dx,offset nrme; exit with msg	jmp	err16exitendp	check_mode;----------------------------------------------------------------------------; this procedure just writes a zero-terminated message to the screen; format: word x, word y, attribute byte, string, 0; In:	DS:SI - pointer to format stringproc	write_msg	push	ax si di es	mov	ax,0b800h; segment of text screen	mov	es,ax; get it to ES	mov	ax,[si+2]; get Y position	mov	di,160	mul	di	add	ax,[si]	mov	di,ax	mov	ah,[si+4]; get attribute byte	add	si,5write_loop_pm:	mov	al,[si]	or	al,al; end of string?	jz	loop_end_pm	inc	si	mov	[es:di],ax	inc	di	inc	di	jmp	write_loop_pmloop_end_pm:	pop	es di si ax	retendp	write_msg;----------------------------------------------------------------------------; main procedure, this is the entry pointrm_msg		db	0,0,0,0,1fh,'Now in Real Mode - press a key to switch '		db	'to Protected Mode!',0rm2_msg		db	0,0,3,0,1fh,'Back in Real Mode - press a key to return '		db	'to DOS!',0start16:	mov	ax,cs; load code-segment into DS and ES	mov	ds,ax	mov	es,ax	cli; better disable interrupts while setting	mov	ss,ax; SS and SP	mov	sp,offset stack16_end	sti; now interrupts don't disturb any more	call	check_processor; check if we are running on at least a 80386	call	check_mode; check if we are running in Real Mode	mov	ax,code16; get code segment into AX	movzx	eax,ax; clear high word	shl	eax,4; make a physical address	mov	[ds:code16_descriptor.base_addr0_15],ax; store it in the dscr	mov	[ds:data16_descriptor.base_addr0_15],ax	shr	eax,8	mov	[ds:code16_descriptor.base_addr16_23],ah	mov	[ds:data16_descriptor.base_addr16_23],ah		mov	ax,code32; get 32-bit code segment into AX	movzx	eax,ax; clear high word	shl	eax,4; make a physical address	mov	[ds:code32_descriptor.base_addr0_15],ax; store it in the dscr	mov	[ds:data32_descriptor.base_addr0_15],ax	shr	eax,8	mov	[ds:code32_descriptor.base_addr16_23],ah	mov	[ds:data32_descriptor.base_addr16_23],ah	mov	ax,code32; get 32-bit code segment into AX	movzx	eax,ax; clear high word	shl	eax,4; make a physical address	add	eax,offset dummy_descriptor; calculate physical address of GDT	mov	[dword ds:gdt_start+2],eax	mov	ax,code32; get 32-bit code segment into AX	movzx	eax,ax; clear high word	shl	eax,4; make a physical address	add	eax,offset interrupt_0; calculate physical address of IDT	mov	[dword ds:idt_start+2],eax	mov	ax,3; set text mode 3, just used to clear screen	int	10h; do it	mov	si,offset rm_msg; write real mode message to screen	call	write_msg	xor	ah,ah	int	16h	cli; disable interrupts	lgdt	[fword ds:global_descriptor_table]; load GDT register	lidt	[fword ds:interrupt_descriptor_table]; load IDT register	mov	eax,cr0; get CR0 into EAX	or	al,1; set Protected Mode bit	mov	cr0,eax; after this we are in Protected Mode!	db	0eah; opcode for far jump (to set CS correctly)	dw	small start32,code32_idxexit16:	; the protected mode code returns here	mov	eax,cr0; get CR0 into EAX	and	al,not 1; clear Protected Mode bit	mov	cr0,eax; after this we are back in Real Mode!	db	0eah	dw	offset flush_ipq,code16flush_ipq:	mov	ax,cs; restore important registers	mov	ss,ax	mov	sp,offset stack16_end	mov	ds,ax	mov	es,ax	lidt	[fword idt_real]	sti; enable interrupts	mov	si,offset rm2_msg; write second message	call	write_msg	xor	ah,ah; wait for a key	int	16h	mov	ax,3; clear screen once again	int	10h	mov	ax,4c00h; everything is okay, we exit with exit-code 0	int	21h; bye...;----------------------------------------------------------------------------ends	code16segment code32 para public use32; this segment contains all 32-bitassume cs:code32, ds:code32; code and data stuffstack32		db	STACK32_SIZE dup (?); 32-bit stacklabel	stack32_end	dword;----------------------------------------------------------------------------label global_descriptor_table fword; here begins the GDTgdt_start	  dw			 gdt_size,0,0; val for GDT regdummy_descriptor  segment_descriptor <0,0,0,0,0,0>code32_descriptor segment_descriptor <0ffffh,0,0,9ah,0cfh,0>; 4GB 32-bit codedata32_descriptor segment_descriptor <0ffffh,0,0,92h,0cfh,0>; 4GB 32-bit datacore32_descriptor segment_descriptor <0ffffh,0,0,92h,0cfh,0>; 4GB 32-bit corecode16_descriptor segment_descriptor <0ffffh,0,0,9ah,0,0> ; 64k 16-bit codedata16_descriptor segment_descriptor <0ffffh,0,0,92h,0,0> ; 64k 16-bit datagdt_size=$-(offset dummy_descriptor)code32_idx	=	08h; offset of 32-bit code segment in GDTdata32_idx	=	10h; offset of 32-bit data segment in GDTcore32_idx	=	18h; offset of 32-bit core segment in GDTcode16_idx	=	20h; offset of 16-bit code segment in GDTdata16_idx	=	28h; offset of 16-bit data segment in GDTlabel interrupt_descriptor_table fword; here begins the IDTidt_start	dw			idt_size,0,0interrupt_0	interrupt_descriptor	<small demo_int,code32_idx,0,8eh,0>idt_size=$-(offset interrupt_0);----------------------------------------------------------------------------start32:; here we start in Protected Mode	mov	ax,data32_idx; load needed registers with the appr.	mov	ss,ax; selectors	mov	esp,offset stack32_end; stack size	mov	ds,ax	mov	es,ax	mov	fs,ax	mov	gs,ax	call	main; now, everything is set up: call main!	db	0eah; far jump opcode; when main returns, get back	dw	offset exit16,0,code16_idx; to the Real Mode code;----------------------------------------------------------------------------; protected mode translation of write_msg; In:	DS:ESI - pointer to format stringproc	write_msg_pm	push	ax esi edi es	mov	ax,core32_idx; in protected mode, we have to use		; core memory to address the screen	mov	es,ax	xor edi,edi	movzx	di,[esi+2]; get Y position	imul	edi,160	add	di,[esi]; add X position	add	di,[esi]	add	edi,0b8000h; physical address of text screen	mov	ah,[esi+4]; get attribute byte	add	esi,5write_loop:	mov	al,[esi]	or	al,al; end of string?	jz	loop_end	inc	esi	mov	[es:edi],ax	inc	edi	inc	edi	jmp	write_looploop_end:	pop	es edi esi ax	retendp	write_msg_pm;----------------------------------------------------------------------------; sample interrupt handlerint_msg		db	0,0,2,0,1fh,'I''m the Interrupt Handler - returning '		db	'now!',0proc	demo_int	mov	esi,offset int_msg	call	write_msg_pm	iretdendp	demo_int;----------------------------------------------------------------------------; main procedure for protected modepm_msg		db	0,0,1,0,1fh,'Now in Protected Mode - calling Interrupt '		db	'Handler!',0main:	mov	esi,offset pm_msg; just put the message...	call	write_msg_pm	int	0; ...call a sample interrupt...	ret	; ...and return;----------------------------------------------------------------------------ends	code32;****************************************************************************end start16

Jeżeli ktoś wie jak to zrobić, to proszę o pomoc. Ewentualnie wskazówki jak mam to zrobić.

 

Pozdrawiam

Serchio

Edytowane przez Serchio

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Tu chodzi o to, żeby adres początku pamięci video nie był 0xB8000 tylko 0.

trzeba ustawic "baze" deskryptora core32, tylko ze ta baza jest poćwiartowana...

 

 

czyli popraw: core32_descriptor segment_descriptor <0ffffh,0,0,92h,0cfh,0>; 4GB 32-bit core

na: core32_descriptor segment_descriptor <0ffffh,8000h,0Bh,92h,0cfh,0>; 4GB 32-bit core

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Aaaa!!!

Jeszcze jedno!

 

W tym Deskryptorze limit jest ustawiony na max! Trzeba to zmienic wystarczy wyzerowac najstarsze 4 bity

 

czyli:

 

core32_descriptor segment_descriptor <0ffffh, 0,0,92h,0cfh,0>; 4GB 32-bit core

core32_descriptor segment_descriptor <0ffffh,8000h,0,92h,0c0h,0>; 4GB 32-bit core

[\code]

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie


×
×
  • Dodaj nową pozycję...