btx.S revision 61064
143561Skato# 243561Skato# Copyright (c) 1998 Robert Nordier 343561Skato# All rights reserved. 443561Skato# 543561Skato# Redistribution and use in source and binary forms are freely 643561Skato# permitted provided that the above copyright notice and this 743561Skato# paragraph and the following disclaimer are duplicated in all 843561Skato# such forms. 943561Skato# 1043561Skato# This software is provided "AS IS" and without any express or 1143561Skato# implied warranties, including, without limitation, the implied 1243561Skato# warranties of merchantability and fitness for a particular 1343561Skato# purpose. 1443561Skato# 1543561Skato 1650477Speter# $FreeBSD: head/sys/boot/pc98/btx/btx/btx.S 61064 2000-05-29 11:58:01Z nyan $ 1743561Skato 1843561Skato# 1943561Skato# Memory layout. 2043561Skato# 2143561Skato .set MEM_BTX,0x1000 # Start of BTX memory 2243561Skato .set MEM_ESP0,0x1800 # Supervisor stack 2343561Skato .set MEM_BUF,0x1800 # Scratch buffer 2443561Skato .set MEM_ESP1,0x1e00 # Link stack 2543561Skato .set MEM_IDT,0x1e00 # IDT 2643561Skato .set MEM_TSS,0x1f98 # TSS 2743561Skato .set MEM_MAP,0x2000 # I/O bit map 2843561Skato .set MEM_DIR,0x4000 # Page directory 2943561Skato .set MEM_TBL,0x5000 # Page tables 3043561Skato .set MEM_ORG,0x9000 # BTX code 3143561Skato .set MEM_USR,0xa000 # Start of user memory 3243561Skato# 3343561Skato# Paging control. 3443561Skato# 3543561Skato .set PAG_SIZ,0x1000 # Page size 3643561Skato .set PAG_CNT,0x1000 # Pages to map 3743561Skato# 3843561Skato# Segment selectors. 3943561Skato# 4043561Skato .set SEL_SCODE,0x8 # Supervisor code 4143561Skato .set SEL_SDATA,0x10 # Supervisor data 4243561Skato .set SEL_RCODE,0x18 # Real mode code 4343561Skato .set SEL_RDATA,0x20 # Real mode data 4443561Skato .set SEL_UCODE,0x28|3 # User code 4543561Skato .set SEL_UDATA,0x30|3 # User data 4643561Skato .set SEL_TSS,0x38 # TSS 4743561Skato# 4843561Skato# Task state segment fields. 4943561Skato# 5043561Skato .set TSS_ESP0,0x4 # PL 0 ESP 5143561Skato .set TSS_SS0,0x8 # PL 0 SS 5243561Skato .set TSS_ESP1,0xc # PL 1 ESP 5343561Skato .set TSS_MAP,0x66 # I/O bit map base 5443561Skato# 5543561Skato# System calls. 5643561Skato# 5743561Skato .set SYS_EXIT,0x0 # Exit 5843561Skato .set SYS_EXEC,0x1 # Exec 5943561Skato# 6043561Skato# V86 constants. 6143561Skato# 6243561Skato .set V86_FLG,0x208eff # V86 flag mask 6343561Skato .set V86_STK,0x400 # V86 stack allowance 6443561Skato# 6543561Skato# Dump format control bytes. 6643561Skato# 6743561Skato .set DMP_X16,0x1 # Word 6843561Skato .set DMP_X32,0x2 # Long 6943561Skato .set DMP_MEM,0x4 # Memory 7043561Skato .set DMP_EOL,0x8 # End of line 7143561Skato# 7243561Skato# Screen defaults and assumptions. 7343561Skato# 7443561Skato.`ifdef' PC98 7543561Skato .set SCR_MAT,0xe1 # Mode/attribute 7643561Skato.else 7743561Skato .set SCR_MAT,0x7 # Mode/attribute 7843561Skato.endif 7943561Skato .set SCR_COL,0x50 # Columns per row 8043561Skato .set SCR_ROW,0x19 # Rows per screen 8143561Skato# 8243561Skato# BIOS Data Area locations. 8343561Skato# 8443561Skato.`ifdef' PC98 8558871Skato .set BDA_MEM,0x501 # Free memory 8658871Skato .set BDA_KEYFLAGS,0x53a # Keyboard shift-state flags 8758871Skato .set BDA_POS,0x53e # Cursor position 8843561Skato.else 8943561Skato .set BDA_MEM,0x413 # Free memory 9058871Skato .set BDA_KEYFLAGS,0x417 # Keyboard shift-state flags 9143561Skato .set BDA_SCR,0x449 # Video mode 9243561Skato .set BDA_POS,0x450 # Cursor position 9358871Skato .set BDA_BOOT,0x472 # Boot howto flag 9443561Skato.endif 9543561Skato# 9643561Skato# Derivations, for brevity. 9743561Skato# 9843561Skato .set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0 9943561Skato .set _ESP1H,MEM_ESP1>>0x8 # Byte 1 of ESP1 10043561Skato .set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base 10143561Skato .set _TSSLM,MEM_DIR-MEM_TSS-1 # TSS limit 10243561Skato .set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit 10343561Skato# 10443561Skato# Code segment. 10543561Skato# 10643561Skato .globl start 10761064Snyan .code16 10843561Skatostart: # Start of code 10943561Skato# 11043561Skato# BTX header. 11143561Skato# 11243561Skatobtx_hdr: .byte 0xeb # Machine ID 11343561Skato .byte 0xe # Header size 11443561Skato .ascii "BTX" # Magic 11543561Skato .byte 0x1 # Major version 11644368Skato .byte 0x1 # Minor version 11743561Skato .byte 0x0 # Flags 11843561Skato .word PAG_CNT-MEM_ORG>>0xc # Paging control 11943561Skato .word break-start # Text size 12043561Skato .long 0x0 # Entry address 12143561Skato# 12243561Skato# Initialization routine. 12343561Skato# 12443561Skatoinit: cli # Disable interrupts 12561064Snyan xor %ax,%ax # Zero/segment 12661064Snyan mov %ax,%ss # Set up 12761064Snyan mov $MEM_ESP0,%sp # stack 12861064Snyan mov %ax,%es # Address 12961064Snyan mov %ax,%ds # data 13061064Snyan pushl $0x2 # Clear 13161064Snyan popfl # flags 13243561Skato# 13343561Skato# Initialize memory. 13443561Skato# 13561064Snyan mov $MEM_IDT,%di # Memory to initialize 13661064Snyan mov $(MEM_ORG-MEM_IDT)/2,%cx # Words to zero 13761064Snyan push %di # Save 13843561Skato rep # Zero-fill 13961064Snyan stosw # memory 14061064Snyan pop %di # Restore 14143561Skato# 14243561Skato# Create IDT. 14343561Skato# 14461064Snyan mov $idtctl,%si # Control string 14543561Skatoinit.1: lodsb # Get entry 14661064Snyan cbw # count 14761064Snyan xchg %ax,%cx # as word 14861064Snyan jcxz init.4 # If done 14943561Skato lodsb # Get segment 15061064Snyan xchg %ax,%dx # P:DPL:type 15161064Snyan lodsw # Get control 15261064Snyan xchg %ax,%bx # set 15361064Snyan lodsw # Get handler offset 15461064Snyan mov $SEL_SCODE,%dh # Segment selector 15561064Snyaninit.2: shr %bx # Handle this int? 15643561Skato jnc init.3 # No 15761064Snyan mov %ax,(%di) # Set handler offset 15861064Snyan mov %dh,0x2(%di) # and selector 15961064Snyan mov %dl,0x5(%di) # Set P:DPL:type 16061064Snyan add $0x4,%ax # Next handler 16161064Snyaninit.3: lea 0x8(%di),%di # Next entry 16243561Skato loop init.2 # Till set done 16343561Skato jmp init.1 # Continue 16443561Skato# 16543561Skato# Initialize TSS. 16643561Skato# 16761064Snyaninit.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0 16861064Snyan movb $SEL_SDATA,TSS_SS0(%di) # Set SS0 16961064Snyan movb $_ESP1H,TSS_ESP1+1(%di) # Set ESP1 17061064Snyan movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base 17152202Skatoifdef(`PAGING',` 17243561Skato# 17343561Skato# Create page directory. 17443561Skato# 17561064Snyan xor %edx,%edx # Page 17661064Snyan mov $PAG_SIZ>>0x8,%dh # size 17761064Snyan xor %eax,%eax # Zero 17861064Snyan mov $MEM_DIR,%di # Page directory 17961064Snyan mov $PAG_CNT>>0xa,%cl # Entries 18061064Snyan mov $MEM_TBL|0x7,%ax # First entry 18161064Snyaninit.5: stosl # Write entry 18261064Snyan add %dx,%ax # To next 18343561Skato loop init.5 # Till done 18443561Skato# 18543561Skato# Create page tables. 18643561Skato# 18761064Snyan mov $MEM_TBL,%di # Page table 18861064Snyan mov $PAG_CNT>>0x8,%ch # Entries 18961064Snyan xor %ax,%ax # Start address 19061064Snyaninit.6: mov $0x7,%al # Set U:W:P flags 19161064Snyan cmp btx_hdr+0x8,%cx # Standard user page? 19243561Skato jb init.7 # Yes 19361064Snyan cmp $PAG_CNT-MEM_BTX>>0xc,%cx # BTX memory? 19443561Skato jae init.7 # No or first page 19561064Snyan and $~0x2,%al # Clear W flag 19661064Snyan cmp $PAG_CNT-MEM_USR>>0xc,%cx # User page zero? 19743561Skato jne init.7 # No 19861064Snyan testb $0x80,btx_hdr+0x7 # Unmap it? 19943561Skato jz init.7 # No 20061064Snyan and $~0x1,%al # Clear P flag 20161064Snyaninit.7: stosl # Set entry 20261064Snyan add %edx,%eax # Next address 20343561Skato loop init.6 # Till done 20452202Skato') 20543561Skato# 20643561Skato# Bring up the system. 20743561Skato# 20861064Snyan mov $0x2820,%bx # Set protected mode 20961064Snyan callw setpic # IRQ offsets 21061064Snyan lidt idtdesc # Set IDT 21152202Skatoifdef(`PAGING',` 21261064Snyan xor %eax,%eax # Set base 21361064Snyan mov $MEM_DIR>>0x8,%ah # of page 21461064Snyan mov %eax,%cr3 # directory 21552202Skato') 21661064Snyan lgdt gdtdesc # Set GDT 21761064Snyan mov %cr0,%eax # Switch to protected 21852827Snyanifdef(`PAGING',` 21961064Snyan or $0x80000001,%eax # mode and enable paging 22052827Snyan',` 22161064Snyan or $0x01,%eax # mode 22252827Snyan') 22361064Snyan mov %eax,%cr0 # 22461064Snyan ljmp $SEL_SCODE,$init.8 # To 32-bit code 22561064Snyan .code32 22643561Skatoinit.8: xorl %ecx,%ecx # Zero 22743561Skato movb $SEL_SDATA,%cl # To 32-bit 22861064Snyan movw %cx,%ss # stack 22943561Skato# 23043561Skato# Launch user task. 23143561Skato# 23243561Skato movb $SEL_TSS,%cl # Set task 23361064Snyan ltr %cx # register 23443561Skato movl $MEM_USR,%edx # User base address 23543561Skato movzwl %ss:BDA_MEM,%eax # Get free memory 23643561Skato.`ifdef' PC98 23743561Skato andl $0x7,%eax 23843561Skato incl %eax 23943561Skato shll $0x11,%eax # To bytes 24043561Skato.else 24143561Skato shll $0xa,%eax # To bytes 24243561Skato.endif 24343561Skato subl $0x1000,%eax # Less arg space 24443561Skato subl %edx,%eax # Less base 24543561Skato movb $SEL_UDATA,%cl # User data selector 24643561Skato pushl %ecx # Set SS 24743561Skato pushl %eax # Set ESP 24861064Snyan push $0x202 # Set flags (IF set) 24961064Snyan push $SEL_UCODE # Set CS 25043561Skato pushl btx_hdr+0xc # Set EIP 25143561Skato pushl %ecx # Set GS 25243561Skato pushl %ecx # Set FS 25343561Skato pushl %ecx # Set DS 25443561Skato pushl %ecx # Set ES 25543561Skato pushl %edx # Set EAX 25643561Skato movb $0x7,%cl # Set remaining 25761064Snyaninit.9: push $0x0 # general 25843561Skato loop init.9 # registers 25943561Skato popa # and initialize 26043561Skato popl %es # Initialize 26143561Skato popl %ds # user 26243561Skato popl %fs # segment 26343561Skato popl %gs # registers 26443561Skato iret # To user mode 26543561Skato# 26643561Skato# Exit routine. 26743561Skato# 26843561Skatoexit: cli # Disable interrupts 26943561Skato movl $MEM_ESP0,%esp # Clear stack 27043561Skato# 27143561Skato# Turn off paging. 27243561Skato# 27343561Skato movl %cr0,%eax # Get CR0 27456813Skatoifdef(`PAGING',` 27543561Skato andl $~0x80000000,%eax # Disable 27643561Skato movl %eax,%cr0 # paging 27752202Skato') 27843561Skato xorl %ecx,%ecx # Zero 27952202Skatoifdef(`PAGING',` 28043561Skato movl %ecx,%cr3 # Flush TLB 28152202Skato') 28243561Skato# 28343561Skato# To 16 bits. 28443561Skato# 28561064Snyan ljmpw $SEL_RCODE,$exit.1 # Reload CS 28661064Snyan .code16 28761064Snyanexit.1: mov $SEL_RDATA,%cl # 16-bit selector 28861064Snyan mov %cx,%ss # Reload SS 28961064Snyan mov %cx,%ds # Load 29061064Snyan mov %cx,%es # remaining 29161064Snyan mov %cx,%fs # segment 29261064Snyan mov %cx,%gs # registers 29343561Skato# 29443561Skato# To real-address mode. 29543561Skato# 29661064Snyan dec %ax # Switch to 29761064Snyan mov %eax,%cr0 # real mode 29861064Snyan ljmp $0x0,$exit.2 # Reload CS 29961064Snyanexit.2: xor %ax,%ax # Real mode segment 30061064Snyan mov %ax,%ss # Reload SS 30161064Snyan mov %ax,%ds # Address data 30243561Skato.`ifdef' PC98 30361064Snyan mov $0x1008,%bx # Set real mode 30443561Skato.else 30561064Snyan mov $0x7008,%bx # Set real mode 30643561Skato.endif 30761064Snyan callw setpic # IRQ offsets 30861064Snyan lidt ivtdesc # Set IVT 30943561Skato# 31043561Skato# Reboot or await reset. 31143561Skato# 31243561Skato sti # Enable interrupts 31361064Snyan testb $0x1,btx_hdr+0x7 # Reboot? 31443561Skatoexit.3: jz exit.3 # No 31543561Skato.`ifdef' PC98 31643561Skato movb $0xa0,%al 31743561Skato outb %al,$0x35 31843561Skato movb 0,%al 31943561Skato outb %al,$0xf0 32043561Skatoexit.4: jmp exit.4 32143561Skato.else 32258871Skato movw $0x1234, BDA_BOOT # Do a warm boot 32361064Snyan ljmp $0xffff,$0x0 # reboot the machine 32443561Skato.endif 32543561Skato# 32643561Skato# Set IRQ offsets by reprogramming 8259A PICs. 32743561Skato# 32843561Skato.`ifdef' PC98 32961064Snyansetpic: in $0x02,%al # Save master 33061064Snyan push %ax # IMR 33161064Snyan in $0x0a,%al # Save slave 33261064Snyan push %ax # IMR 33343561Skato movb $0x11,%al # ICW1 to 33443561Skato outb %al,$0x00 # master, 33543561Skato outb %al,$0x08 # slave 33643561Skato movb %bl,%al # ICW2 to 33743561Skato outb %al,$0x02 # master 33843561Skato movb %bh,%al # ICW2 to 33943561Skato outb %al,$0x0a # slave 34043561Skato movb $0x80,%al # ICW3 to 34143561Skato outb %al,$0x02 # master 34243561Skato movb $0x7,%al # ICW3 to 34343561Skato outb %al,$0x0a # slave 34443561Skato movb $0x1d,%al # ICW4 to 34543561Skato outb %al,$0x02 # master, 34643561Skato movb $0x9,%al # ICW4 to 34743561Skato outb %al,$0x0a # slave 34861064Snyan pop %ax # Restore slave 34943561Skato outb %al,$0x0a # IMR 35061064Snyan pop %ax # Restore master 35143561Skato outb %al,$0x02 # IMR 35243561Skato.else 35361064Snyansetpic: in $0x21,%al # Save master 35461064Snyan push %ax # IMR 35561064Snyan in $0xa1,%al # Save slave 35661064Snyan push %ax # IMR 35743561Skato movb $0x11,%al # ICW1 to 35843561Skato outb %al,$0x20 # master, 35943561Skato outb %al,$0xa0 # slave 36043561Skato movb %bl,%al # ICW2 to 36143561Skato outb %al,$0x21 # master 36243561Skato movb %bh,%al # ICW2 to 36343561Skato outb %al,$0xa1 # slave 36443561Skato movb $0x4,%al # ICW3 to 36543561Skato outb %al,$0x21 # master 36643561Skato movb $0x2,%al # ICW3 to 36743561Skato outb %al,$0xa1 # slave 36843561Skato movb $0x1,%al # ICW4 to 36943561Skato outb %al,$0x21 # master, 37043561Skato outb %al,$0xa1 # slave 37161064Snyan pop %ax # Restore slave 37243561Skato outb %al,$0xa1 # IMR 37361064Snyan pop %ax # Restore master 37443561Skato outb %al,$0x21 # IMR 37543561Skato.endif 37661064Snyan retw # To caller 37761064Snyan .code32 37843561Skato# 37943561Skato# Initiate return from V86 mode to user mode. 38043561Skato# 38143561Skatointhlt: hlt # To supervisor mode 38243561Skato# 38343561Skato# Exception jump table. 38443561Skato# 38561064Snyanintx00: push $0x0 # Int 0x0: #DE 38643561Skato jmp ex_noc # Divide error 38761064Snyan push $0x1 # Int 0x1: #DB 38843561Skato jmp ex_noc # Debug 38961064Snyan push $0x3 # Int 0x3: #BP 39043561Skato jmp ex_noc # Breakpoint 39161064Snyan push $0x4 # Int 0x4: #OF 39243561Skato jmp ex_noc # Overflow 39361064Snyan push $0x5 # Int 0x5: #BR 39443561Skato jmp ex_noc # BOUND range exceeded 39561064Snyan push $0x6 # Int 0x6: #UD 39643561Skato jmp ex_noc # Invalid opcode 39761064Snyan push $0x7 # Int 0x7: #NM 39843561Skato jmp ex_noc # Device not available 39961064Snyan push $0x8 # Int 0x8: #DF 40043561Skato jmp except # Double fault 40161064Snyan push $0xa # Int 0xa: #TS 40243561Skato jmp except # Invalid TSS 40361064Snyan push $0xb # Int 0xb: #NP 40443561Skato jmp except # Segment not present 40561064Snyan push $0xc # Int 0xc: #SS 40643561Skato jmp except # Stack segment fault 40761064Snyan push $0xd # Int 0xd: #GP 40843561Skato jmp ex_v86 # General protection 40961064Snyan push $0xe # Int 0xe: #PF 41043561Skato jmp except # Page fault 41161064Snyanintx10: push $0x10 # Int 0x10: #MF 41243561Skato jmp ex_noc # Floating-point error 41343561Skato# 41443561Skato# Handle #GP exception. 41543561Skato# 41643561Skatoex_v86: testb $0x2,0x12(%esp,1) # V86 mode? 41743561Skato jz except # No 41843561Skato jmp v86mon # To monitor 41943561Skato# 42043561Skato# Save a zero error code. 42143561Skato# 42243561Skatoex_noc: pushl (%esp,1) # Duplicate int no 42343561Skato movb $0x0,0x4(%esp,1) # Fake error code 42443561Skato# 42543561Skato# Handle exception. 42643561Skato# 42743561Skatoexcept: cld # String ops inc 42843561Skato pushl %ds # Save 42943561Skato pushl %es # most 43043561Skato pusha # registers 43143561Skato movb $0x6,%al # Push loop count 43243561Skato testb $0x2,0x3a(%esp,1) # V86 mode? 43343561Skato jnz except.1 # Yes 43443561Skato pushl %gs # Set GS 43543561Skato pushl %fs # Set FS 43643561Skato pushl %ds # Set DS 43743561Skato pushl %es # Set ES 43843561Skato movb $0x2,%al # Push loop count 43943561Skato cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode? 44043561Skato jne except.1 # No 44143561Skato pushl %ss # Set SS 44243561Skato leal 0x50(%esp,1),%eax # Set 44343561Skato pushl %eax # ESP 44443561Skato jmp except.2 # Join common code 44543561Skatoexcept.1: pushl 0x50(%esp,1) # Set GS, FS, DS, ES 44643561Skato decb %al # (if V86 mode), and 44743561Skato jne except.1 # SS, ESP 44861064Snyanexcept.2: push $SEL_SDATA # Set up 44943561Skato popl %ds # to 45043561Skato pushl %ds # address 45143561Skato popl %es # data 45243561Skato movl %esp,%ebx # Stack frame 45343561Skato movl $dmpfmt,%esi # Dump format string 45443561Skato movl $MEM_BUF,%edi # Buffer 45543561Skato.`ifdef' PC98 45643561Skato pushl %eax 45743561Skato pushl %edx 45843561Skatowait.1: 45943561Skato inb $0x60,%al 46043561Skato testb $0x04,%al 46143561Skato jz wait.1 46243561Skato movb $0xe0,%al 46343561Skato outb %al,$0x62 46443561Skatowait.2: 46543561Skato inb $0x60,%al 46643561Skato testb $0x01,%al 46743561Skato jz wait.2 46843561Skato xorl %edx,%edx 46943561Skato inb $0x62,%al 47043561Skato movb %al,%dl 47143561Skato inb $0x62,%al 47243561Skato movb %al,%dh 47343561Skato inb $0x62,%al 47443561Skato inb $0x62,%al 47543561Skato inb $0x62,%al 47643561Skato movl %edx,%eax 47743561Skato shlw $1,%ax 47843561Skato movl $BDA_POS,%edx 47943561Skato movw %ax,(%edx) 48043561Skato popl %edx 48143561Skato popl %eax 48243561Skato.endif 48343561Skato pushl %edi # Dump to 48443561Skato call dump # buffer 48543561Skato popl %esi # and 48643561Skato call putstr # display 48743561Skato leal 0x18(%esp,1),%esp # Discard frame 48843561Skato popa # Restore 48943561Skato popl %es # registers 49043561Skato popl %ds # saved 49143561Skato cmpb $0x3,(%esp,1) # Breakpoint? 49243561Skato je except.3 # Yes 49343561Skato jmp exit # Exit 49443561Skatoexcept.3: leal 0x8(%esp,1),%esp # Discard err, int no 49543561Skato iret # From interrupt 49643561Skato# 49743561Skato# Return to user mode from V86 mode. 49843561Skato# 49943561Skatointrtn: cld # String ops inc 50043561Skato pushl %ds # Address 50143561Skato popl %es # data 50243561Skato leal 0x3c(%ebp),%edx # V86 Segment registers 50343561Skato movl MEM_TSS+TSS_ESP1,%esi # Link stack pointer 50443561Skato lodsl # INT_V86 args pointer 50543561Skato movl %esi,%ebx # Saved exception frame 50643561Skato testl %eax,%eax # INT_V86 args? 50743561Skato jz intrtn.2 # No 50843561Skato movl $MEM_USR,%edi # User base 50943561Skato movl 0x1c(%esi),%ebx # User ESP 51043561Skato movl %eax,(%edi,%ebx,1) # Restore to user stack 51143561Skato leal 0x8(%edi,%eax,1),%edi # Arg segment registers 51243561Skato testb $0x4,-0x6(%edi) # Return flags? 51343561Skato jz intrtn.1 # No 51443561Skato movl 0x30(%ebp),%eax # Get V86 flags 51543561Skato movw %ax,0x18(%esi) # Set user flags 51643561Skatointrtn.1: leal 0x10(%esi),%ebx # Saved exception frame 51743561Skato xchgl %edx,%esi # Segment registers 51843561Skato movb $0x4,%cl # Update seg regs 51943561Skato rep # in INT_V86 52043561Skato movsl # args 52143561Skatointrtn.2: movl %edx,%esi # Segment registers 52243561Skato leal 0x28(%ebp),%edi # Set up seg 52343561Skato movb $0x4,%cl # regs for 52443561Skato rep # later 52543561Skato movsl # pop 52643561Skato movl %ebx,%esi # Restore exception 52743561Skato movb $0x5,%cl # frame to 52843561Skato rep # supervisor 52943561Skato movsl # stack 53043561Skato movl %esi,MEM_TSS+TSS_ESP1 # Link stack pointer 53143561Skato popa # Restore 53243561Skato leal 0x8(%esp,1),%esp # Discard err, int no 53343561Skato popl %es # Restore 53443561Skato popl %ds # user 53543561Skato popl %fs # segment 53643561Skato popl %gs # registers 53743561Skato iret # To user mode 53843561Skato# 53943561Skato# V86 monitor. 54043561Skato# 54143561Skatov86mon: cld # String ops inc 54243561Skato pushl $SEL_SDATA # Set up for 54343561Skato popl %ds # flat addressing 54443561Skato pusha # Save registers 54543561Skato movl %esp,%ebp # Address stack frame 54643561Skato movzwl 0x2c(%ebp),%edi # Load V86 CS 54743561Skato shll $0x4,%edi # To linear 54843561Skato movl 0x28(%ebp),%esi # Load V86 IP 54943561Skato addl %edi,%esi # Code pointer 55043561Skato xorl %ecx,%ecx # Zero 55143561Skato movb $0x2,%cl # 16-bit operands 55243561Skato xorl %eax,%eax # Zero 55343561Skatov86mon.1: lodsb # Get opcode 55443561Skato cmpb $0x66,%al # Operand size prefix? 55543561Skato jne v86mon.2 # No 55643561Skato movb $0x4,%cl # 32-bit operands 55743561Skato jmp v86mon.1 # Continue 55843561Skatov86mon.2: cmpb $0xf4,%al # HLT? 55943561Skato jne v86mon.3 # No 56043561Skato cmpl $inthlt+0x1,%esi # Is inthlt? 56144368Skato jne v86mon.7 # No (ignore) 56243561Skato jmp intrtn # Return to user mode 56344368Skatov86mon.3: cmpb $0xf,%al # Is 56444368Skato jne v86mon.4 # this 56544368Skato cmpb $0x20,(%esi) # a 56644368Skato jne v86mon.4 # MOV EAX,CR0 56744368Skato cmpb $0xc0,0x1(%esi) # instruction? 56844368Skato je v86mov # Yes 56944368Skatov86mon.4: cmpb $0xfa,%al # CLI? 57043561Skato je v86cli # Yes 57143561Skato cmpb $0xfb,%al # STI? 57243561Skato je v86sti # Yes 57343561Skato movzwl 0x38(%ebp),%ebx # Load V86 SS 57443561Skato shll $0x4,%ebx # To offset 57543561Skato pushl %ebx # Save 57643561Skato addl 0x34(%ebp),%ebx # Add V86 SP 57743561Skato movl 0x30(%ebp),%edx # Load V86 flags 57843561Skato cmpb $0x9c,%al # PUSHF/PUSHFD? 57943561Skato je v86pushf # Yes 58043561Skato cmpb $0x9d,%al # POPF/POPFD? 58143561Skato je v86popf # Yes 58243561Skato cmpb $0xcd,%al # INT imm8? 58343561Skato je v86intn # Yes 58443561Skato cmpb $0xcf,%al # IRET/IRETD? 58543561Skato je v86iret # Yes 58643561Skato popl %ebx # Restore 58743561Skato popa # Restore 58843561Skato jmp except # Handle exception 58944368Skatov86mon.5: movl %edx,0x30(%ebp) # Save V86 flags 59044368Skatov86mon.6: popl %edx # V86 SS adjustment 59143561Skato subl %edx,%ebx # Save V86 59243561Skato movl %ebx,0x34(%ebp) # SP 59344368Skatov86mon.7: subl %edi,%esi # From linear 59443561Skato movl %esi,0x28(%ebp) # Save V86 IP 59543561Skato popa # Restore 59643561Skato leal 0x8(%esp,1),%esp # Discard int no, error 59743561Skato iret # To V86 mode 59843561Skato# 59944368Skato# Emulate MOV EAX,CR0. 60044368Skato# 60144368Skatov86mov: movl %cr0,%eax # CR0 to 60244368Skato movl %eax,0x1c(%ebp) # saved EAX 60344368Skato incl %esi # Adjust 60444368Skato incl %esi # IP 60544368Skato jmp v86mon.7 # Finish up 60644368Skato# 60743561Skato# Emulate CLI. 60843561Skato# 60943561Skatov86cli: andb $~0x2,0x31(%ebp) # Clear IF 61044368Skato jmp v86mon.7 # Finish up 61143561Skato# 61243561Skato# Emulate STI. 61343561Skato# 61443561Skatov86sti: orb $0x2,0x31(%ebp) # Set IF 61544368Skato jmp v86mon.7 # Finish up 61643561Skato# 61743561Skato# Emulate PUSHF/PUSHFD. 61843561Skato# 61943561Skatov86pushf: subl %ecx,%ebx # Adjust SP 62043561Skato cmpb $0x4,%cl # 32-bit 62143561Skato je v86pushf.1 # Yes 62261064Snyan data16 # 16-bit 62343561Skatov86pushf.1: movl %edx,(%ebx) # Save flags 62444368Skato jmp v86mon.6 # Finish up 62543561Skato# 62643561Skato# Emulate IRET/IRETD. 62743561Skato# 62843561Skatov86iret: movzwl (%ebx),%esi # Load V86 IP 62943561Skato movzwl 0x2(%ebx),%edi # Load V86 CS 63043561Skato leal 0x4(%ebx),%ebx # Adjust SP 63143561Skato movl %edi,0x2c(%ebp) # Save V86 CS 63243561Skato xorl %edi,%edi # No ESI adjustment 63343561Skato# 63443561Skato# Emulate POPF/POPFD (and remainder of IRET/IRETD). 63543561Skato# 63643561Skatov86popf: cmpb $0x4,%cl # 32-bit? 63743561Skato je v86popf.1 # Yes 63843561Skato movl %edx,%eax # Initialize 63961064Snyan data16 # 16-bit 64043561Skatov86popf.1: movl (%ebx),%eax # Load flags 64143561Skato addl %ecx,%ebx # Adjust SP 64243561Skato andl $V86_FLG,%eax # Merge 64343561Skato andl $~V86_FLG,%edx # the 64443561Skato orl %eax,%edx # flags 64544368Skato jmp v86mon.5 # Finish up 64643561Skato# 64752202Skato# trap int 15, function 87 64852202Skato# reads %es:%si from saved registers on stack to find a GDT containing 64952202Skato# source and destination locations 65052202Skato# reads count of words from saved %cx 65152202Skato# returns success by setting %ah to 0 65243561Skato# 65352202Skatoint15_87: pushl %eax # Save 65452202Skato pushl %ebx # some information 65552202Skato pushl %esi # onto the stack. 65652202Skato pushl %edi 65752202Skato xorl %eax,%eax # clean EAX 65852202Skato xorl %ebx,%ebx # clean EBX 65952202Skato movl 0x4(%ebp),%esi # Get user's ESI 66052202Skato movl 0x3C(%ebp),%ebx # store ES 66152202Skato movw %si,%ax # store SI 66252202Skato shll $0x4,%ebx # Make it a seg. 66352202Skato addl %eax,%ebx # ebx=(es<<4)+si 66452202Skato movb 0x14(%ebx),%al # Grab the 66552202Skato movb 0x17(%ebx),%ah # necessary 66652202Skato shll $0x10,%eax # information 66752202Skato movw 0x12(%ebx),%ax # from 66852202Skato movl %eax,%esi # the 66952202Skato movb 0x1c(%ebx),%al # GDT in order to 67052202Skato movb 0x1f(%ebx),%ah # have %esi offset 67152202Skato shll $0x10,%eax # of source and %edi 67252202Skato movw 0x1a(%ebx),%ax # of destination. 67352202Skato movl %eax,%edi 67452202Skato pushl %ds # Make: 67552202Skato popl %es # es = ds 67652202Skato pushl %ecx # stash ECX 67752202Skato xorl %ecx,%ecx # highw of ECX is clear 67852202Skato movw 0x18(%ebp),%cx # Get user's ECX 67958871Skato shll $0x1,%ecx # Convert from num words to num 68058871Skato # bytes 68152202Skato rep # repeat... 68252202Skato movsb # perform copy. 68352202Skato popl %ecx # Restore 68452202Skato popl %edi 68552202Skato popl %esi # previous 68652202Skato popl %ebx # register 68752202Skato popl %eax # values. 68852202Skato movb $0x0,0x1d(%ebp) # set ah = 0 to indicate 68952202Skato # success 69052202Skato andb $0xfe,%dl # clear CF 69152202Skato jmp v86mon.5 # Finish up 69252202Skato 69352202Skato# 69458871Skato# Reboot the machine by setting the reboot flag and exiting 69558871Skato# 69658871Skatoreboot: orb $0x1,btx_hdr+0x7 # Set the reboot flag 69758871Skato jmp exit # Terminate BTX and reboot 69858871Skato 69958871Skato# 70052202Skato# Emulate INT imm8... also make sure to check if it's int 15/87 70152202Skato# 70243561Skatov86intn: lodsb # Get int no 70358871Skato cmpb $0x19,%al # is it int 19? 70458871Skato je reboot # yes, reboot the machine 70552202Skato cmpb $0x15,%al # is it int 15? 70658871Skato jne v86intn.3 # no, skip parse 70752202Skato pushl %eax # stash EAX 70852202Skato movl 0x1c(%ebp),%eax # user's saved EAX 70958871Skato cmpb $0x87,%ah # is it the memcpy subfunction? 71058871Skato jne v86intn.1 # no, keep checking 71152202Skato popl %eax # get the stack straight 71252202Skato jmp int15_87 # it's our cue 71358871Skatov86intn.1: cmpw $0x4f53,%ax # is it the delete key callout? 71458871Skato jne v86intn.2 # no, handle the int normally 71558871Skato movb BDA_KEYFLAGS,%al # get the shift key state 71658871Skato.`ifdef' PC98 71758871Skato andb $0x18,%al # mask off just Ctrl and Alt 71858871Skato cmpb $0x18,%al # are both Ctrl and Alt down? 71958871Skato.else 72058871Skato andb $0xc,%al # mask off just Ctrl and Alt 72158871Skato cmpb $0xc,%al # are both Ctrl and Alt down? 72258871Skato.endif 72358871Skato jne v86intn.2 # no, handle the int normally 72458871Skato popl %eax # restore EAX 72558871Skato jmp reboot # reboot the machine 72658871Skatov86intn.2: popl %eax # restore EAX 72758871Skatov86intn.3: subl %edi,%esi # From 72843561Skato shrl $0x4,%edi # linear 72943561Skato movw %dx,-0x2(%ebx) # Save flags 73043561Skato movw %di,-0x4(%ebx) # Save CS 73143561Skato leal -0x6(%ebx),%ebx # Adjust SP 73243561Skato movw %si,(%ebx) # Save IP 73343561Skato shll $0x2,%eax # Scale 73443561Skato movzwl (%eax),%esi # Load IP 73543561Skato movzwl 0x2(%eax),%edi # Load CS 73643561Skato movl %edi,0x2c(%ebp) # Save CS 73743561Skato xorl %edi,%edi # No ESI adjustment 73861064Snyan andb $~0x1,%dh # Clear TF 73944368Skato jmp v86mon.5 # Finish up 74043561Skato# 74143561Skato# Hardware interrupt jump table. 74243561Skato# 74361064Snyanintx20: push $0x8 # Int 0x20: IRQ0 74443561Skato jmp int_hw # V86 int 0x8 74561064Snyan push $0x9 # Int 0x21: IRQ1 74643561Skato jmp int_hw # V86 int 0x9 74761064Snyan push $0xa # Int 0x22: IRQ2 74843561Skato jmp int_hw # V86 int 0xa 74961064Snyan push $0xb # Int 0x23: IRQ3 75043561Skato jmp int_hw # V86 int 0xb 75161064Snyan push $0xc # Int 0x24: IRQ4 75243561Skato jmp int_hw # V86 int 0xc 75361064Snyan push $0xd # Int 0x25: IRQ5 75443561Skato jmp int_hw # V86 int 0xd 75561064Snyan push $0xe # Int 0x26: IRQ6 75643561Skato jmp int_hw # V86 int 0xe 75761064Snyan push $0xf # Int 0x27: IRQ7 75843561Skato jmp int_hw # V86 int 0xf 75943561Skato.`ifdef' PC98 76061064Snyan push $0x10 # Int 0x28: IRQ8 76143561Skato jmp int_hw # V86 int 0x10 76261064Snyan push $0x11 # Int 0x29: IRQ9 76343561Skato jmp int_hw # V86 int 0x11 76461064Snyan push $0x12 # Int 0x2a: IRQ10 76543561Skato jmp int_hw # V86 int 0x12 76661064Snyan push $0x13 # Int 0x2b: IRQ11 76743561Skato jmp int_hw # V86 int 0x13 76861064Snyan push $0x14 # Int 0x2c: IRQ12 76943561Skato jmp int_hw # V86 int 0x14 77061064Snyan push $0x15 # Int 0x2d: IRQ13 77143561Skato jmp int_hw # V86 int 0x15 77261064Snyan push $0x16 # Int 0x2e: IRQ14 77343561Skato jmp int_hw # V86 int 0x16 77461064Snyan push $0x17 # Int 0x2f: IRQ15 77543561Skato jmp int_hw # V86 int 0x17 77643561Skato.else 77761064Snyan push $0x70 # Int 0x28: IRQ8 77843561Skato jmp int_hw # V86 int 0x70 77961064Snyan push $0x71 # Int 0x29: IRQ9 78043561Skato jmp int_hw # V86 int 0x71 78161064Snyan push $0x72 # Int 0x2a: IRQ10 78243561Skato jmp int_hw # V86 int 0x72 78361064Snyan push $0x73 # Int 0x2b: IRQ11 78443561Skato jmp int_hw # V86 int 0x73 78561064Snyan push $0x74 # Int 0x2c: IRQ12 78643561Skato jmp int_hw # V86 int 0x74 78761064Snyan push $0x75 # Int 0x2d: IRQ13 78843561Skato jmp int_hw # V86 int 0x75 78961064Snyan push $0x76 # Int 0x2e: IRQ14 79043561Skato jmp int_hw # V86 int 0x76 79161064Snyan push $0x77 # Int 0x2f: IRQ15 79243561Skato jmp int_hw # V86 int 0x77 79343561Skato.endif 79443561Skato# 79543561Skato# Reflect hardware interrupts. 79643561Skato# 79743561Skatoint_hw: testb $0x2,0xe(%esp,1) # V86 mode? 79843561Skato jz intusr # No 79943561Skato pushl $SEL_SDATA # Address 80043561Skato popl %ds # data 80143561Skato xchgl %eax,(%esp,1) # Swap EAX, int no 80243561Skato pushl %ebp # Address 80343561Skato movl %esp,%ebp # stack frame 80443561Skato pushl %ebx # Save 80543561Skato shll $0x2,%eax # Get int 80643561Skato movl (%eax),%eax # vector 80743561Skato subl $0x6,0x14(%ebp) # Adjust V86 ESP 80843561Skato movzwl 0x18(%ebp),%ebx # V86 SS 80943561Skato shll $0x4,%ebx # * 0x10 81043561Skato addl 0x14(%ebp),%ebx # + V86 ESP 81143561Skato xchgw %ax,0x8(%ebp) # Swap V86 IP 81243561Skato rorl $0x10,%eax # Swap words 81343561Skato xchgw %ax,0xc(%ebp) # Swap V86 CS 81443561Skato roll $0x10,%eax # Swap words 81543561Skato movl %eax,(%ebx) # CS:IP for IRET 81643561Skato movl 0x10(%ebp),%eax # V86 flags 81743561Skato movw %ax,0x4(%ebx) # Flags for IRET 81843561Skato andb $~0x3,0x11(%ebp) # Clear IF, TF 81943561Skato popl %ebx # Restore 82043561Skato popl %ebp # saved 82143561Skato popl %eax # registers 82243561Skato iret # To V86 mode 82343561Skato# 82443561Skato# Invoke V86 interrupt from user mode, with arguments. 82543561Skato# 82643561Skatointx31: stc # Have btx_v86 82743561Skato pushl %eax # Missing int no 82843561Skato# 82943561Skato# Invoke V86 interrupt from user mode. 83043561Skato# 83143561Skatointusr: std # String ops dec 83243561Skato pushl %eax # Expand 83343561Skato pushl %eax # stack 83443561Skato pushl %eax # frame 83543561Skato pusha # Save 83643561Skato pushl %gs # Save 83743561Skato movl %esp,%eax # seg regs 83843561Skato pushl %fs # and 83943561Skato pushl %ds # point 84043561Skato pushl %es # to them 84161064Snyan push $SEL_SDATA # Set up 84243561Skato popl %ds # to 84343561Skato pushl %ds # address 84443561Skato popl %es # data 84543561Skato movl $MEM_USR,%ebx # User base 84643561Skato movl %ebx,%edx # address 84743561Skato jc intusr.1 # If btx_v86 84843561Skato xorl %edx,%edx # Control flags 84943561Skato xorl %ebp,%ebp # btx_v86 pointer 85043561Skatointusr.1: leal 0x50(%esp,1),%esi # Base of frame 85143561Skato pushl %esi # Save 85243561Skato addl -0x4(%esi),%ebx # User ESP 85343561Skato movl MEM_TSS+TSS_ESP1,%edi # Link stack pointer 85443561Skato leal -0x4(%edi),%edi # Adjust for push 85543561Skato xorl %ecx,%ecx # Zero 85643561Skato movb $0x5,%cl # Push exception 85743561Skato rep # frame on 85843561Skato movsl # link stack 85943561Skato xchgl %eax,%esi # Saved seg regs 86043561Skato movl 0x40(%esp,1),%eax # Get int no 86143561Skato testl %edx,%edx # Have btx_v86? 86243561Skato jz intusr.2 # No 86343561Skato movl (%ebx),%ebp # btx_v86 pointer 86443561Skato movb $0x4,%cl # Count 86543561Skato addl %ecx,%ebx # Adjust for pop 86643561Skato rep # Push saved seg regs 86743561Skato movsl # on link stack 86843561Skato addl %ebp,%edx # Flatten btx_v86 ptr 86943561Skato leal 0x14(%edx),%esi # Seg regs pointer 87043561Skato movl 0x4(%edx),%eax # Get int no/address 87143561Skato movzwl 0x2(%edx),%edx # Get control flags 87243561Skatointusr.2: movl %ebp,(%edi) # Push btx_v86 and 87343561Skato movl %edi,MEM_TSS+TSS_ESP1 # save link stack ptr 87443561Skato popl %edi # Base of frame 87543561Skato xchgl %eax,%ebp # Save intno/address 87643561Skato movl 0x48(%esp,1),%eax # Get flags 87743561Skato testb $0x2,%dl # Simulate CALLF? 87843561Skato jnz intusr.3 # Yes 87943561Skato decl %ebx # Push flags 88043561Skato decl %ebx # on V86 88143561Skato movw %ax,(%ebx) # stack 88243561Skatointusr.3: movb $0x4,%cl # Count 88343561Skato subl %ecx,%ebx # Push return address 88443561Skato movl $inthlt,(%ebx) # on V86 stack 88543561Skato rep # Copy seg regs to 88643561Skato movsl # exception frame 88743561Skato xchgl %eax,%ecx # Save flags 88843561Skato movl %ebx,%eax # User ESP 88943561Skato subl $V86_STK,%eax # Less bytes 89043561Skato ja intusr.4 # to 89143561Skato xorl %eax,%eax # keep 89243561Skatointusr.4: shrl $0x4,%eax # Gives segment 89343561Skato stosl # Set SS 89443561Skato shll $0x4,%eax # To bytes 89543561Skato xchgl %eax,%ebx # Swap 89643561Skato subl %ebx,%eax # Gives offset 89743561Skato stosl # Set ESP 89843561Skato xchgl %eax,%ecx # Get flags 89943561Skato btsl $0x11,%eax # Set VM 90061064Snyan andb $~0x1,%ah # Clear TF 90143561Skato stosl # Set EFL 90243561Skato xchgl %eax,%ebp # Get int no/address 90343561Skato testb $0x1,%dl # Address? 90443561Skato jnz intusr.5 # Yes 90543561Skato shll $0x2,%eax # Scale 90643561Skato movl (%eax),%eax # Load int vector 90743561Skatointusr.5: movl %eax,%ecx # Save 90843561Skato shrl $0x10,%eax # Gives segment 90943561Skato stosl # Set CS 91043561Skato movw %cx,%ax # Restore 91143561Skato stosl # Set EIP 91243561Skato leal 0x10(%esp,1),%esp # Discard seg regs 91343561Skato popa # Restore 91443561Skato iret # To V86 mode 91543561Skato# 91643561Skato# System Call. 91743561Skato# 91843561Skatointx30: cmpl $SYS_EXEC,%eax # Exec system call? 91943561Skato jne intx30.1 # No 92043561Skato pushl %ss # Set up 92143561Skato popl %es # all 92243561Skato pushl %es # segment 92343561Skato popl %ds # registers 92443561Skato pushl %ds # for the 92543561Skato popl %fs # program 92643561Skato pushl %fs # we're 92743561Skato popl %gs # invoking 92843561Skato movl $MEM_USR,%eax # User base address 92943561Skato addl 0xc(%esp,1),%eax # Change to user 93043561Skato leal 0x4(%eax),%esp # stack 93156813Skatoifdef(`PAGING',` 93243561Skato movl %cr0,%eax # Turn 93343561Skato andl $~0x80000000,%eax # off 93443561Skato movl %eax,%cr0 # paging 93543561Skato xorl %eax,%eax # Flush 93643561Skato movl %eax,%cr3 # TLB 93756813Skato') 93843561Skato popl %eax # Call 93943561Skato call *%eax # program 94043561Skatointx30.1: incb %ss:btx_hdr+0x7 # Flag reboot 94143561Skato jmp exit # Exit 94243561Skato# 94343561Skato# Dump structure [EBX] to [EDI], using format string [ESI]. 94443561Skato# 94543561Skatodump.0: stosb # Save char 94643561Skatodump: lodsb # Load char 94743561Skato testb %al,%al # End of string? 94843561Skato jz dump.10 # Yes 94943561Skato testb $0x80,%al # Control? 95043561Skato jz dump.0 # No 95143561Skato movb %al,%ch # Save control 95243561Skato movb $'=',%al # Append 95343561Skato stosb # '=' 95443561Skato lodsb # Get offset 95543561Skato pushl %esi # Save 95643561Skato movsbl %al,%esi # To 95743561Skato addl %ebx,%esi # pointer 95843561Skato testb $DMP_X16,%ch # Dump word? 95943561Skato jz dump.1 # No 96043561Skato lodsw # Get and 96143561Skato call hex16 # dump it 96243561Skatodump.1: testb $DMP_X32,%ch # Dump long? 96343561Skato jz dump.2 # No 96443561Skato lodsl # Get and 96543561Skato call hex32 # dump it 96643561Skatodump.2: testb $DMP_MEM,%ch # Dump memory? 96743561Skato jz dump.8 # No 96843561Skato pushl %ds # Save 96943561Skato testb $0x2,0x52(%ebx) # V86 mode? 97043561Skato jnz dump.3 # Yes 97161064Snyan verr 0x4(%esi) # Readable selector? 97243561Skato jnz dump.3 # No 97343561Skato ldsl (%esi),%esi # Load pointer 97443561Skato jmp dump.4 # Join common code 97543561Skatodump.3: lodsl # Set offset 97643561Skato xchgl %eax,%edx # Save 97743561Skato lodsl # Get segment 97843561Skato shll $0x4,%eax # * 0x10 97943561Skato addl %edx,%eax # + offset 98043561Skato xchgl %eax,%esi # Set pointer 98143561Skatodump.4: movb $0x10,%cl # Bytes to dump 98243561Skatodump.5: lodsb # Get byte and 98343561Skato call hex8 # dump it 98443561Skato decb %cl # Keep count 98543561Skato jz dump.7 # If done 98643561Skato movb $'-',%al # Separator 98743561Skato cmpb $0x8,%cl # Half way? 98843561Skato je dump.6 # Yes 98943561Skato movb $' ',%al # Use space 99043561Skatodump.6: stosb # Save separator 99143561Skato jmp dump.5 # Continue 99243561Skatodump.7: popl %ds # Restore 99343561Skatodump.8: popl %esi # Restore 99443561Skato movb $0xa,%al # Line feed 99543561Skato testb $DMP_EOL,%ch # End of line? 99643561Skato jnz dump.9 # Yes 99743561Skato movb $' ',%al # Use spaces 99843561Skato stosb # Save one 99943561Skatodump.9: jmp dump.0 # Continue 100043561Skatodump.10: stosb # Terminate string 100143561Skato ret # To caller 100243561Skato# 100343561Skato# Convert EAX, AX, or AL to hex, saving the result to [EDI]. 100443561Skato# 100543561Skatohex32: pushl %eax # Save 100643561Skato shrl $0x10,%eax # Do upper 100743561Skato call hex16 # 16 100843561Skato popl %eax # Restore 100943561Skatohex16: call hex16.1 # Do upper 8 101043561Skatohex16.1: xchgb %ah,%al # Save/restore 101143561Skatohex8: pushl %eax # Save 101243561Skato shrb $0x4,%al # Do upper 101343561Skato call hex8.1 # 4 101443561Skato popl %eax # Restore 101543561Skatohex8.1: andb $0xf,%al # Get lower 4 101643561Skato cmpb $0xa,%al # Convert 101743561Skato sbbb $0x69,%al # to hex 101843561Skato das # digit 101943561Skato orb $0x20,%al # To lower case 102043561Skato stosb # Save char 102143561Skato ret # (Recursive) 102243561Skato# 102343561Skato# Output zero-terminated string [ESI] to the console. 102443561Skato# 102543561Skatoputstr.0: call putchr # Output char 102643561Skatoputstr: lodsb # Load char 102743561Skato testb %al,%al # End of string? 102843561Skato jnz putstr.0 # No 102943561Skato ret # To caller 103043561Skato# 103143561Skato# Output character AL to the console. 103243561Skato# 103343561Skatoputchr: pusha # Save 103443561Skato xorl %ecx,%ecx # Zero for loops 103543561Skato movb $SCR_MAT,%ah # Mode/attribute 103643561Skato movl $BDA_POS,%ebx # BDA pointer 103743561Skato movw (%ebx),%dx # Cursor position 103843561Skato.`ifdef' PC98 103943561Skato movl $0xa0000,%edi 104043561Skato.else 104143561Skato movl $0xb8000,%edi # Regen buffer (color) 104243561Skato cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode? 104343561Skato jne putchr.1 # No 104443561Skato xorw %di,%di # Regen buffer (mono) 104543561Skato.endif 104643561Skatoputchr.1: cmpb $0xa,%al # New line? 104743561Skato je putchr.2 # Yes 104843561Skato.`ifdef' PC98 104943561Skato movw %dx,%cx 105043561Skato movb %al,(%edi,%ecx,1) # Write char 105143561Skato addl $0x2000,%ecx 105243561Skato movb %ah,(%edi,%ecx,1) # Write attr 105343561Skato addw $0x02,%dx 105443561Skato jmp putchr.3 105543561Skatoputchr.2: movw %dx,%ax 105643561Skato movb $SCR_COL*2,%dl 105743561Skato div %dl 105843561Skato incb %al 105943561Skato mul %dl 106043561Skato movw %ax,%dx 106143561Skatoputchr.3: cmpw $SCR_ROW*SCR_COL*2,%dx 106243561Skato.else 106343561Skato xchgl %eax,%ecx # Save char 106443561Skato movb $SCR_COL,%al # Columns per row 106543561Skato mulb %dh # * row position 106643561Skato addb %dl,%al # + column 106743561Skato adcb $0x0,%ah # position 106843561Skato shll %eax # * 2 106943561Skato xchgl %eax,%ecx # Swap char, offset 107043561Skato movw %ax,(%edi,%ecx,1) # Write attr:char 107143561Skato incl %edx # Bump cursor 107243561Skato cmpb $SCR_COL,%dl # Beyond row? 107343561Skato jb putchr.3 # No 107443561Skatoputchr.2: xorb %dl,%dl # Zero column 107543561Skato incb %dh # Bump row 107643561Skatoputchr.3: cmpb $SCR_ROW,%dh # Beyond screen? 107743561Skato.endif 107843561Skato jb putchr.4 # No 107943561Skato leal 2*SCR_COL(%edi),%esi # New top line 108043561Skato movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 108143561Skato rep # Scroll 108243561Skato movsl # screen 108343561Skato movb $' ',%al # Space 108443561Skato.`ifdef' PC98 108543561Skato xorb %ah,%ah 108643561Skato.endif 108743561Skato movb $SCR_COL,%cl # Columns to clear 108843561Skato rep # Clear 108943561Skato stosw # line 109043561Skato.`ifdef' PC98 109143561Skato movw $(SCR_ROW-1)*SCR_COL*2,%dx 109243561Skato.else 109343561Skato movb $SCR_ROW-1,%dh # Bottom line 109443561Skato.endif 109543561Skatoputchr.4: movw %dx,(%ebx) # Update position 109643561Skato popa # Restore 109743561Skato ret # To caller 109843561Skato 109943561Skato .p2align 4 110043561Skato# 110143561Skato# Global descriptor table. 110243561Skato# 110343561Skatogdt: .word 0x0,0x0,0x0,0x0 # Null entry 110443561Skato .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 110543561Skato .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 110643561Skato .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 110743561Skato .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 110843561Skato .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE 110943561Skato .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA 111043561Skato .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS 111143561Skatogdt.1: 111243561Skato# 111343561Skato# Pseudo-descriptors. 111443561Skato# 111543561Skatogdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT 111643561Skatoidtdesc: .word _IDTLM,MEM_IDT,0x0 # IDT 111743561Skatoivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT 111843561Skato# 111943561Skato# IDT construction control string. 112043561Skato# 112143561Skatoidtctl: .byte 0x10, 0x8e # Int 0x0-0xf 112243561Skato .word 0x7dfb,intx00 # (exceptions) 112343561Skato .byte 0x10, 0x8e # Int 0x10 112443561Skato .word 0x1, intx10 # (exception) 112543561Skato .byte 0x10, 0x8e # Int 0x20-0x2f 112643561Skato .word 0xffff,intx20 # (hardware) 112743561Skato .byte 0x1, 0xee # int 0x30 112843561Skato .word 0x1, intx30 # (system call) 112943561Skato .byte 0x2, 0xee # Int 0x31-0x32 113043561Skato .word 0x1, intx31 # (V86, null) 113143561Skato .byte 0x0 # End of string 113243561Skato# 113343561Skato# Dump format string. 113443561Skato# 113543561Skatodmpfmt: .byte '\n' # "\n" 113643561Skato .ascii "int" # "int=" 113743561Skato .byte 0x80|DMP_X32, 0x40 # "00000000 " 113843561Skato .ascii "err" # "err=" 113943561Skato .byte 0x80|DMP_X32, 0x44 # "00000000 " 114043561Skato .ascii "efl" # "efl=" 114143561Skato .byte 0x80|DMP_X32, 0x50 # "00000000 " 114243561Skato .ascii "eip" # "eip=" 114343561Skato .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n" 114443561Skato .ascii "eax" # "eax=" 114543561Skato .byte 0x80|DMP_X32, 0x34 # "00000000 " 114643561Skato .ascii "ebx" # "ebx=" 114743561Skato .byte 0x80|DMP_X32, 0x28 # "00000000 " 114843561Skato .ascii "ecx" # "ecx=" 114943561Skato .byte 0x80|DMP_X32, 0x30 # "00000000 " 115043561Skato .ascii "edx" # "edx=" 115143561Skato .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n" 115243561Skato .ascii "esi" # "esi=" 115343561Skato .byte 0x80|DMP_X32, 0x1c # "00000000 " 115443561Skato .ascii "edi" # "edi=" 115543561Skato .byte 0x80|DMP_X32, 0x18 # "00000000 " 115643561Skato .ascii "ebp" # "ebp=" 115743561Skato .byte 0x80|DMP_X32, 0x20 # "00000000 " 115843561Skato .ascii "esp" # "esp=" 115943561Skato .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n" 116043561Skato .ascii "cs" # "cs=" 116143561Skato .byte 0x80|DMP_X16, 0x4c # "0000 " 116243561Skato .ascii "ds" # "ds=" 116343561Skato .byte 0x80|DMP_X16, 0xc # "0000 " 116443561Skato .ascii "es" # "es=" 116543561Skato .byte 0x80|DMP_X16, 0x8 # "0000 " 116643561Skato .ascii " " # " " 116743561Skato .ascii "fs" # "fs=" 116843561Skato .byte 0x80|DMP_X16, 0x10 # "0000 " 116943561Skato .ascii "gs" # "gs=" 117043561Skato .byte 0x80|DMP_X16, 0x14 # "0000 " 117143561Skato .ascii "ss" # "ss=" 117243561Skato .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n" 117343561Skato .ascii "cs:eip" # "cs:eip=" 117443561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n" 117543561Skato .ascii "ss:esp" # "ss:esp=" 117643561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n" 117743561Skato .asciz "System halted" # End 117843561Skato# 117943561Skato# End of BTX memory. 118043561Skato# 118143561Skato .p2align 4 118243561Skatobreak: 1183