;----------RED-SECTOR-INC.-proudly-presents-a-33-year-old-record-:---------- ; 455-byte footprint___ _ "...The original chess game in a bootsector" ; / / _____ _ _ _____ _ _ ___ _ ; .::. / / / / / / / / / / ; :::: / / ____ .-/ _ ___/-. .-/ _ ___/-. / /__ ; :: / \ | | . | | | . | / / ; :: __ _ \ l | | | l | | / ___/ ; .::. / / / / | l |_| l | |__/ / ____ ; .::::. / __/ `--' `--' / | ; :::::::: / / | ; ___ __ Cl! ___ ___ / ___ _ _ __| ; ___ _ _ / __/_ __ _ _/ _/_ _ /_ / / ___ /__ ; /_/ / / / / / / _____/ / / / __/ _ / / / ; .-/ ___/ / /______ / ___\ \___ / / __/ ; | / / / | __/ ___ | \ | ___\ \___ ; | / ____ | / | | _/ | | \ | ; | /--/ | ___/ | | | | | _/ | ; | | / / :: | ____/ :: | | :: \_____| | | ; |_____/ :: | __/ /_______| /_______| |_______\ | :: \_____| ; /_______| /___ _ /___ _ _ ___\ |_______\ ; /___ _ _ ___\ v.03 ; BootChess is the smallest computer implementation of chess on any platform ;-BootChess.asm-------------------;----------------------------------------- _b equ byte ; gui=1 x86=0 p2q=0 485b NO pad OK gui NO vbr+ NO queen _w equ word ; gui=0 x86=1 p2q=1 479b+ OK pad NO gui OK vbr- OK queen _d equ dword ; gui=0 x86=1 p2q=0 481b+ OK pad NO gui OK vbr+ NO queen _s equ short ; gui=0 x86=0 p2q=1 487b NO pad NO gui NO vbr- OK queen _f equ far ; gui=0 x86=0 p2q=0 468b NO pad NO gui NO vbr+ NO queen org 100h ; start of com binary program ip brd equ bf2+16 ; chess board at end of sector mov di,brd ; set physical board index mov bp,12 ; set 6x8+8 empty sqr mid board lines call in2 ; pass#1 black "rnbqkbnr" low-caps push word opn ; pass#2 hi-caps whites & fall-through rle:lodsb ; al='.'/al=null (fixed length rle) mov cl,8 ; empty sqr mid board line length rep stosb ; set one empty sqr mid board line dec bp ; all empty sqr mid brd lines inited ? jnz rle ; if not repeat init else bp=0 assumed mov ah,'A'-'a' ; fall-through pass#2 white hi-caps in2:mov si,br0 ; si points to endrank "rnbqkbnr" str mov cL,8 ; "rnbqkbnr" endrank str length in3:lodsb ; read physical board str car add al,ah ; hi-caps rank 1 / low-caps rank 8 stosb ; write physical board str car loop in3 ; all "rnbqkbnr" str car written ? mov cl,8 ; si-;equiv piece vals di-;0x88 brd rep movsb ; write logical 0x88 board str vals retn ; return to callers ge0:mov bx,di ; physical board idx (bx=brd) mov dh,'1' ; beg white move src rank ge1:mov dl,'h' ; beg white move src file ge2:mov [si],dx ; beg white move src str mov ch,'1' ; beg white move dst rank ge3:mov cl,'h' ; beg white move dst file ge4:mov [si+2],cx ; beg white move dst str pusha ; save all values call idx ; passive chess coords to linear indexes jbe mis ; white move src color not conforming push bx ; save white move dst idx call ver ; white move legal chess ? pop bx ; restore white move dst idx jc mis ; white move not legal chess mov di,num+3 ; compare move destination rank in 7dfeh inc si ; with move source rank in 7dfch cmpsb ; is taxi distance to topmost bettered ? jnc wor ; else not getting closer to black king cmp _b [di],'?' ; does any fallback move exist yet ? jz lkj ; no, then last valid move good enough wor:mov aL,_b[si+bx+brd-num-'a'+6]; yes, previous valid legal exist so dec aL ; only override if it's a capture js mis ; no, don't want worse taxi distance mov bx,fs ; it's a capture with piece value=al cmp bL,aL ; but hightest capture value yet ? jnc mis ; no, less important opponent piece max:mov fs,bx ; fs=best move yet in taxi half-ply lkj:dec si ; realign source index dec si ; to copy dword bst=dword idx movsd ; after 4096 tries : move=dword bst mis:popa ; restore all values cmp cl,'a' ; end white move dst file ? loopnz ge4 ; dec white move else next dst file inc ch ; inc white move dst rank cmp ch,'9' ; end white move dst rank ? jnz ge3 ; else next move dst rank cpx:inc bx ; inc physical board index dec dx ; dec white move src file cmp dl,'`' ; end white move src file ? jnz ge2 ; else next move src file inc dh ; inc white move src rank cmp dh,ch ; end white move src rank ? ch=9 jnz ge1 ; else next move src rank push _d [si+4] ; get best white move found pop _d [si] ; set it as final white move val:mov cl,'.' ; valid : empty sqr replaces src piece call act ; active chess coords to linear indexes xor bp,3 ; player turn and pawn unidir. delta jz ge0 ; white turn to play (case best=0) bla:mov al,'?' ; input str clear pattern mov di,si ; input str clear pattern (di=num) mov cx,8 ; input str clear pattern rep stosb ; input str clear pattern (di=brd) call key ; get user keyboard input jbe bla ; black move src color not conforming opn:call ver ; di=brd, black move legal chess ? jc bla ; white move not legal chess jmp _s val ; validate black move ver:call idx ; get lin indexes /w implicit passive xchg bx,dx ; switch bx=dst idx dx=src idx mov ah,[si+bx+brd-num-'a'+8] ; get piece logical 0x88 brd val... mov dh,bl ; dh=src idx dl=dst idx sub dx,"aa" ; get move file zero-based indexes bsr bx,ax ; scan for 1st bit set (si=idx+10) movsx bx,[si+bx-10-num+tab] ; bl=moved piece type idx (bh=0) mov cx,_w [si+bx-num+tab] ; piece type deltas cl=repeats ch=num sahf ; set piece logical 0x88 brd val jnp sp1 ; branch if piece not pawn (bit#4!=1) jc sp2 ; branch if pawn prev moved (bit#0=1) sp1:jns sp3 ; branch if piece not king (bit#7!=1) sp2:mov cl,1 ; override repeat if piece pawn or king sp3:jnp sp4 ; branch if piece not pawn (bit#4!=1) add bx,bp ; pawn player turn unidirection mutex sp4:inc bx ; advance piece type struct field ptr and ah,11111100b ; isolate piece bitmask only vl1:push cx ; save piece type deltas mov al,dh ; load start dst idx val inc bx ; advance piece type struct field ptr vl2:add al,[si+bx-num+tab] ; add this piece delta to dst idx val xchg aL,bL ; base reg=dst idx val and preserved mov ch,[si+bx+brd-num+8] ; read projected dst square val xchg aL,bL ; base reg=piece type struct field ptr cmp al,dl ; wanted move found (src+delta(s)=dst) ? jnz dif ; different than requested move sam:sahf ; get piece logical 0x88 brd val in flgs jnp yes ; branch if piece is not pawn (bit#2=0) test [si+bx-num+tab],1 ; pawn piece delta parity=diag vs. vert jz ord ; branch if pawn piece moving vert test ch,ch ; pawn piece vert move=;eating ? jz _s bad ; illegal chess move is a miss yes:pop cx ; correct entry sp and disregard count retn ; return to caller(s) ord:test ch,ch ; pawn piece vert move=;no eating ? jz yes ; no eating=;empty dst sqr else illegal dif:sahf ; store piece nature in flags register jnp skp ; not pawn piece so skip direction test test [si+bx-num+tab],1 ; pawn piece delta parity=diag vs. vert jnz bad ; diagonal pawn move is illegal skp:test ch,ch ; else skipping over dst square val ? jnz bad ; projected dst sqr val is not empty sahf ; get piece logical 0x88 brd val in flgs jz x88 ; branch if piece is queen (bit#6=1) jna bad ; branch if piece is not knight(bit#4=0) x88:test al,88h ; ch=0 dst out of physical board limits? loopz vl2 ; else cont if delta repeats remain bad:pop cx ; restore piece type deltas dec ch ; all possible delta nums verified ? jnz vl1 ; if not then cont next delta type nok:stc ; else return /w no match flg set retn ; return to caller key:call prt ; refresh screen to account input echo xor bx,bx ; bx=str idx=odd/even/alpha/num mutex kbd:cbw ; fun blocking wait for keystroke (ah=0) int 16h ; std bios keybd api (ah=scan al=ascii) car:mov [bx+si],al ; sav ascii val to move string (si=num) prt:pusha ; save game state snapshot mov si,bf2+16 mov cl,8 rows:mov ch,8 row:lodsb int 29h dec ch jnz row mov al,10 int 29h add si,8 loop rows popa ; restore game state snapshot inc bx ; test if any more keys ? cmp bl,4 ; frFR format input string jc kbd ; else continue input idx:loop idx ; ch=0 passive call load src/dst lin idx act:mov si,num ; reinit si to point to coord input str. mov bx,[si] ; bx=src coord (pass#1) cbw ; empty sqr val in logical 0x88 board call put ; place param passed as fun pass#1 mov dx,[si+2] ; bx=dst idx dx=src idx xchg bx,dx ; fall-through for second pass push word mat ; test for checkmate and conforming put:xchg ax,bx ; bx|dx=[num+di]+16*((8-'0')-[num+di+1]) aad -10h ; shl ah,4/sub al,ah/xor ah,ah add al,80h ; bx|dx=al-640%256-16*ah xchg ax,bx ; bx|dx=al+128-16*ah jcxz sim ; active call request or simulation ? prm:xchg ah,[si+bx+brd-num-'a'+8] ; update piece logical 0x88 board val xchg cl,[si+bx+brd-num-'a'] ; update piece physical board ascii val or ah,1 ; update piece moved once (bit#0) sim:retn ; return to caller(s) mat:sahf ; catured piece king and mate ? js xit ; if piece is king then game is over call chk ; move src color conforming ? jnz nok ; move src color not conforming chk:xchg bx,dx ; src idx <- dst idx mov al,[si+bx+brd-num-'a'] ; pass#1:src idx pass#2:dst idx di=brd xor _b [si+len-num],8 ; self-modif 8/26 val=[1;8]/[a(A);z(Z)] mov cl,-'a' ; assert black piece car interval test bp,bp ; test whose turn it is to play jnz lim ; assert white piece car interval mov cl,-'A' ; al=ascii value cl=-(lower boundery) lim:xadd al,cl ; tmp=al+cl cl=al al=tmp +fall-trough db 0d4h ; aam <self-modified value> len:db 12h ; ah=al/8 al%=8 mov al,cl ; al=restored ascii value test ah,ah ; set/clear zf=0 success zf=1 failure xit:retn ; return to caller(s) nb: destroys ah tab db p-tab,r-tab,n-tab,b-tab ; piece type mov offset array db q-tab,q-tab ; note original 1K ZX Chess q=k trick br0 db "rnbqkbnr",8,16,32,64,128 ; end rank pattern + beg piece values db 32,16,8,'p',4,'.',0,'.',0 ; end piece values + beg mid board reps db '.',0,'.',0,'P',4 ; ... end mid board reps p db 2,3,-10h,-15,-17,10h,15 ; bit#2 pf=04 p[6]=r[0] overlay r db 17,4,10h,-1h,-10h ; bit#3 ??=08 r[5]=n[0] overlay n db 1,8,1fh,21h,12h,-0eh,-1fh ; bit#4 af=16 n[9]=b[0] overlay db -21h,-12h ; ... end of knight moves list b db 0eh,4,-0fh,11h,-11h ; bit#5 ??=32 b[5]=q[0] overlay q db 0fh,8 ; bit#6 zf=64 k=q except k[0]=1 bf2 db 10h,11h,0fh,1h,-10h ; queen/king moves list and gui base db -11h,-0fh,-1h ; ... end of queen/king moves list num db "e2e4" ; hardcoded Ruy Lopez opening
Write, Run & Share Assembly code online using OneCompiler's Assembly online compiler for free. It's one of the robust, feature-rich online compilers for Assembly language. Getting started with the OneCompiler's Assembly compiler is simple and pretty fast. The editor shows sample boilerplate code when you choose language as Assembly
and start coding.
Assembly language(asm) is a low-level programming language, where the language instructions will be more similar to machine code instructions.
Every assembler may have it's own assembly language designed for a specific computers or an operating system.
Assembly language requires less execution time and memory. It is more helful for direct hardware manipulation, real-time critical applications. It is used in device drivers, low-level embedded systems etc.
Assembly language usually consists of three sections,
Data section
To initialize variables and constants, buffer size these values doesn't change at runtime.
bss section
To declare variables
text section
_start
specifies the starting of this section where the actually code is written.
There are various define directives to allocate space for variables for both initialized and uninitialized data.
variable-name define-directive initial-value
Define Directive | Description | Allocated Space |
---|---|---|
DB | Define Byte | 1 byte |
DW | Define Word | 2 bytes |
DD | Define Doubleword | 4 bytes |
DQ | Define Quadword | 8 bytes |
DT | Define Ten Bytes | 10 bytes |
Define Directive | Description |
---|---|
RESB | Reserve a Byte |
RESW | Reserve a Word |
RESD | Reserve a Doubleword |
RESQ | Reserve a Quadword |
REST | Reserve a Ten Bytes |
Constants can be defined using
CONSTANT_NAME EQU regular-exp or value
%assign constant_name value
%define constant_name value
Loops are used to iterate a set of statements for a specific number of times.
mov ECX,n
L1:
;<loop body>
loop L1
where n specifies the no of times loops should iterate.
Procedure is a sub-routine which contains set of statements. Usually procedures are written when multiple calls are required to same set of statements which increases re-usuability and modularity.
procedure_name:
;procedure body
ret