Serchio Opublikowano 12 Czerwca 2009 Zgłoś Opublikowano 12 Czerwca 2009 (edytowane) 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 12 Czerwca 2009 przez Serchio Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
mangado Opublikowano 10 Września 2009 Zgłoś Opublikowano 10 Września 2009 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 Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
mangado Opublikowano 11 Września 2009 Zgłoś Opublikowano 11 Września 2009 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] Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...
Serchio Opublikowano 23 Września 2009 Zgłoś Opublikowano 23 Września 2009 Dzięki za odpowiedź, w końcu po ciężkich bojach udało mi się coś zdziałać, ale Twoje rozumowanie jest jak najbardziej poprawne - w taki właśnie sposób rozwiązałem zadanie :) Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach Więcej opcji udostępniania...