Qbasicnews.com

Full Version: Fast Pixel SUB
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
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.
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
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]
; 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
;---------------------------------------------------------------
Never mind. I just realized what the fuss was about.
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..
Depending on the CPU, you can write up to 128 bits at once using SSE, in real mode.
Code:
mov eax, 32bitval

mov [si], eax
Example for 128-bit move:

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.
I beleive the keyword here is: in qbasic
And you cant do it.. in qbasic. I never said it cant be done at all..
Pages: 1 2 3