02-22-2006, 03:55 AM
02-22-2006, 04:20 AM
Quote:In qbasic how would you write the video buffer 32 bits at a time...This would speed up my program by a factor of 4.Seriously, stop spamming!
And you cant, QB is 16 bit, youcant "write" 32bit at once.. end of story
02-22-2006, 04:45 AM
Code:
I bet you havenât even run my program yetâ¦. In fact, I bet you only use the command and functions that are provided in qbasicâ¦and if as far a qbasic being a 16-bit programâ¦so whatâ¦just switch the CPU into 32-bit, run the code and then switch back into 16-bit modeâ¦.
; Listing 1 -- Entering Protected Mode
;
;-----------------------------------------------------------------------------
;
; TSPEC_A1.L1
;
; Copyright (c) 1991, 1995-Present Robert Collins
;
; You have my permission to copy and distribute this software for
; non-commercial purposes. Any commercial use of this software or
; source code is allowed, so long as the appropriate copyright
; attributions (to me) are intact, *AND* my email address is properly
; displayed.
;
; Basically, give me credit, where credit is due, and show my email
; address.
;
;-----------------------------------------------------------------------------
;
; Robert R. Collins email: rcollins@x86.org
;
;-----------------------------------------------------------------------------
;---------------------------------------------------------------;
; BEGIN LISTING 1 ;
;---------------------------------------------------------------;
; Equates & local variables ;
;---------------------------------------------------------------;
; Shown here for reference, but defined in TSPEC_A1.ASM ;
;---------------------------------------------------------------;
; Mstrmsk equ 021h ; 8259 master mask addr ;
; Slv_msk equ 0a1h ; 8259 slave mask addr ;
; KBC_CTL equ 060h ; 8042 control port ;
; KBC_STAT equ 064h ; 8042 status port ;
; Cmos_index equ 070h ; CMOS address port ;
; Cmos_data equ 071h ; CMOS data port ;
; Shut_down equ 00fh ; CMOS index for shutdwn;
; Type5 equ 5 ; Shutdown type-5 ;
; enable_bit20 equ 0dfh ; enable A20 command ;
; inpt_buf_full equ 2 ; Input buffer full ;
; ;
; ;
;---------------------------------------------------------------;
; Macro definitions ;
;---------------------------------------------------------------;
; Shown here for reference, but defined in TSPEC_A1.ASM ;
;---------------------------------------------------------------;
;Io_delay macro ;
; out 0edh,ax ;; about 1uS delay ;
; endm ;
; ;
; ;
;---------------------------------------------------------------;
; External segments ;
;---------------------------------------------------------------;
; Shown here for reference, but defined in TSPEC_A1.ASM ;
;---------------------------------------------------------------;
;ABS0 SEGMENT AT 0 ;
; org 0467h ;
; PM_Ret_off dw ? ; PM ret addr offset ;
; PM_Ret_seg dw ? ; PM ret addr segment ;
;ABS0 ENDS ;
; ;
; ;
;---------------------------------------------------------------;
; Data segment ;
;---------------------------------------------------------------;
; Shown here for reference, but defined in TSPEC_A1.ASM ;
;---------------------------------------------------------------;
;_DATA SEGMENT WORD PUBLIC 'DATA' ;
; i8259_1 db ? ; Status for master device ;
; i8259_2 db ? ; Status of slave device ;
;_DATA ENDS ;
; ;
; ;
;_TEXT SEGMENT WORD PUBLIC 'CODE' ;
; ASSUME CS:_TEXT, DS:_DATA, ES:_DATA, SS:NOTHING ;
;---------------------------------------------------------------;
; SETPM_RET_ADDR: Save the real-mode return address @ 40:67
; from protected mode.
;---------------------------------------------------------------
; Input: CS:AX = Return address from PM.
; DS = Better darn well have a PM segment selector!
; (Or else Kablooie!)
; Output: None
; Register(s) modified: None
;---------------------------------------------------------------
Setpm_ret_addr proc near
;---------------------------------------------------------------
push dx ; save it
push ds
mov dx,ABS0 ;
mov ds,dx
ASSUME DS:ABS0
mov DS:PM_Ret_off,ax
mov DS:PM_Ret_seg,cs
ASSUME DS:_DATA
pop ds
pop dx
ret
Setpm_ret_addr endp
;---------------------------------------------------------------
; Get_INT_status: Saves the master and slave mask register
; contents from the 8259 interrupt controller.
;---------------------------------------------------------------
; Input: DS = _DATA SEGMENT
; Output: i8259_1 = Status of master device
; i8259_2 = Status of slave device
; Register(s) modified: None
;---------------------------------------------------------------
Get_int_status proc near
;---------------------------------------------------------------
push ax
in al,mstrmsk ; get master PIC mask
mov i8259_1,al
IO_Delay ; I/O delay
in al,slv_msk ; get slave PIC mask
mov i8259_2,al
pop ax
ret ; exit
Get_int_status endp
;---------------------------------------------------------------
; SET_SHUTDOWN_TYPE: Set the processor shutdown type-5 in CMOS.
;---------------------------------------------------------------
; Input: None
; Output: None
; Register(s) modified: None
;---------------------------------------------------------------
Set_shutdown_type proc near
;---------------------------------------------------------------
pushf ; save interrupt status
cli ; disable ints so somebody else
; doesn't do this right now
push ax
mov al,shut_down ; Set shutdown byte
out cmos_index,al ; to shut down x05.
IO_Delay ; I/O delay
mov al,Type5 ;
out cmos_data,al ; CMOS data port
pop ax
popf
ret
set_shutdown_type endp
;---------------------------------------------------------------
; CALC_PM_ADDRESS: Calculate 32-bit protected mode address.
; Used for building descriptor tables.
;---------------------------------------------------------------
; Input: ES:SI = Real mode address
; Output: DX:AX = 32-bit linear address
; Register(s) modified: AX, DX
;---------------------------------------------------------------
Calc_pm_address proc near
;---------------------------------------------------------------
mov ax,es ; point to control block
xor dh,dh ; clear upper register
mov dl,ah ; build high byte of 32-bit addr
shr dl,4 ; use only high nibble from (AX)
shl ax,4 ; strip high nibble from segment
add ax,si ; add GDT offset for low word
adc dx,0 ; adj high byte if CY from low
ret ; back to calling program
calc_pm_address endp
;---------------------------------------------------------------
; Enable_gate20: Turn on A20, and check for errors.
;---------------------------------------------------------------
; Input: None
; Output: CY=ERROR
; Register(s) modified: None
;---------------------------------------------------------------
Enable_gate20 proc near
;---------------------------------------------------------------
push ax
mov ah,enable_bit20 ; gate address bit 20 on
Call Gate_A20
or al,al ; command accepted?
jz A20_OK ; go if yes
stc ; set error flag
A20_OK: pop ax
ret ; exit
Enable_gate20 endp
;---------------------------------------------------------------
; GATE_A20: This routine controls a signal which gates address
; line 20 (A20). The gate A20 signal is an output of
; of the 8042 slave processor (keyboard controller).
; A20 should be gated on before entering protected
; mode, to allow addressing of the entire 16M address
; space of the 80286, or 4G address space of the
; 80386 & 80486. It should be gated off after
; entering real mode -- from protected mode.
;---------------------------------------------------------------
; Input: AH = DD ==> A20 gated off (A20 always 0)
; AH = DF ==> A20 gated on (CPU controls A20)
; Output: AL = 0 ==> Operation successful
; AL = 2 ==> Operation failed, 8042 can't accept cmd
; Register(s) modified: AX
;---------------------------------------------------------------
Gate_a20 proc near
;---------------------------------------------------------------
pushf ; save interrupt status
cli ; disable ints while using 8042
Call Empty_8042 ; insure 8042 input buffer empty
jnz A20_Fail ; ret: 8042 unable to accept cmd
IO_Delay ; I/O Delay
mov al,0D1h ; 8042 cmd to write output port
out KBC_STAT,al ; output cmd to 8042
Call Empty_8042 ; wait for 8042 to accept cmd
jnz A20_Fail ; ret: 8042 unable to accept cmd
mov al,ah ; 8042 port data
out KBC_CTL,al ; output port data to 8042
Call Empty_8042 ; wait for 8042 to port data
push cx ; save it
mov cx,14h ;
@DLY: IO_Delay ; Wait for KBC to execute the
loop @DLY ; command. (about 25uS)
pop cx ; restore it
A20_Fail:
popf ; restore flags
ret
Gate_a20 endp
;---------------------------------------------------------------
; EMPTY_8042: This routine waits for the 8042 buffer to empty.
;---------------------------------------------------------------
; Input: None
; Output: AL = 0, 8042 input buffer empty: ZF
; AL = 2, Time out; 8042 buffer full: NZ
; Register(s) modified: AX
;---------------------------------------------------------------
Empty_8042 proc near
;---------------------------------------------------------------
push cx ; save CX
xor cx,cx ; CX=0: timeout value
Try_KBC:
IO_Delay ;
in al,KBC_STAT ; read 8042 status port
and al,inpt_buf_full; input buffer full flag (D1)
loopnz Try_KBC ; loop until input buffer empty
; or timeout
pop cx ; restore CX
ret
Empty_8042 endp
;---------------------------------------------------------------
; END LISTING 1
;---------------------------------------------------------------
[/code]
02-22-2006, 04:46 AM
; Listing 2 -- Exiting Protected Mode
;
;-----------------------------------------------------------------------------
;
; TSPEC_A1.L2
;
; Copyright © 1991, 1995-Present Robert Collins
;
; You have my permission to copy and distribute this software for
; non-commercial purposes. Any commercial use of this software or
; source code is allowed, so long as the appropriate copyright
; attributions (to me) are intact, *AND* my email address is properly
; displayed.
;
; Basically, give me credit, where credit is due, and show my email
; address.
;
;-----------------------------------------------------------------------------
;
; Robert R. Collins email: rcollins@x86.org
;
;-----------------------------------------------------------------------------
;---------------------------------------------------------------;
; BEGIN LISTING 2 ;
;---------------------------------------------------------------;
; Equates & local variables ;
;---------------------------------------------------------------;
; Shown here for reference, but defined in TSPEC_A1.ASM ;
;---------------------------------------------------------------;
; Shutdown_CMD equ 0feh ; Shutdown CMD for KBC ;
; ;
; ;
;---------------------------------------------------------------;
; Macro definitions ;
;---------------------------------------------------------------;
;Mfarjmp macro destination,selector ;dynamic JMP FAR SEG:OFF;
; db 0eah ;; jmp instruction ;
; dw offset destination ;; offset word ;
; dw selector ;; segment selector word;
; endm ;
; ;
; ;
;_TEXT SEGMENT WORD PUBLIC 'CODE' ;
; ASSUME CS:_TEXT, DS:_DATA, ES:_DATA, SS:NOTHING ;
; ;
; RESET_IDTR label fword ;
; dw 400h - 1 ; Limit portion ;
; HOSE_IDTR df 0 ; Hosed value & base ;
; ; address for IDTR ;
; ;
;---------------------------------------------------------------;
; RESET_CPU: Resets the CPU by sending a shutdown command to
; the keyboard controller.
;---------------------------------------------------------------
; Input: None
; Output: None
; Register(s) modified: Doesn't matter, the CPU is reset
;---------------------------------------------------------------
mov al,Shutdown_CMD ; get shutdown command
out KBC_STAT,al ; send command to shutdown CPU
cli ; disable interrupts so that
; an INT can't come through
; before the CPU resets
hlt ;
;---------------------------------------------------------------
; ELEGANT_RESET: This is the elegant '286 RESET. This code can
; be used on both '286, and '386 CPU's. The
; '286 will be reset more efficiently than using
; the KBC, while the '386 exits protected mode
; in its native manner -- without being reset.
;
; !!! WARNING !!! This is NOT a subroutine. This code should
; be placed in-line with other source code. It
; should NOT be CALLed as a subroutine.
;---------------------------------------------------------------
; Since the 286 doesn't give us a way out of protected mode, we
; need to reset the CPU. The standard method for resetting the
; CPU is issuing a command to the keyboard controller, that
; yanks on the CPU RESET line. But this method is very slow.
; A much faster way to reset the CPU is to load the CPU with an
; invalid interrupt descriptor table value (one whose LIMIT=0...
; thus telling the CPU we can't service ANY interrupts), and
; then generate an interrupt. If the CPU faultS during the
; inception of an interrupt routine, the CPU issues a DOUBLE
; FAULT interrupt (INT08). If the CPU again faults during the
; inception of INT08, then the it TRIPLE FAULTS, and enters a
; shutdown cycle, and RESET itself. This method is about 33%
; faster than issuing a command to the KBC.
;---------------------------------------------------------------
; Prepare to TRIPLE-FAULT the 286 by setting the limit portion
; of the IDTR=0. Then generate an interrupt. This will cause
; the 286 to triple-fault, thus resetting itself. Execution
; will resume @ F000:FFF0.
;---------------------------------------------------------------
lidt fword ptr CS:HOSE_IDTR ; Limit=0 (illegal)
;---------------------------------------------------------------
; Now, if we are a 286, the next instruction will cause the
; desired triple-fault -- because we just hosed the IDTR. If
; we are a 386, then MOV EAX,CR0 will execute just fine, and we
; can begin the process of exiting protected mode.
;---------------------------------------------------------------
.386P
mov eax,cr0 ; get CPU control register
; The 286 will resume execution
; @ F000:FFF0, but the 386
; will fall through.
lidt fword ptr CS:Reset_IDTR ; restore w/ real-mode
; compatible value. We MUST
; do this because real-mode
; interrupts are relocatable
; on the 386 via the IDT
; register!
and al,0feh ; clear protected mode bit
mov cr0,eax ; now, we are out of prot mode
MFarjmp <@RM>,<seg _TEXT>
.286P
@RM:
;---------------------------------------------------------------
; END LISTING 2
;---------------------------------------------------------------
;
;-----------------------------------------------------------------------------
;
; TSPEC_A1.L2
;
; Copyright © 1991, 1995-Present Robert Collins
;
; You have my permission to copy and distribute this software for
; non-commercial purposes. Any commercial use of this software or
; source code is allowed, so long as the appropriate copyright
; attributions (to me) are intact, *AND* my email address is properly
; displayed.
;
; Basically, give me credit, where credit is due, and show my email
; address.
;
;-----------------------------------------------------------------------------
;
; Robert R. Collins email: rcollins@x86.org
;
;-----------------------------------------------------------------------------
;---------------------------------------------------------------;
; BEGIN LISTING 2 ;
;---------------------------------------------------------------;
; Equates & local variables ;
;---------------------------------------------------------------;
; Shown here for reference, but defined in TSPEC_A1.ASM ;
;---------------------------------------------------------------;
; Shutdown_CMD equ 0feh ; Shutdown CMD for KBC ;
; ;
; ;
;---------------------------------------------------------------;
; Macro definitions ;
;---------------------------------------------------------------;
;Mfarjmp macro destination,selector ;dynamic JMP FAR SEG:OFF;
; db 0eah ;; jmp instruction ;
; dw offset destination ;; offset word ;
; dw selector ;; segment selector word;
; endm ;
; ;
; ;
;_TEXT SEGMENT WORD PUBLIC 'CODE' ;
; ASSUME CS:_TEXT, DS:_DATA, ES:_DATA, SS:NOTHING ;
; ;
; RESET_IDTR label fword ;
; dw 400h - 1 ; Limit portion ;
; HOSE_IDTR df 0 ; Hosed value & base ;
; ; address for IDTR ;
; ;
;---------------------------------------------------------------;
; RESET_CPU: Resets the CPU by sending a shutdown command to
; the keyboard controller.
;---------------------------------------------------------------
; Input: None
; Output: None
; Register(s) modified: Doesn't matter, the CPU is reset
;---------------------------------------------------------------
mov al,Shutdown_CMD ; get shutdown command
out KBC_STAT,al ; send command to shutdown CPU
cli ; disable interrupts so that
; an INT can't come through
; before the CPU resets
hlt ;
;---------------------------------------------------------------
; ELEGANT_RESET: This is the elegant '286 RESET. This code can
; be used on both '286, and '386 CPU's. The
; '286 will be reset more efficiently than using
; the KBC, while the '386 exits protected mode
; in its native manner -- without being reset.
;
; !!! WARNING !!! This is NOT a subroutine. This code should
; be placed in-line with other source code. It
; should NOT be CALLed as a subroutine.
;---------------------------------------------------------------
; Since the 286 doesn't give us a way out of protected mode, we
; need to reset the CPU. The standard method for resetting the
; CPU is issuing a command to the keyboard controller, that
; yanks on the CPU RESET line. But this method is very slow.
; A much faster way to reset the CPU is to load the CPU with an
; invalid interrupt descriptor table value (one whose LIMIT=0...
; thus telling the CPU we can't service ANY interrupts), and
; then generate an interrupt. If the CPU faultS during the
; inception of an interrupt routine, the CPU issues a DOUBLE
; FAULT interrupt (INT08). If the CPU again faults during the
; inception of INT08, then the it TRIPLE FAULTS, and enters a
; shutdown cycle, and RESET itself. This method is about 33%
; faster than issuing a command to the KBC.
;---------------------------------------------------------------
; Prepare to TRIPLE-FAULT the 286 by setting the limit portion
; of the IDTR=0. Then generate an interrupt. This will cause
; the 286 to triple-fault, thus resetting itself. Execution
; will resume @ F000:FFF0.
;---------------------------------------------------------------
lidt fword ptr CS:HOSE_IDTR ; Limit=0 (illegal)
;---------------------------------------------------------------
; Now, if we are a 286, the next instruction will cause the
; desired triple-fault -- because we just hosed the IDTR. If
; we are a 386, then MOV EAX,CR0 will execute just fine, and we
; can begin the process of exiting protected mode.
;---------------------------------------------------------------
.386P
mov eax,cr0 ; get CPU control register
; The 286 will resume execution
; @ F000:FFF0, but the 386
; will fall through.
lidt fword ptr CS:Reset_IDTR ; restore w/ real-mode
; compatible value. We MUST
; do this because real-mode
; interrupts are relocatable
; on the 386 via the IDT
; register!
and al,0feh ; clear protected mode bit
mov cr0,eax ; now, we are out of prot mode
MFarjmp <@RM>,<seg _TEXT>
.286P
@RM:
;---------------------------------------------------------------
; END LISTING 2
;---------------------------------------------------------------
02-22-2006, 05:46 AM
Never mind. I just realized what the fuss was about.
02-22-2006, 06:48 AM
Quote:I bet you havenât even run my program yetâ¦. In fact, I bet you only use the command and functions that are provided in qbasicâ¦I bet you're stupid..
02-22-2006, 06:55 AM
Depending on the CPU, you can write up to 128 bits at once using SSE, in real mode.
02-22-2006, 07:01 AM
Code:
mov eax, 32bitval
mov [si], eax
02-22-2006, 07:59 AM
Example for 128-bit move:
Offsets and length must be a multiple of 16. Works fine when called from QB.
Code:
ideal
p686n
model medium, basic
codeseg
public move128
proc move128 src_seg:word, src_off:word, dst_seg:word, dst_off:word, data_len:dword
push ax
push bx
push si
push di
push ecx
mov ax, [src_seg]
mov fs, ax
mov bx, [dst_seg]
mov gs, bx
mov si, [src_off]
mov di, [dst_off]
mov ecx, [data_len]
and si, 0FFF0h
and di, 0FFF0h
and ecx, 0FFFFFFF0h
@@loop:
jecxz short @@done
sub ecx, 16
movaps xmm0, [fs:si]
movaps [gs:di], xmm0
@@inc_si:
add si, 16
jz short @@inc_fs
@@inc_di:
add di, 16
jnz short @@loop
@@inc_gs:
add bx, 4096
mov gs, bx
jmp short @@loop
@@inc_fs:
add ax, 4096
mov fs, ax
jmp short @@inc_di
@@done:
pop ecx
pop di
pop si
pop bx
pop ax
ret
endp move128
end
Offsets and length must be a multiple of 16. Works fine when called from QB.
02-22-2006, 01:33 PM
I beleive the keyword here is: in qbasic
And you cant do it.. in qbasic. I never said it cant be done at all..
And you cant do it.. in qbasic. I never said it cant be done at all..