The following is a listing of the macros used in this source listing. You will be able to tell when a macro was used by a plus (+) sign to the left of the hex code produced in column two by the assembler.
ASLA: MACRO
%L ASL A
ENDM
RORA: MACRO
%L ROR A
ENDS
LSRA: MACRO
%L LSR A
ENDM
ROLA: MACRO
%L ROL
ENDM
FDB: MACRO
%L DW REV (%1)
IF '=%2' <> '='
DW REV (%2)
IF '=%3' <> '='
DW REV (%3)
IF '=%4' <> '='
DW REV (%4)
IF '=%5' <> '='
DW REV (%5)
ENDIF
ENDIF
ENDIF
ENDIF
ENDM
LOCAL: MACRO
PROC
ENDM
BYTE: MACRO
IF '%I' = '='
%L DB $80+(((%2-*)&$7F) XOR $40 )
ELSE
IF '%1' = '@@'
%L DW ( %2 )
ELSE
%L DB %1
ENDIF
ENDIF
ENDM
Syntax Table Macro
; THIS MACRO IS USED TO SIMULATE THE ACTION OF THE ORIGINAL
; ASSEMBLER IN HANDLING SPECIAL SYNTAX TABLE PSEUDO OPS AND
; OPERANDS
;
; THE 'SYN' MACRO EXAMINES UP TO 4 ARGUMENTS FOR CERTAIN SPECIAL
; CASE NAMES.
;
; IF THE NAME 'JS' IS FOUND, IT GENERATES A SPECIAL 'RELATIVE
; SYNTAX JSR' TO THE LABEL FOUND IN THE NEXT PARAMETER
;
; IF THE NAME 'AD' IS FOUND. IT GENERERATES A WORD ADDRESS OF
; THE LABEL FOUND IS THE NEST PARAMETER
;
; ANY OTHER NAME IS ASSUMED TO BE A SIMPLE BYTE VALUE
SYN: MACRO
:SYAR2 SET '=%2'<>'='
:SYAR3 SET '=%3'<>'='
:SYAR4 SET '=%4'<>'='
IF '%1' = 'JS'
%L DB $80+(((%2-*)&$7F) XOR $40 )
:SYAR2 SET 0
ELSE
IF '%1' = 'AD'
%L DW (%2)
:SYAR2 SET 0
ELSE
%L DB %1
ENDIF
ENDIF
IF :SYAR2
IF '%2'= 'JS'
DB $80+(((%3-*)&$7F) XOR $40 )
:SYAR3 SET 0
ELSE
IF '%2' = 'AD'
DW (%3)
:SYAR3 SET 0
ELSE
DB %2
ENDIF
ENDIF
ENDIF
IF :SYAR3
IF '%3'= 'JS'
DB $80+(((%4-*)&$7F) XOR $40 )
:SYAR4 SET 0
ELSE
IF '%3' = 'AD'
DW (%4)
:SYAR4 SET 0
ELSE
DB %3
ENDIF
ENDIF
ENDIF
IF :SYAR4
IF '%4'= 'JS'
DB $80+(((%5-*)&$7F) XOR $40 )
ELSE
IF '%4' = 'AD'
DW (%5)
ELSE
DB %4
ENDIF
ENDIF
ENDIF
ENDM
Yes, it’s true. There are some bugs in Atari BASIC. Of course, that’s not surprising, since Atari released the product as ROM without giving the authors a chance to do second-round bug-fixing. But what hurts, a little, is that most of the fixes for the bugs have been known since June of 1979.
As this book is being written, rumor has it that at last Atari is in the final stages of releasing a new version of the BASIC ROMs. Unfortunately, these modified ROMs will appear too late for us to comment upon them in this edition. On the other hand, there are supposed to be fewer than twenty fixes implemented (which isn’t a bad record for a product as mature as Atari BASIC), so those of you who are willing to PEEK around a bit can use this listing as at least a road map to the new ROMs.
In any case, though, we thought it would be appropriate to mention a few of the bugs we know about, show you why they exist, and tell how we fixed them back there in the summer of ’79.
In the course of editing a BASIC program, sometimes the system loses all or part of the program, or it simply hangs. Often, even SYSTEM RESET will not return control to the user.
Also, string assignments that involve the movement of exact multiples of 256 bytes do not move the bytes properly. For example, A$=B$(257,512) would actually move bytes 513 through 768 of B$ into bytes 257 through 512 of A$, even if neither string were DIMensioned to those values.
Both of these are really the same bug. And both are caused because we strove to be a little too efficient.
There are many ways to move strings of bytes using the 6502’s instruction set. The simplest and most-used methods, though, are excruciatingly slow. So Paul and Kathleen invented a super-fast set of move-memory routines, one for moving up in memory (EXPAND, at $A881) and one for moving down in memory (CONTRACT, at $A8FD). Unfortunately, the routines are very complex (which is what makes them fast) and difficult to interface with properly. And so a bug crept into CONTRACT.
Take a look at the code of FMOVER ($A947). When we get here, we expect MVLNG to contain the complement of the least significant byte of the move length while MVLNG+1 contains its most significant byte. But look what happens if the original move length was, for example, $200. The complement of the least significant byte ($00) is still zero ($00), so the BEQ to :CONT4 occurs immediately.
But by then, the X register contains the number of pages to move plus one (X would contain 3 in this example), so we increment it (it becomes 2) and go to label :CONT3, where we bump the high-order byte of both the source and destination addresses. Ah, but therein lies the rub! We haven’t yet done anything with the first values in those source and destination addresses, so we have effectively skipped 256 bytes of each!
The solution is to replace the BEQ :CONT4 at $A94E with the following code:
DEX
BNE :CONT2
RTS
Do you see the difference? If we enter with MVLNG equal to zero, we immediately move 256 bytes (at : CONT2) before ever attempting to change the source and destination addresses.
And this fix works, honest. We’ve been using it like this for over two years BASIC A+.
Taking the unary minus of a number (A=0 : PRINT -A) can result in garbage. Usually, this garbage will not affect subsequent calculations, but it does print strangely. And how did this come about?
We simply forgot to take into consideration the fact that zero doesn’t really have a sign. Look at the code for the unary minus operator (XPUMINUS, at $ACA8). Do you see the problem? We simply invert the most significant bit (the sign bit) of the floating point number in FR0.
What we should have coded would be something like this:
LDA FR0
BEQ :NOINVERT
EOR #$80
STA FR0
:NOINVERT
Luckily, this is not too severe a problem to the BASIC user (one can always use “PRINT 0-A” instead of “PRINT A”) but just think — it only cost two bytes to fix this bug.
The GET statement does not reinitialize its buffer pointer, so it can do nasty things to memory if used directly after a statement which has changed the system buffer pointer. For example, GET can change the line number of a DATA statement if it is used after a READ. Also, the same problem exists for the LOCATE statement, since it calls GET.
From BASIC, the easiest solution is to use a function or statement which is known to reset the pointer. Coding “XX=STR$(0)” works just fine, as does PRINTing any number.
Within the source listing, the problem exists at location $BC82, label GET1. If the code had simply read as follows, there would be no bug:
GET1
JSR INTLBF ; reset buffer pointer
LDA #ICGTC ; continue as before
Using either an INPUT or READ statement without a following variable does not cause a syntax error (as it should). Then, attempting to execute a statement such as 20 INPUT can cause total system lock-up.
The solution from BASIC? Be careful and don’t do it.
And this is one bug that we will not show the fix for, simply because it’s too long and involved. We will, however, point to labels :SINPUT and :SREAD (at locations $A6F4 and $A6F5) in the Syntax Tables and show why the bug exists.
Note that the :SINPUT does a syntax call (SYN JS,) to the :OPD syntax, which looks for — but does not insist upon — a file number specifier (#<numeric expression>). Then the syntax joins with :SREAD, which looks for zero or more variables.
Oops! Zero or more? Shouldn’t that be one or more? That’s where the problem lies.
In all too many cases, the use of the NOT operator is guaranteed to get you in trouble. If you don’t believe it, try this: PRINT NOT NOT 1.
The explanation of why the bug occurs is too lengthy to give in detail here; suffice it to say that the precedence of NOT is wrong. Remember the Operator Precedence Table we displayed in Chapter 8 of Part 2? Look at what you got for the go-onto-stack and come-off-stack precedence values for NOT.
Or look at location $AC57, the NOT entry in OPRTAB. NOT uses a 7 for both its precedence values. But wait a minute. If two operators have the same apparent precedence (as in NOT NOT A or even A + B + C), the expression executor will pop the first one off the stack and execute it. But with a unary operator, there is nothing to execute yet.
And the same bug exists for both unary minus and unary plus, so - -3 and + +5 don’t execute properly. Of course, since unary plus doesn’t really do anything, it doesn’t matter. In the case of unary minus, though, all but the last minus sign in a string of minus signs is ignored (that is, - -3 produces -3 as a result, instead of +3, as it should). But, by an incredible coincidence, the damage that unary minus causes is invisible to Execute Expression as a whole and only produces the error noted.
The fix? Well, if we want to leave NOT where it is in the order of things, the only way is to restructure the whole precedence table. But if we are willing to accord it a very high precedence, like unary plus and minus, we can fix it — and plus and minus — by changing the bytes at $AC57, $AC64, and $AC65 to $DC. And, thanks to the differing go-onto-stack and come-off-stack values, we can stack as many NOTs, pluses, or minuses as we want.
Are these all the bugs we know about that can be fixed easily? No. But these are the easiest to understand or the easiest to fix, and we thought they were instructive.
Of course, unless you have an EPROM board and burner handy, you may not be able to take advantage of these fixes. But at least now you may be able to work around them as you program with good old buggy-version Atari BASIC.
And take heart. Remember Richard’s Rule: Any nontrivial piece of software has bugs in it. And the corollary: Any piece of software which is bug-free is trivial.
AADD AF52 CGTO 0017 CVFPI AD56 EREXPR AAE0
AAPSTR AB98 CILET 0036 CVIFP D9AA EXOPOP AB0B
n ADC AF53 CIO E456 DATAD 00B6 EXP DDC0
ADFLAG 00B1 CIX 00F2 DATALN 00B7 EXP1 DE03
n AFP D800 CLALL1 BD4F n DCBORG 0300 EXP10 DDCC
AMUL1 AF5D CLE 001D DEGFLG 00FB EXP2 DE20
AMUL2 AF46 CLEN 0042 DEGON 0006 EXP3 DE26
APHM 000E CLIST 0004 DIGRT 00F1 EXPAND A881
ARGOPS 0080 CLPRR 002B DIRFLG 00A6 EXPERR DE4B
ARGP2 AC06 CLSALL BD41 DNERR BCB0 EXPINT AB2E
ARGPOP ABF2 CLSYS1 BCF1 DOSLOC 000A EXPLOW A87F
ARGPUS ABBA CLSYSD BCF1 DSPFLG 02FE EXPOUT DE4A
ARGSTK 0080 CLT 0020 ECSIZE 00A4 EXPSGN DE39
ARSLVL 00AA CMINUS 0026 EEXP 00ED EXSVOP 00AB
ARSTKX 00AA CMUL 0024 ELADVC BADD EXSVPR 00AC
n ASCIN D800 CNE 001E ENDSTA 008E FADD DA66
ASLA mac CNFNP 0044 ENDVVT 0088 n FASC D8E6
ATAN BE77 CNOT 0028 ENTDTD 00B4 FBODY 000C
ATAN1 BE9A COLD1 A008 EPCHAR 005D FCHRFL 00F0
ATAN2 BED4 COLDST A000 ERBRTN B920 FDB mac
ATCOEF DFAE COLOR 00C8 ERGFDE B922 FDIV DB28
ATEMP 00AF COMCNT 00B0 ERLTL B924 FHALF DF6C
ATNOIT BEE2 CON 001E ERNOFO B926 FIXRST B825
BININT 00D4 COSTLO A8FB ERNOLN B928 FLD01 DD8F
BOTH BDB3 CONTRA A8FD n ERON B93E n FLD0P DD8D
BRKBYT 0011 COPEN BBB6 EROVFL B92A FLD0R DD89
BYELOC E471 COR 0029 ERRAOS B92C FLD11 DD9E
n BYTE mac COS BDB1 ERRDIM B92E FLD1P DD9C
C 0044 COX 0094 ERRDNO B918 FLD1R DD98
BYELOC E471 CPC 009D ERRINP B930 FLIM 0000
n BYTE mac CPLUS 0025 ERRLN B932 FLIST BAD5
C 0044 CPND 001C ERRNSF B916 n FLOG10 DF01
CAASN 002D CR 009B ERRNUM 00B9 FLPTR 00FC
CACOM 003C CREAD 0022 ERROOD B934 FMOVE DDB6
CADR 0043 CREGS 02C4 ERROR B940 PMOVE1 DDB8
CALPRN 0038 CRPRN 002C ERRPTL B91A FMOVER A947
CAND 002A CRTGI BFF9 ERRRAV 003C FMPREC 0005
CASC 0040 CSASN 002E ERRSSL B936 FMUL DADB
CCHX 0031 CSC 0015 ERRVSF B938 n FNTAB A829
CCOM 0012 CSEQ 0034 ERSVAL B91C FONE DE8F
CCR 0016 CSGE 0031 ERVAL B93A FP9S DFEA
CDATA 0001 CSGT 0033 ESIGN 00EF FPI D9D2
CDIV 0027 CSLE 002F EVAADR 0002 FPONE BE71
CDLPRN 0039 CSLPRN 0037 EVAD1 0004 FPORG D800
n CDOL 0013 CSLT 0032 EVAD2 0006 FPREC 0006
n CDQ 0010 CSNE 0030 n EVARRA 0040 FPSCR 05E6
CDSLPR 003B CSOE 0011 EVDIM 0001 FPSCR1 05EC
CEOS 0014 CSROP 001D n EVNUM 0001 FPTR2 00FE
CEQ 0022 CSTEP 001A EVSADR 0002 FR0 00D4
CERR 0037 CSTR 003D EVSCAL 0000 FR0M 00D5
CEXP 0023 CTHEN 001B EVSDIM 0006 FR1 00E0
CFFUN 003D CTO 0019 EVSDTA 0002 FR1M 00E1
CFLPRN 003A CUMINU 0036 EVSLEN 0004 FR2 00E6
CFOR 0008 CUPLUS 0035 EVSTR 0080 FRA10 DD01
CGE 001F CUSR 003F n EVTYPE 0000 FRA1E DD09
CGOSUB 000C CVAFP D800 n EVVALU 0002 FRA20 DD05
CGS 0018 CVAL 0041 EXECNL A95F FRA2E DD0F
CGT 0021 CVFASC D8E6 EXECNS A962 FRADD AD3B
FRCMP AD35 n ICOIN 0001 LSRA mac RNDDIV B0A8
FRCMPP AD32 ICOIO 0003 LSTMC B63D RNDLOC D20A
FRDIV AD4D n ICOOUT 0002 MAXCIX 009F ROLA mac
FRE 00DA n ICPBC 000A MDEND DB1A ROM A000
FRMUL AD47 n ICPBR 0008 MDESUP DCCF RORA mac
FRSIGN 00EE ICPTC 000B MDSUP DCE0 RSHF0E DC62
FRSUB AD41 n ICPTR 0009 MEMFUL B93C RSHFT0 DC3A
FRUN BAF7 ICPUT 0346 MEMTOP 0090 RSHFT1 DC3E
FRX 00EC ICSBRK 0080 n MEND1 DB1E RSTPTR B8AF
FSCR 05E6 n ICSDER 0083 MEND2 DB21 RSTSEO BD99
FSCR1 05EC n ICSDNR 0081 MEND3 DB24 RTNVAR AC16
FSQR BF08 n ICSEOF 0003 MEOLFL 0092 RUNINI B8F8
FST01 DDAD n ICSIVC 0084 MISCR1 0480 RUNSTK 008E
n FST0P DDAB n ICSIVN 0086 MISCRA 0500 SAVCUR 00BE
FST0R DDA7 n ICSNED 0082 MV0TO1 DDB6 SAVDEX 00B3
FSTEP 0006 n ICSNOP 0085 MVFA 0099 SCANT 00AF
FSUB DA60 n ICSOK 0001 MVFR0E DD34 SCOEF BE41
FTWO BF93 ICSTA 0343 MVFR12 DD28 SCRX 0055
GDIO1 BC22 ICSTAT 000D MVLNG 00A2 SCRY 0054
GDVCIO BC1D n ICSTR 0002 MVTA 009B SCVECT BFF9
GET1 BC82 n ICSWPE 0087 NATCF 000B SEARCH A462
GET1IN ABE9 IFP D9AA NCTOFR AB4D SETDZ BD72
GETINT ABE0 n ILSHFT DA5A NIBSH0 DBEB SETLIN B818
GETLL A9DD INBUFF 00F3 NIBSH2 DBE7 SETLN1 B81B
n GETPI0 ABD8 INDEX2 0097 NLCOEF 000A SETSEO BD79
GETPIN ABD5 INTLBF DA51 NOCD0 BD01 SGNFLG 00F0
GETSTM A9A2 IO1 BD0A NORM DC00 SICKIO BCB9
GETTOK AB3E n 102 BD0E NORM1 DC04 SIN BDA7
GETVAR AB89 IO3 BD10 NPCOEF 000A SINDON BE40
GFDISP 0003 IO4 BD12 NSCF 0006 SINERR BDA5
GFHEAD 0004 IO5 BD19 NSIGN 00EE SINF1 BDF6
n GFLNO 0001 n IO6 BD1D NXTSTD 00A7 SINF3 BE00
GFTYPE 0000 IO7 BD24 ONLOOP 00B3 SINF4 BE11
GIOCMD BD04 IO8 BD26 OPETAB AA70 SINF5 BDE4
GIODVC BC9F IOCB 0340 OPNTAB A7E3 n SINF6 BDD5
GIOPRM BD02 IOCBOR 0340 OPRTAB AC3F SINF7 BDCC
GLGO BA92 IOCMD 00C0 OPSTKX 00A9 n SINOVF BDCB
GLINE BA89 IODVC 00C1 OUTBUF 0080 SIX 0480
GLPCX BAC4 IOTES2 BCB6 P10COF DE4D SKBLAN DBA1
GLPX BAC6 IOTEST BCB3 n PATCH BDA4 SKCTL D20F
n GNLINE BA80 ISVAR BD2F PATSIZ 0001 SKPBLA DBA1
GNXTL A9D0 ISVAR1 BD2D PIOV18 BE6B SNTAB A4AF
GRFBAS 0270 n LBPR1 057E PIOV2 BE5F SNX1 A050
GSTRAD AB9B n LBPR2 057F PIOV4 DFF0 SNX2 A053
GTINTO ABE3 LBUFF 0580 PLYARG 05E0 SNX3 A05D
GWTAD AC28 LDDVX BCA6 PLYCNT 00EF SOPEN BBD1
HIMEM 02E5 LDIOST BCFB PLYEV1 DD5B SOX 0481
HMADR 02E5 LDLINE B578 PLYEV2 DD6F SPC 0482
n IBUFFX 00A9 LELNUM 00AD PLYEVL DD40 SQR BEE5
ICAUX1 034A LGCOEF DF72 PLYOUT DD88 SQR1 BF00
ICAUX2 034B LISTDT 00B5 POKADR 0095 SQR10 DF66
ICAUX3 034C LLINE B55C POP1 AC0F SQR2 BF84
ICAUX4 034D LLNGTH 009F POPRST B841 SQR3 BF8A
ICAUX5 034E LMADR 02E7 PRCHAR BA9F SQRCNT 00EF
ICBAH 0345 LOADFL 00CA PRCR BD6E SQRDON BF64
ICBAL 0344 LOCAL mac PRCX BAA1 SQRERR BEE3
ICBLH 0349 LOG DECD PRDY1 BD59 SQRLP BF2A
ICBLL 0348 n LOG1 DEDB PREADY BD57 SQROUT BF92
ICCLOS 000C LOG10 DED1 PROMPT 00C2 SRCADR 0095
ICCOM 0342 LOG10E DE89 PSHRST B683 SRCNXT A490
n ICDDC 000E LOG2 DEEF PSTR B480 SRCSKP 00AA
n ICDNO 0341 LOG3 DEF3 PTABW 00C9 SREG1 D208
ICDRAW 0011 LOG4 DEF9 PUTCHA BA9F SREG2 D200
n ICFREE 00FF LOG5 DEDB QTEMP 00D9 SREG3 D201
n ICGBC 0006 LOG6 DF46 RADFLG 00FB SSTR BA73
n ICGBR 0004 LOG7 DF53 RADON 0000 STACK 0480
ICGR 001C LOGBTH DED3 RESCUR B6BE STARP 008C
ICGTC 0007 LOGDON DF64 RISASN AEA6 STENUM 00AF
ICGTR 0005 n LOGERR DED9 RISC AB64 STETAB AA00
n ICHID 0340 n LOGOUT DF56 RML 0007 STINDE 00A8
ICLEN 0010 LOMEM 0080 RMSG BD67 STKLVL 00A9
n ICMAX 000E LPRTOP B535 STMCUR 008A
STMLBD 00A7 XDATA A9E7 XPCHR B067 XPSNE ACBE
STMSTR 00A8 XDEG B261 XPCOS B125 XPSQR B157
STMTAB 0088 XDIM B1D9 XPDIV AC9F XPSTIC B026
STOP B7A7 XDOS A9EE XPDLPR AD82 XPSTR B049
STOPLN 00BA XDPSLP AD82 XPEQ ACDC XPSTRI B02E
STRCMP AF81 XDRAWT BA31 XPEXP B14D XPUMIN ACA8
SVCOLO 02FB XEND B78D XPFLPR AD7B XPUPLU ACB4
SVDISP 00B2 XENTER BACB XPFRE AFEB XPUSH AD16
SVESA 0097 XERR B91E XPGE ACD5 XPUSR B0BA
SVONTC 00B0 XFALSE AD00 XPGT ACCC XPUT BC72
SVONTL 00B2 XFMFLG 00F1 XPIFP AFD1 XPVAL B000
SVONTX 00B3 XFOR B64B XPIFP1 AFD5 XRAD B266
SWNTP 00AD XFORM DE95 XPIFP2 AFD8 XREAD B283
SWVTE 00B1 XGET BC7F XPINT B0DD XREM A9E7
SYN mac XGO1 B6AE XPL10 B143 XREST B26B
SYNTAX A060 XGO2 B6A6 XPLE ACB5 XRTN B719
TEMPA 00C4 XGOSUB B6A0 XPLEN AFCA XRUN B74D
TENDST A9E2 XGOTO B6A3 XPLOG B139 XSAASN AEA3
n TESTRT A9E7 XGR BA50 XPLOT BA76 XSAVE BB5D
TOPRST 0090 XGS B6C7 XPLPRN AB1F XSAVE1 BB62
TRAPLN 00BC XGS1 B6CA XPLT ACC5 XSETCO B9B7
TSCOX 00AB XIF B778 XPMINU AC8D XSOUND B9DD
TSLNUM 00A0 XINPUT B316 XPMUL AC96 XSTATU BC28
TSTALP A3F7 XINT B0E6 XPNE ACBE XSTOP B793
TSTBRK A9F4 XITBT B354 XPNOT ACF9 XTF AD09
TSTEND B910 XLET AAE0 XPOINT BC4D XTI AD07
TSTNUM DBAF XLIST B483 XPOKE B24C XTRAP B7E1
TVNUM 00D3 XLOAD BAFB XPOP B841 XTRUE AD05
TVSCIX 00AC XLOAD1 BB04 XPOR ACEE XXIO BBE5
TVTYPE 00D2 XLOCAT BC95 XPOS BA16 ZF1 DA46
VNTD 0084 XLPRIN B464 XPPDL B022 ZFP 00D2
VNTP 0082 XNEW A00C XPPEEK AFE1 ZFR0 DA44
VNUM 00D3 XNEXT B6CF XPPLUS AC84 ZICB 0020
VTYPE 00D2 XNOTE BC36 XPPOWE B165 ZPADEC AFBC
WTP 0086 XON B7ED XPPTRI B02A ZPG1 0080
WARMFL 0008 XOP1 BBED XPRINT B3B6 ZTEMP1 00F5
WARMST A04D XOP2 BBFB XPRND B08B ZTEMP2 00C6
WWTPT 009D XOPEN BBEB XPRPRN AD7B ZTEMP3 00F9
XBYE A9E8 XPAASN AD5F n XPSEQ ACDC ZTEMP4 00F7
XCLOAD BBAC XPABS B0AE XPSGE ACD5 ZVAR B8C0
XCLOSE BC1B XPACOM AD79 XPSGN AD19 ZXLY DA48
XCLR B766 XPADR B01C XPSGT ACCC
XCMP AD26 XPALPR AD86 XPSIN B11B
XCOLOR BA29 XPAND ACE3 XPSLE ACB5
XCOM B1D9 XPASC B012 XPSLPR AE26
XCONT B7BE XPATN B12F XPSLT ACC5
XCSAVE BBA4