Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

I really could use some help from a seasoned 80386 assembly language programmer

29 views
Skip to first unread message

monah...@gmail.com

unread,
Jan 12, 2013, 11:18:50 PM1/12/13
to
I am putting together an 80386 S-100 bus board and am writing a ROM based monitor to use with the board. See here:-

http://s100computers.com/My%20System%20Pages/80386%20Board/80386%20CPU%20Board.htm

After a steep learning curve using selectors etc. I managed to switch the CPU in and out of protected mode (PM) using a flat 4GB address space and 32 bit registers. It’s so nice not having to worry about segments!

However I am having a real problem getting software interrupts (have not even tried hardware ones yet). The board/software works fine in real mode for both software and 8259A driven hardware interrupts. Can run MSDOS “out of the box” for example.

I won’t use up your time on basic stuff. Here is the core issue/code. I am using the NASM assembler.

First the switch to PM mode. Works fine!
……..
o32 LGDT [dword CS:GdtDesc] ;Initilize GDTR (for GdtDesc, see below)
o32 LIDT [dword CS:IdtDesc] ;Initilize IDTR (for IdtDesc, see below)

MOV EAX,CR0 ;Set to protected mode
OR EAX,1
MOV CR0,EAX ;<---- GOTO PM MODE
JMP $+2 ;Flush
;The CPU is now executing in 16-bit
;protected mode.
;Make a far jump in order to load CS
;with a selector
;to our 32-bit executable code
;descriptor.


o32 JMP dword PM_CS_386:(PM_ROM_BASE+Start32) ;Long JMP to absolute
;start of PM CODE

Start32:

…… All the above code works fine. I have written many monitor type commands that work in PM mode
The problem starts here:-

For initial simplicity I have laid down the PM Interrupt descriptor table starting at 0H in RAM. Filling every entry to point to a simple message:-

PM_INT_TEST:
mov ebx,INT_SIGNON ;Send a signon message
call P_PRINT_STRING

CLD ;Default to direction is up

mov ebx,0 ;IDT starts at 0H in RAM
mov cx,100H ;Fill all (256 or 100H) 80386
;interrupts

p_fill_ints:
mov word [ebx],PM_error_int ;Offset (below) of error routine
mov word [ebx+2],PM_CS_386 ;Protect mode 386 code
mov byte [ebx+4],0
mov byte [ebx+5],10001110B ;P=1 (enable), DPL=0, 01110= 80386
;Interrupt Gate (8EH))
mov word [ebx+6],0 ;Offset 31...16
add ebx,8 ;Point to next int entry
loop p_fill_ints ;Fill in all 256 ebntries

MOV CL,’*’
call P_CO ;Consol output to show we got here.

INT 4 ;<<< To test overflow int

JMP Test_Done ;We are done

PM_error_int: ;Unassigned Interrupt warning
pushad
MOV CL,'@' ;Put an ‘@’ character on screen
call P_CO
popad
iret

<<< PROBLEM >>> ANY INERRUPT NUMBER I USE NEVER ARRIVES AT PM_error_int:
(Seems to go to an non-defined location).

;======================== 80386 DESCRIPTOR TABLES =================

ALIGN 4 ;80386 DESCRIPTOR TABLES

Gdt: DD 0 ;GDT[0]: Null entry, never used.
DD 0
;GDT[1]:Executable, read-only code,
;base address of 0,
;limit of FFFFFh, granularity bit (G)
; set (making the ;limit 4GB)
DW 0FFFFh ;Limit[15..0]
DW 0000h ;Base[15..0]
DB 00h ;Base[23..16]
DB 10011010b ;P(1) DPL(00) S(1) 1 C(0) R(1) A(0)
DB 11001111b ;G(1) D(1) 0 0 Limit[19..16]
DB 00h ;Base[31..24]

;GDT[2]: Writable data segment,
;covering the same
;address space than GDT[1].
DW 0FFFFh ;Limit[15..0]
DW 0000h ;Base[15..0]
DB 00h ;Base[23..16]
DB 10010010b ;P(1) DPL(00) S(1) 0 E(0) W(1) A(0)
DB 11001111b ;G(1) B(1) 0 0 Limit[19..16]
DB 00h ;Base[31..24]

;GDT[3]:Executable, read-only 16 bit
;code, base address
;of 0, limit of FFFFh,
;granularity bit (G) set (making the
;limit 64K)
DW 0FFFFh ;Limit[15..0]
DW 0000h ;Base[15..0]
DB 0Eh ;Base[23..16] (>>>> Note base is @ E000:0H <<<<)
DB 10011010b ;P(1) DPL(00) S(1) 1 C(0) R(1) A(0)
DB 00000000b ;G(0) D(0) 0 0 Limit[19..16]
DB 00h ;Base[31..24]

;GDT[4]: Writable data segment, 16 bit
;code, base ;address of 0, limit of
;FFFFh.
DW 0FFFFh ;Limit[15..0]
DW 0000h ;Base[15..0]
DB 0Eh ;Base[23..16] (>>>> Note base is @ E000:0H <<<<)
DB 10010010b ;P(1) DPL(00) S(1) 0 E(0) W(1) A(0)
DB 00000000b ;G(0) B(0) 0 0 Limit[19..16]
DB 00h ;Base[31..24]


GDT_SIZE EQU ($ - Gdt) ;<<<< Size of GDT, in bytes

GdtDesc: ;GDT descriptor
DW GDT_SIZE - 1 ;GDT limit
DD 000E0000H ;GDT base address (Note, relocated to
;0E0000H in RAM above)



IdtDesc: ;IDT descriptor
DW IDT_SIZE - 1 ;IDT limit
DD 0H ;IDT base address = 0 for testing


ridt: DW 03ffh ; The base of the IDT for real-mode
;interrupts use
DD 0 ;use when we go back to real mode
;(works fine)


Herbert Kleebauer

unread,
Jan 13, 2013, 11:57:45 AM1/13/13
to
On 13.01.2013 05:18, monah...@gmail.com wrote:

> However I am having a real problem getting software interrupts (have not even tried hardware ones yet).

Maybe you should try:

comp.lang.asm.x86 (moderated group, so posting may be delayed some hours)
alt.os.development

monah...@gmail.com

unread,
Jan 13, 2013, 1:22:51 PM1/13/13
to
Will do thanks
0 new messages