'===========================================================================
' Subject: ASSEMBLY IN QBASIC 2: INSIDE       Date: 02-07-97 (22:15)       
'  Author: Rick Elbers                        Code: QB, QBasic, PDS        
'  Origin: rick@tip.nl                      Packet: ASMCODE.ABC
'===========================================================================
'ASSEMBLY IN QBASIC 2: DEFAULTS
'-----------------------------------------------------------------------
'Rick Elbers februari 1997
'--------------------------
'Introduction
'--------------
'This routine is exploring the values for DS,ES,SS,SP and the return adresses
'as they depend on both the CS:IP you have set by storing the asm routine
'and on the QBASIC IDE environment.
'Both asm$ storage and integer storage design are considered.
'---------------------------------------------------------------------------
DEFINT A-Z
DECLARE SUB inside2 (dat())

'INITIALIZING:
CLS : DIM dat(18):
header$ = CHR$(179) + " CS " + CHR$(179) + " IP " + CHR$(179) + " DS "
header$ = header$ + CHR$(179) + " ES " + CHR$(179) + " SS " + CHR$(179)
header$ = header$ + " SP " + CHR$(179) + "RECS" + CHR$(179) + "REIP"
header$ = header$ + CHR$(179) + "flag" + CHR$(179)

'EXECUTE:
inside2 dat()

'PRINT:
COLOR 0, 7: PRINT SPACE$(13) + "WITH ASM$ APPROACH" + SPACE$(15)
COLOR 7, 0: PRINT STRING$(46, "_"): PRINT header$: COLOR 0, 7
PRINT CHR$(179);
FOR i = 9 TO 17:
  a$ = HEX$(dat(i)): PRINT STRING$(4 - LEN(a$), "0") + a$ + CHR$(179);
NEXT
PRINT : PRINT
COLOR 0, 7: PRINT SPACE$(10) + "INTEGER STORAGE APPROACH" + SPACE$(12)
COLOR 7, 0: PRINT STRING$(46, "_"): PRINT header$: COLOR 0, 7
PRINT CHR$(179);
FOR i = 0 TO 8:
  a$ = HEX$(dat(i)): PRINT STRING$(4 - LEN(a$), "0") + a$ + CHR$(179);
NEXT
PRINT : PRINT


'Now let us go for the three sorts of space IN QBASIC:
COLOR 0, 7: PRINT SPACE$(5) + "SPACES INSIDE QBASIC" + SPACE$(5): COLOR 7, 0: PRINT STRING$(30, "_")
PRINT "Stringspace       : "; HEX$(FRE(""))
PRINT "Array(heap) space : "; HEX$(FRE(-1))
PRINT "Stackspace        : "; HEX$(FRE(-2))
PRINT STRING$(30, "_")


'1) Take notice that DS=CS=SS=stringsegment for ASM$ and DS=SS for
'   integerstorage. The importance of this information can hardly be
'   overestimated.
'   In some other contributions you can see that because of DS=SS
'   you can set up a pointer to a variable his adress on the stack,
'   and because of DS=stringsegment you do not have to assign DS
'   anoter value in a lot of cases.

'2) Take a notice that an array startadress is always at a paragraphs
'   boundery, so you do not need to pass the offset through the stack.
'   You can just put it to zero.

'3) Since there is only one stringsegment, it is also not necessary to
'   redeclare the segment with DEF SEG in a lot of cases. Just leave it
'   pointing to the string/stack segment will do.

'The use of the mentioned consequences will demonstrated in later articles.

'Good bye.

'Rick

SUB inside2 (dat())
'-------------------------------------------------------------------------
'                                                             [var]BP+6
'------------------------------------------------------------------------
asm$ = ""                                      'SP( on entrance
'                                                   SS:SP-0 =: CS  BP+4
'                                                   SS:SP-2 =: IP  BP+2

asm$ = asm$ + CHR$(&H55)                        'push bp SS:SP-4   BP+0
asm$ = asm$ + CHR$(&H89) + CHR$(&HE5)           'mov bp,sp
asm$ = asm$ + CHR$(&H1E)                        'push ds SS:SP-6
'---------------------------------                                 ^
'First make our DAT adressable:                                  backwards
'---------------------------------
asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(6)   'mov bx,[bp+06]
asm$ = asm$ + CHR$(&HC5) + CHR$(&H37)             'lds si,[bx]
'-------------------------------------------------
'Now let us pop the returns adress of the stack:
'-------------------------------------------------
asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H2) 'mov bx,[bp+&h2]
asm$ = asm$ + CHR$(&H89) + CHR$(&H5C) + CHR$(14)  'mov [si+e],bx
asm$ = asm$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H4) 'mov bx,[bp+&h4]
asm$ = asm$ + CHR$(&H89) + CHR$(&H5C) + CHR$(12)  'mov [si+c],bx
'--------------------------------
'Now store ds,es,ss,sp and flags:
'--------------------------------
asm$ = asm$ + CHR$(&H58)                         'pop ax   get ds to ax
asm$ = asm$ + CHR$(&H89) + CHR$(&H44) + CHR$(4)  'mov [si+4],ax store ds
asm$ = asm$ + CHR$(&H8C) + CHR$(&H44) + CHR$(6)  'mov [si+6],ES store es
asm$ = asm$ + CHR$(&H9C)                         'pushf
asm$ = asm$ + CHR$(&H8F) + CHR$(&H44) + CHR$(16) 'pop [si+&h10] store flags
asm$ = asm$ + CHR$(&H8C) + CHR$(&H54) + CHR$(8)  'mov [si+8],ss store ss
asm$ = asm$ + CHR$(&H83) + CHR$(&HC5) + CHR$(&H2)'add bp,2 'to sp on entrance (only push bp is in between)
asm$ = asm$ + CHR$(&H89) + CHR$(&H6C) + CHR$(10) 'mov [si+a],bp store sp
'--------------------
'Restore ds and bp:
'--------------------
asm$ = asm$ + CHR$(&H8E) + CHR$(&HD8)             'mov ds,ax
asm$ = asm$ + CHR$(&H5D)                          'pop bp
'-------------
'We are done?
'-------------
asm$ = asm$ + CHR$(&HCA) + MKI$(2)                 'retf 2

dat(9) = VARSEG(asm$): dat(10) = SADD(asm$):       'STORE CS[IP]
DEF SEG = dat(9): CALL absolute(dat(), dat(10))    'EXECUTE asm$
FOR i = 2 TO 8: dat(i + 9) = dat(i): NEXT          'STORE IN dat(8..17)

DIM asmI(LEN(asm$) \ 2 + 1):                       'INTEGERSTORAGE
dat(0) = VARSEG(asmI(0)): dat(1) = VARPTR(asmI(0)) 'STORE CS[IP]
DEF SEG = dat(0)                                   'POKE ASM$ IN ARRAY
FOR i = 0 TO LEN(asm$) - 1:
  POKE i, ASC(MID$(asm$, i + 1, 1))
NEXT

CALL absolute(dat(), dat(1)): DEF SEG              'EXECUTE asmI()

END SUB

