Compare commits

...
Author SHA1 Message Date
James Gregory
4028269fe1
Merge pull request #43 from thp/code-fixes
Code fixes
2020-05-21 19:30:04 +10:00
Thomas Perl
d54e14ca74 CurrentColordb -> CurrentColor db 2020-05-21 11:25:45 +02:00
Thomas Perl
4b5c169695 COLOR_ENTRY_LENGTHequ -> COLOR_ENTRY_LENGTH equ 2020-05-21 11:25:15 +02:00
Thomas Perl
8d29240973 loopDrawDiagonalLoop -> loop DrawDiagonalLoop 2020-05-21 11:24:43 +02:00
Thomas Perl
7388cf370c loopVLineLoop -> loop VLineLoop 2020-05-21 11:24:18 +02:00
Thomas Perl
beff664727 labelbyte -> label byte 2020-05-21 11:23:42 +02:00
Thomas Perl
b9bf2eb0ed _DATAsegmentpublic -> _DATA segment public 2020-05-21 11:14:12 +02:00
Thomas Perl
1a87045a95 pus h -> push 2020-05-21 11:13:30 +02:00
Thomas Perl
28e420e665 Fix ASM OCR of macros 2020-05-21 11:13:06 +02:00
Thomas Perl
51194d4928 not40h -> not 40h 2020-05-21 11:12:28 +02:00
Thomas Perl
b96792917b Fix more ASM calling (OCR) 2020-05-21 11:12:10 +02:00
Thomas Perl
73e56070b4 Fix function calling (OCR) 2020-05-21 11:11:50 +02:00
Thomas Perl
6adf8f912b Fix cmpcx->cmp cx 2020-05-21 11:11:16 +02:00
Thomas Perl
f2025ac6e8 Add missing ; for ASM comment 2020-05-21 11:10:54 +02:00
Thomas Perl
700514a488 Code OCR fix: lodsbyte -> lods byte 2020-05-21 11:10:09 +02:00
Thomas Perl
f87c4484c2 Fix db512->db 512 2020-05-21 11:09:07 +02:00
Thomas Perl
2342c2d49d Fix typo 2020-05-21 11:08:49 +02:00
Thomas Perl
670082d347 Fix MAXIMUM_SCAN_LINEequ 2020-05-21 11:08:17 +02:00
Thomas Perl
03978b9651 Fix looping/calling OCR bugs 2020-05-21 11:07:47 +02:00
Thomas Perl
a4df877739 Datasegment -> Data segment 2020-05-21 11:07:02 +02:00
Thomas Perl
b3144a2145 Startproc near -> Start proc near 2020-05-21 11:06:40 +02:00
Thomas Perl
9072e5d500 Fix various (ends) code OCR errors 2020-05-21 11:06:10 +02:00
Thomas Perl
97d436fb73 Fix 'endp' -> ' endp'
Automatically done using:

    sed -i '' -e 's/\([^ ]\)endp/\1 endp/g' src/*.md
2020-05-21 10:55:36 +02:00
Thomas Perl
9373e5d2ee Fix 'procnear' -> ' proc near'
Automatically done using:

    sed -i '' -e 's/procnear/ proc near/g' src/*.md
2020-05-21 10:54:08 +02:00
12 changed files with 94 additions and 94 deletions

View file

@ -754,12 +754,12 @@ Parms struc
Buffer dw ?
BufferLength dw ?
Checksum dw ?
Parmsends
Parms ends
;
.model small
.code
public _ChecksumChunk
_ChecksumChunkprocnear
_ChecksumChunk proc near
push bp
mov bp,sp
push si ;save C's register variable
@ -779,7 +779,7 @@ ChecksumLoop:
pop si ;restore C's register variable
pop bp
ret
_ChecksumChunkendp
_ChecksumChunk endp
end
```

View file

@ -245,7 +245,7 @@ the whole point.)
.stack 100h
.data
; Sample string to search through.
SampleString labelbyte
SampleString label byte
db This is a sample string of a long enough length '
db so that raw searching speed can outweigh any '
db extra set-up time that may be required.',0
@ -263,7 +263,7 @@ NoByteFoundMsg db 0dh,0ah
db Buffer exhausted with no match.', 0dh, 0ah, $'
.code
Startprocnear
Start proc near
mov ax,@data ;point to standard data segment
mov ds,ax
mov dx,offset Prompt
@ -289,7 +289,7 @@ PrintStatus:
int 21h ;report status
mov ah,4ch ;return to DOS
int 21h
Startendp
Start endp
; Function to search a buffer of a specified length until either a
; specified byte or a zero byte is encountered.
@ -306,7 +306,7 @@ Startendp
; byte is found
; Carry Flag = set if searched-for byte found, reset otherwise
SearchMaxLengthprocnear
SearchMaxLength proc near
cld
SearchMaxLengthLoop:
lodsb ;get the next byte
@ -324,7 +324,7 @@ ByteFound:
;we found the searched-for byte
stc ;return "found" status
ret
SearchMaxLengthendp
SearchMaxLength endp
end Start
```
@ -350,7 +350,7 @@ all the difference.
.stack 100h
.data
; Sample string to search through.
SampleStringlabelbyte
SampleString label byte
db This is a sample string of a long enough length '
db so that raw searching speed can outweigh any '
db extra set-up time that may be required.',0
@ -403,7 +403,7 @@ PrintStatus:
mov ah,4ch ;return to DOS
int 21h
Startendp
Start endp
; Function to search a buffer of a specified length until either a
; specified byte or a zero byte is encountered.
@ -468,7 +468,7 @@ ByteFound:
; we found the searched-for byte
stc ;return "found" status
ret
SearchMaxLengthendp
SearchMaxLength endp
end Start
```

View file

@ -395,7 +395,7 @@ Parmsends
.model small
.code
public _FindString
_FindStringprocnear
_FindString proc near
push bp ;preserve caller's stack frame
mov bp,sp ;point to our stack frame
push si ;preserve caller's register variables
@ -458,7 +458,7 @@ FindStringDone:
pop si
pop bp ;restore caller's stack frame
ret
_FindStringendp
_FindString endp
end
```
@ -492,7 +492,7 @@ Parmsends
.model small
.code
public _FindString
_FindStringprocnear
_FindString proc near
push bp ;preserve caller's stack frame
mov bp,sp ;point to our stack frame
push si ;preserve caller's register variables
@ -559,7 +559,7 @@ FindStringDone:
pop si
pop bp ;restore caller's stack frame
ret
_FindStringendp
_FindString endp
end
```
@ -743,7 +743,7 @@ parmsends
.model small
.code
public _Div
_Divprocnear
_Div proc near
push bp ;preserve caller's stack frame
mov bp,sp ;point to our stack frame
push si ;preserve caller's register variables
@ -778,7 +778,7 @@ DivLoop:
pop si
pop bp ;restore caller's stack frame
ret
_Divendp
_Div endp
end
```

View file

@ -85,12 +85,12 @@ registers.
;
; By Michael Abrash
;
stacksegmentword stack 'STACK'
db512 dup (?)
stackends
stack segment word stack 'STACK'
db 512 dup (?)
stack ends
;
datasegment word 'DATA'
IMAGE_WIDTHEQU 4 ;in bytes
data segment word 'DATA'
IMAGE_WIDTH EQU 4 ;in bytes
IMAGE_HEIGHT EQU 32 ;in pixels
LEFT_BOUND EQU 10 ;in bytes
RIGHT_BOUND EQU 66 ;in bytes
@ -105,11 +105,11 @@ READ_MAP EQU 4 ;Read Map register index in GC
;
PatternPlane0 label byte
db 32 dup (0ffh,0ffh,0,0)
PatternPlane1 labelbyte
PatternPlane1 label byte
db 32 dup (0ffh,0,0ffh,0)
PatternPlane2 labelbyte
PatternPlane2 label byte
db 32 dup (0f0h,0f0h,0f0h,0f0h)
PatternPlane3 labelbyte
PatternPlane3 label byte
db 32 dup (0cch,0cch,0cch,0cch)
;
; Temporary storage for 16-color image during animation.
@ -124,7 +124,7 @@ ImagePlane3 db 32*4 dup (?)
ImageX dw 40 ;in bytes
ImageY dw 100 ;in pixels
ImageXDirection dw 1 ;in bytes
dataends
data ends
;
code segment word 'CODE'
assume cs:code,ds:data
@ -197,12 +197,12 @@ DelayLoop:
int 10h
mov ah,4ch
int 21h
Startendp
Start endp
;
; Draws the image at offset DS:SI to the current image location in
; VGA memory.
;
DrawImageprocnear
DrawImage proc near
mov ax,VGA_SEGMENT
mov es,ax
call GetImageOffset ;ES:DI is the destination address for the
@ -233,7 +233,7 @@ DrawImageLoop:
cmp al,10h ;have we done all four planes?
jnz DrawImagePlaneLoop
ret
DrawImageendp
DrawImage endp
;
; Copies the image from its current location in VGA memory into the
; buffer at DS:DI.
@ -274,7 +274,7 @@ GetImageLoop:
push es
pop ds ;restore original DS
ret
GetImageendp
GetImage endp
;
; Erases the image at its current location.
;
@ -435,7 +435,7 @@ VLineLoop:
; provides the data written to display
; memory, and AL is actually ignored)
add di,SCREEN_WIDTH-1 ;point to the next scan line
loopVLineLoop
loop VLineLoop
;
; Select write mode 0 and read mode 1.
;
@ -513,12 +513,12 @@ WaitKeyLoop:
int 10h ;return to text mode
mov ah,4ch
int 21h ;done
Startendp
Start endp
;
; Enables set/reset for all planes, and sets the set/reset color
; to AL.
;
SelectSetResetColorprocnear
SelectSetResetColor proc near
mov dx,GC_INDEX
push ax ;preserve color
mov al,SET_RESET
@ -533,7 +533,7 @@ SelectSetResetColorprocnear
mov al,0fh
out dx,al ;enable set/reset for all planes
ret
SelectSetResetColorendp
SelectSetResetColor endp
code ends
end Start
```
@ -636,7 +636,7 @@ COLOR_DONT_CARE EQU 7 ;Color Don't Care register index in GC
;
code segment word 'CODE'
assume cs:code
Startprocnear
Start proc near
;
; Select graphics mode 12h.
;
@ -698,7 +698,7 @@ DrawDiagonalLoop:
; point to the next scan line
ror al,1 ;move the pixel mask one pixel to the right
adc bx,0 ;advance to the next byte if the pixel mask wrapped
loopDrawDiagonalLoop
loop DrawDiagonalLoop
;
; Wait for a key to be pressed to end, then return to text mode and
; return to DOS.
@ -713,7 +713,7 @@ WaitKeyLoop:
int 10h ;return to text mode
mov ah,4ch
int 21h ;done
Startendp
Start endp
code ends
end Start
```

View file

@ -557,14 +557,14 @@ x= x+1
; Used to label the colors of the color bars. (Color values are
; filled in on the fly.)
;
ColorNumberslabelbyte
ColorNumbers label byte
rept 16
db 000h', 0ah, 8, 8, 8, 8
endm
COLOR_ENTRY_LENGTHequ($-ColorNumbers)/16
COLOR_ENTRY_LENGTH equ ($-ColorNumbers)/16
db $'
;
CurrentColordb?
CurrentColor db ?
;
; Space for the array of 16 colors we'll pass to the BIOS, plus
; an overscan setting of black.
@ -574,7 +574,7 @@ Data ends
;
Code segment
assume cs:Code, ds:Data
Start procnear
Start proc near
cld
mov ax,Data
mov ds,ax
@ -764,7 +764,7 @@ ColorNumberLoop:
mov dx,offset ColorNumbers
int 21h ;put up the attribute numbers
ret
ColorNumbersUpendp
ColorNumbersUp endp
;
Start endp
Code ends
@ -820,7 +820,7 @@ WAIT_KEY macro
endm
;
stack segment para stack STACK'
db512 dup (?)
db 512 dup (?)
stack ends
;
Data segment word DATA'

View file

@ -146,7 +146,7 @@ SCREEN_WIDTH equ 640
SCREEN_HEIGHT equ 350
CRTC_INDEX equ 3d4h ;CRT Controller Index register
OVERFLOW equ 7 ;index of Overflow reg in CRTC
MAXIMUM_SCAN_LINEequ 9 ;index of Maximum Scan Line register
MAXIMUM_SCAN_LINE equ 9 ;index of Maximum Scan Line register
; in CRTC
START_ADDRESS_HIGH equ 0ch ;index of Start Address High register
; in CRTC
@ -318,7 +318,7 @@ CountVerticalSyncsLoop:
int 10h ;return to text mode
mov ah,4ch
int 21h ;return to DOS
Startendp
Start endp
;*********************************************************************
; Waits for the leading edge of the vertical sync pulse.
;
@ -328,7 +328,7 @@ Startendp
;
; Registers altered: AL, DX
;
WaitForVerticalSyncStartprocnear
WaitForVerticalSyncStart proc near
mov dx,INPUT_STATUS_0
WaitNotVerticalSync:
in al,dx
@ -349,7 +349,7 @@ WaitForVerticalSyncStart endp
;
; Registers altered: AL, DX
;
WaitForVerticalSyncEndprocnear
WaitForVerticalSyncEnd proc near
mov dx,INPUT_STATUS_0
WaitVerticalSync2:
in al,dx
@ -360,7 +360,7 @@ WaitNotVerticalSync2:
test al,08h
jnz WaitNotVerticalSync2
ret
WaitForVerticalSyncEndendp
WaitForVerticalSyncEnd endp
;*********************************************************************
; Sets the start address to the value specifed by StartAddress.
; Wait for the trailing edge of vertical sync before setting so that
@ -751,7 +751,7 @@ MyStack segment para stack 'STACK'
db 512 dup (0)
MyStack ends
;*********************************************************************
Datasegment
Data segment
SplitScreenLine dw ? ;line the split screen currently
; starts after
StartAddress dw ? ;display memory offset at which
@ -763,7 +763,7 @@ Data ends
Code segment
assume cs:Code, ds:Data
;*********************************************************************
Startproc near
Start proc near
mov ax,Data
mov ds,ax
;
@ -837,7 +837,7 @@ ColumnLoop2:
; panning effects can be seen easily
inc di
inc di
loopColumnLoop2
loop ColumnLoop2
ror ax,1 ;shift pattern word
dec dx
jnz RowLoop2
@ -847,7 +847,7 @@ loopColumnLoop2
; screen jerks back and forth as the pel panning setting cycles.
;
mov cx,200 ;pan 200 pixels to the left
callPanRight
call PanRight
;
; Wait for a key press (don't echo character).
;
@ -904,7 +904,7 @@ endif
int 10h ;return to text mode
mov ah,4ch
int 21h ;return to DOS
Startendp
Start endp
;*********************************************************************
; Waits for the leading edge of the vertical sync pulse.
;
@ -997,7 +997,7 @@ SetPelPan proc near
mov al,[PelPan]
out dx,al ;load the new Pel Pan setting
ret
SetPelPanendp
SetPelPan endp
;*********************************************************************
; Sets the scan line the split screen starts after to the scan line
; specified by SplitScreenLine.
@ -1104,8 +1104,8 @@ DoSetStartAddress:
ret
PanRight endp
;*********************************************************************
Codeends
endStart
Code ends
end Start
```
### Notes on Setting and Reading Registers

View file

@ -37,7 +37,7 @@ the way up to 360x480—and that's with the vanilla IBM VGA!
In this chapter, I'm going to focus on one of my favorite 256-color
modes, which provides 320x400 resolution and two graphics pages and can
be set up with very little reof the VGA. In the next chapter, I'll
be set up with very little reprogramming of the VGA. In the next chapter, I'll
discuss higher-resolution 256-color modes, and starting in Chapter 47,
I'll cover the high-performance "Mode X" 256-color programming that many
games use.
@ -283,7 +283,7 @@ endif
;
; Macro to output a constant value to an indexed VGA register.
;
CONSTANT_TO_INDEXED_REGISTERmacroADDRESS, INDEX, VALUE
CONSTANT_TO_INDEXED_REGISTER macro ADDRESS, INDEX, VALUE
mov dx,ADDRESS
mov ax,(VALUE shl 8) + INDEX
OUT_WORD
@ -309,7 +309,7 @@ ColorLoop:
; line descriptor list
LineLoop:
mov cx,[si+StartX] ;set the initial X coordinate
cmpcx,-1
cmp cx,-1
jz LinesDone ;a descriptor with a -1 X
; coordinate marks the end
; of the list
@ -341,7 +341,7 @@ LinesDone:
;
call GetNextKey
mov ax,0003h
int 10h text mode
int 10h ;text mode
mov ah,4ch
int 21h ;done
;
@ -477,7 +477,7 @@ WritePixel proc near
; the pixel
mov es:[di],bl ;draw the pixel
ret
WritePixelendp
WritePixel endp
;
; Reads the color of the pixel at the specified location in 320x400
; 256-color mode.
@ -491,7 +491,7 @@ WritePixelendp
;
; Registers altered: AX, CX, DX, SI, ES
;
ReadPixelprocnear
ReadPixel proc near
mov ax,VGA_SEGMENT
mov es,ax ;point to display memory
mov ax,SCREEN_WIDTH/4
@ -511,9 +511,9 @@ ReadPixelprocnear
mov dx,GC_INDEX
OUT_WORD ;set to read from the proper plane for
; the pixel
lodsbyte ptr es:[si] ;read the pixel
lods byte ptr es:[si] ;read the pixel
ret
ReadPixelendp
ReadPixel endp
;
; Waits for the next key and returns it in AX.
;
@ -690,7 +690,7 @@ endif
;
; Macro to output a constant value to an indexed VGA register.
;
CONSTANT_TO_INDEXED_REGISTERmacroADDRESS, INDEX, VALUE
CONSTANT_TO_INDEXED_REGISTER macro ADDRESS, INDEX, VALUE
mov dx,ADDRESS
mov ax,(VALUE shl 8) + INDEX
OUT_WORD
@ -702,7 +702,7 @@ Start proc near
;
; Set 320x400 256-color mode.
;
callSet320By400Mode
call Set320By400Mode
;
; We're in 320x400 256-color mode, with page 0 displayed.
; Let's fill page 0 with color bars slanting down and to the right.
@ -722,7 +722,7 @@ callSet320By400Mode
;
; Wait for a key and flip to page 1 when one is pressed.
;
callGetNextKey
call GetNextKey
CONSTANT_TO_INDEXED_REGISTER CRTC_INDEX,START_ADDRESS_HIGH,80h
;set the Start Address High register
; to 80h, for a start address of 8000h
@ -735,7 +735,7 @@ callSet320By400Mode
;
; Wait for another key and flip back to page 0 when one is pressed.
;
callGetNextKey
call GetNextKey
CONSTANT_TO_INDEXED_REGISTER CRTC_INDEX,START_ADDRESS_HIGH,00h
;set the Start Address High register
; to 00h, for a start address of 0000h
@ -757,7 +757,7 @@ Start endp
;
; Output: none
;
Set320By400Modeprocnear
Set320By400Mode proc near
;
; First, go to normal 320x200 256-color mode, which is really a
; 320x400 256-color mode with each line scanned twice.
@ -831,7 +831,7 @@ CONSTANT_TO_INDEXED_REGISTER SC_INDEX,MAP_MASK,0fh
out dx,al
inc dx
in al,dx
and al,not40h ;turn off doubleword
and al,not 40h ;turn off doubleword
out dx,al
dec dx
mov al,MODE_CONTROL
@ -853,7 +853,7 @@ Set320By400Mode endp
; make them slant down and to the left, 0 to make
; them vertical.
;
ColorBarsUpprocnear
ColorBarsUp proc near
mov ax,VGA_SEGMENT
mov es,ax ;point to display memory
sub bh,bh ;start with color 0
@ -867,7 +867,7 @@ RowLoop:
;4 pixels at each address, so
; each 320-pixel row is 80 bytes wide
; in each plane
pus h bx ;save the row-start color
push bx ;save the row-start color
ColumnLoop:
MAP_SELECT = 1
rept 4 ;do all 4 pixels at this address with
@ -887,11 +887,11 @@ MAP_SELECT = MAP_SELECT shl 1
dec si ;count down lines on the screen
jnz RowLoop
ret
ColorBarsUpendp
ColorBarsUp endp
;
; Waits for the next key and returns it in AX.
;
GetNextKeyprocnear
GetNextKey proc near
WaitKey:
mov ah,1
int 16h
@ -901,9 +901,9 @@ WaitKey:
ret
GetNextKey endp
;
Codeends
Code ends
;
endStart
end Start
```
When you run Listing 31.2, note the extremely smooth edges and fine

View file

@ -148,7 +148,7 @@ WORD_OUTS_OK equ 1 ;set to 0 to assemble for
; computers that can't handle
; word outs to indexed VGA registers
;
_DATAsegmentpublic byte DATA'
_DATA segment public byte DATA'
;
; 360x480 256-color mode CRT Controller register settings.
; (Courtesy of John Bridges.)
@ -171,7 +171,7 @@ vptbl dw 06b00h ; horz total
dw 00616h ; v blank end
dw 0e317h ; turn on byte mode
vpend label word
_DATAends
_DATA ends
;
; Macro to output a word value to a port.
;
@ -199,7 +199,7 @@ _TEXTsegment byte public CODE'
; Returns: nothing
;
public _Set360x480Mode
_Set360x480Modeprocnear
_Set360x480Mode proc near
push si ;preserve C register vars
push di
mov ax,12h ; start with mode 12h
@ -239,7 +239,7 @@ _Set360x480Modeprocnear
pop di ;restore C register vars
pop si
ret
_Set360x480Modeendp
_Set360x480Mode endp
;
; Draws a pixel in the specified color at the specified
; location in 360x480 256-color mode.
@ -258,7 +258,7 @@ Color dw ? ;color in which to draw (in the
DParms ends
;
public _Draw360x480Dot
_Draw360x480Dotprocnear
_Draw360x480Dot proc near
push bp ;preserve caller's BP
mov bp,sp ;point to stack frame
push si ;preserve C register vars
@ -289,7 +289,7 @@ _Draw360x480Dotprocnear
pop si
pop bp ;restore caller's BP
ret
_Draw360x480Dotendp
_Draw360x480Dot endp
;
; Reads the color of the pixel at the specified
; location in 360x480 256-color mode.
@ -306,7 +306,7 @@ ReadY dw ? ;Y coordinate from which to read
RParms ends
;
public _Read360x480Dot
_Read360x480Dotprocnear
_Read360x480Dot proc near
push bp ;preserve caller's BP
mov bp,sp ;point to stack frame
push si ;preserve C register vars
@ -336,7 +336,7 @@ _Read360x480Dotprocnear
pop bp ;restore caller's BP
ret
_Read360x480Dot endp
_TEX Tends
_TEXT ends
end
```

View file

@ -532,7 +532,7 @@ FillVertLoop:
jnz FillHorzLoop ;no, do the next column
ret;
endStart
end Start
```
Note the jagged lines at the corners of the screen when you run Listing

View file

@ -720,7 +720,7 @@ DrawLoop:
dec dx ;count down the lines of the image
jnz DrawLoop
ret
DrawObjectendp
DrawObject endp
;
Code ends
end Start

View file

@ -199,7 +199,7 @@ SCparms ends
align ALIGNMENT
public -CosSin
-CosSinprocnear
-CosSin proc near
push bp ;preserve stack frame
mov bp,sp ;set up local stack frame
@ -272,7 +272,7 @@ CSDone:
pop bp;restore stack frame
ret
-CosSinendp
-CosSin endp
;=====================================================================
; Matrix multiplies Xform by SourceVec, and stores the result in
; DestVec. Multiplies a 4x4 matrix times a 4x1 matrix; the result
@ -351,7 +351,7 @@ pop di;restore register variables
pop si
pop bp;restore stack frame
ret
-XformVecendp
-XformVec endp
;=====================================================================
; Matrix multiplies SourceXform1 by SourceXform2 and stores the
; result in DestXform. Multiplies a 4x4 matrix times a 4x4 matrix;
@ -475,7 +475,7 @@ pop di;restore register variables
pop si
pop bp;restore stack frame
ret
-ConcatXformsendp
-ConcatXforms endp
end
```

View file

@ -339,7 +339,7 @@ SCparms ends
alignALIGNMENT
public _CosSin
_CosSin procnear
_CosSin proc near
push bp ;preserve stack frame
mov bp,sp ;set up local stack frame
@ -597,7 +597,7 @@ FixedMulDone:
align ALIGNMENT
public _XformVec
_XformVecprocnear
_XformVec proc near
push bp ;preserve stack frame
mov bp,sp ;set up local stack frame
push si ;preserve register variables
@ -704,7 +704,7 @@ endif ;USE386
pop si
pop bp ;restore stack frame
ret
_XformVecendp
_XformVec endp
;=====================================================================
; Matrix multiplies SourceXform1 by SourceXform2 and stores the
@ -741,7 +741,7 @@ CXparms ends
align ALIGNMENT
public _ConcatXforms
_ConcatXformsprocnear
_ConcatXforms proc near
push bp ;preserve stack frame
mov bp,sp ;set up local stack frame
push si ;preserve register variables