mirror of
https://github.com/xcat2/xNBA.git
synced 2024-12-16 00:01:34 +00:00
cc8821a443
running the decompresser in 16:16 protected mode using the real-mode stack. However, there's an even simpler way to do it...
179 lines
3.3 KiB
ArmAsm
179 lines
3.3 KiB
ArmAsm
|
|
#define CR0_PE 1
|
|
|
|
|
|
.arch i386
|
|
.section ".prefix", "awx", @progbits
|
|
|
|
/****************************************************************************
|
|
* alloc_basemem (real-mode near call)
|
|
*
|
|
* Allocate space from base memory via the BIOS free base memory
|
|
* counter at 40: 13
|
|
*
|
|
* Parameters:
|
|
* %cx : Number of bytes to allocate
|
|
* Returns:
|
|
* %es : Segment address of newly allocated memory
|
|
****************************************************************************
|
|
*/
|
|
.section ".prefix"
|
|
.code16
|
|
alloc_basemem:
|
|
/* Preserve registers */
|
|
pushw %cx
|
|
pushw %ax
|
|
|
|
/* %fs = 0x40, %ax = fbms */
|
|
movw $40, %ax
|
|
movw %ax, %fs
|
|
|
|
/* Round up %cx to nearest kB, subtract from FBMS */
|
|
addw $0x03ff, %cx
|
|
andw $0xfc00, %cx
|
|
shrw $10, %cx
|
|
movw %fs:0x13, %ax
|
|
subw %cx, %ax
|
|
movw %ax, %fs:0x13
|
|
|
|
/* Convert to segment address in %es */
|
|
shlw $6, %ax
|
|
movw %ax, %es
|
|
|
|
/* Restore registers and return */
|
|
popw %ax
|
|
popw %cx
|
|
ret
|
|
|
|
|
|
.section ".prefix"
|
|
.align 16
|
|
gdt:
|
|
gdt_limit: .word gdt_length - 1
|
|
gdt_base: .long gdt
|
|
.word 0 /* padding */
|
|
|
|
cs16: /* 16 bit code segment, base at real-mode %cs:0000 */
|
|
.equ CS16, cs16 - gdt
|
|
.word 0xffff, 0
|
|
.byte 0, 0x9b, 0, 0
|
|
|
|
ss16: /* 16 bit stack segment, base at real-mode %ss:0000 */
|
|
.equ SS16, ss16 - gdt
|
|
.word 0xffff, 0
|
|
.byte 0, 0x93, 0, 0
|
|
|
|
flat_ds: /* 16 bit data segment, zero base, 4GB limit */
|
|
.equ FLAT_DS, flat_ds - gdt
|
|
.word 0xffff, 0
|
|
.byte 0, 0x9f, 0xcf, 0
|
|
|
|
gdt_end:
|
|
.equ gdt_length, gdt_end - gdt
|
|
|
|
|
|
|
|
|
|
.section ".prefix"
|
|
.code16
|
|
prot16_call:
|
|
|
|
|
|
/* Install .data16 to top of base memory */
|
|
movw %cs, %ax
|
|
addw $_data16_load_offset_pgh, %ax
|
|
movw %ax, %ds
|
|
movw $_data16_size, %cx
|
|
call alloc_basemem
|
|
xorw %si, %si
|
|
xorw %di, %di
|
|
movw $_data16_progbits_size, %cx
|
|
rep movsb /* or "call decompress16" */
|
|
|
|
/* Install .code16 to top of base memory */
|
|
movw %cs, %ax
|
|
addw $_code16_load_offset_pgh, %ax
|
|
movw %ax, %ds
|
|
movw $_code16_size, %cx
|
|
call alloc_basemem
|
|
xorw %si, %si
|
|
xorw %di, %di
|
|
rep movsb /* or "call decompress16" */
|
|
|
|
/* Push flags and real-mode segment registers */
|
|
pushfl
|
|
push %gs
|
|
push %fs
|
|
push %es
|
|
push %ds
|
|
push %ss
|
|
push %cs
|
|
|
|
/* Physical address of %cs:0000 to %ebx, of %ss:0000 to %eax */
|
|
xorl %ebx, %ebx
|
|
movw %cs, %bx
|
|
shll $4, %ebx
|
|
xorl %eax, %eax
|
|
movw %ss, %ax
|
|
shll $4, %eax
|
|
|
|
/* Set up GDT and switch to protected mode */
|
|
addl %ebx, %cs:gdt_base
|
|
orl %ebx, %cs:(cs16+2)
|
|
orl %eax, %cs:(ss16+2)
|
|
cli
|
|
data32 lgdt %cs:gdt
|
|
movl %cr0, %eax
|
|
orb $CR0_PE, %al
|
|
movl %eax, %cr0
|
|
data32 ljmp $CS16, $1f
|
|
1: movw $SS16, %ax
|
|
movw %ax, %ss
|
|
movw $FLAT_DS, %ax
|
|
movw %ax, %ds
|
|
movw %ax, %es
|
|
movw %ax, %fs
|
|
movw %ax, %gs
|
|
|
|
/* Install .text and .data to 2MB mark. Use 2MB to avoid
|
|
* having to deal with A20.
|
|
*/
|
|
leal _text_load_offset(%ebx), %esi
|
|
movl $( 2 * 1024 * 1024 ), %edi
|
|
movl $_text_and_data_progbits_size, %ecx
|
|
addr32 rep movsb /* or "call decompress16" */
|
|
|
|
/* Restore real-mode segment limits */
|
|
movw %ss, %ax
|
|
movw %ax, %ds
|
|
movw %ax, %es
|
|
movw %ax, %fs
|
|
movw %ax, %gs
|
|
|
|
/* Return to real mode, restore segment registers and flags */
|
|
pushw $1f
|
|
movl %cr0, %eax
|
|
andb $0!CR0_PE, %al
|
|
movl %eax, %cr0
|
|
lret /* used as equivalent of pop %cs */
|
|
1: pop %ss
|
|
pop %ds
|
|
pop %es
|
|
pop %fs
|
|
pop %gs
|
|
popfl
|
|
|
|
/* Call init_gdt */
|
|
pushw %cs
|
|
pushw $1f
|
|
pushw %es
|
|
pushw $init_gdt
|
|
lret /* lcall %es:init_gdt */
|
|
1:
|
|
|
|
|
|
|
|
ret
|
|
|
|
|