User Tools

Site Tools


sd:part_ii_writing_games_in_assembly_language

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
sd:part_ii_writing_games_in_assembly_language [2026/04/02 19:42] appledogsd:part_ii_writing_games_in_assembly_language [2026/04/03 05:30] (current) appledog
Line 3: Line 3:
  
 == Introduction == Introduction
-At the end of [[SD-8516 Stellar BASIC]] we wrote a game called [[sdb:robots|ROBOTS.BAS]]. This was a fun little take on the classic CHASE or 'robots' game from the bsd games collection. Now, for our study of Assembly Language, let's write a similar game: 'robots.asm'.+At the end of [[SD-8516 Stellar BASIC]] we wrote a game called [[sdb:robots|ROBOTS.BAS]]. This was a fun little take on the classic CHASE or 'robots' game from the bsd games collection. Now, for our study of Assembly Language, let's write a similar game: 'robots.asm'. Don't worry if you're not familiar with the BASIC version of this program; everything will be explained here.
  
 == Part 1: Assembling and Running a Program == Part 1: Assembling and Running a Program
-An assembly language program should start with an .address the bytes will be compiled fromOur program therefore begins:+Just like BASIC programs have line numbers, or C programs have #include statements, an assembly language program should start with an ''.address'' statementThis will tell the assembler where to start assembling the program. This enables us to use labels like ''start:'' and ''message:''. The assembler can calculate the exact address of the label in relative to the ''.address'' when assembling the program.
  
 <codify armasm> <codify armasm>
Line 218: Line 218:
  
 == Part 3: Player Input == Part 3: Player Input
-Part three of rthi+Let's begin part 3 by adding a new subroutine to our main loop. Our main loop now becomes: 
 + 
 +<codify armasm> 
 +main_loop: 
 +    CALL @draw_map 
 +    CALL @get_input 
 +    RET 
 +</codify> 
 + 
 +=== get_input 
 +The primary goal of this section is to get input from the player and deal with it. We can do this by using the getkey function: 
 + 
 +<codify armasm> 
 +get_input: 
 +    LDAH $02        ; getkey() 
 +    INT $10 
 +</codify> 
 + 
 +In this case, the function specification for AH=$02, INT 0x10 is: 
 + 
 +    ; ============================================================================ 
 +    ; AH=02h - Read Character (Blocking) 
 +    ; Input:  None 
 +    ; Output: AL  = ASCII character 
 +    ;          = number of keys that were in buffer before this call 
 +    ;          = keyboard flags at time of press 
 +    ; Note:   X, Y preserved for cursor position 
 +    ;         This function BLOCKS until a key is pressed 
 +    ; ============================================================================ 
 + 
 +As we can see, this function returns the ASCII code of the key the player will press in ''AL''. Thus, we can deal with the player's commands. 
 + 
 +=== uppercase or lowercase? 
 +The player might type an uppercase command or a lowercase command. Let's normalize the keys to uppercase before processing them: 
 + 
 +<codify armasm> 
 + 
 +    ; Uppercase: if AL >= 'a', it must be an uppercase character (or an invalid command). 
 +    CMP AL, #97 
 +    JNC @gi_check_keys      ; AL < 'a', skip 
 +  
 +    CMP AL, #123 
 +    JC @gi_check_keys       ; AL >= '{', skip 
 +     
 +    SUB AL, #32 
 +     
 +gi_check_keys: 
 +    ... 
 +</codify> 
 + 
 +CMP works as follows: 
 + 
 +    CMP A, B        ; if A >= B, then set carry 
 + 
 +Therefore, 
 + 
 +    CMP AL, #97     ; if AL is greater or equal to #97 ('a') then set carry 
 + 
 +So therefore if carry is NOT set, skip past the SUB command. Or else (if it's a lowercase ASCII) subtract 32 to convert from lowercase to uppercase. 
 + 
 +The second compare has a protective function. 
 + 
 +    CMP AL, #123             ; if AL >= 123, set carry. 
 +     
 +    ; If it's '{' or anything after, skip: 
 +    JC @gi_check_keys        ; Jump if Carry = Jump if AL > 'z' (al >= '}'
 + 
 + 
 +So after these two checks, the only values that reach SUB AL, #32 are exactly the bytes from 97 to 122 inclusive; i.e. 'a' to 'z'
 + 
 +Visual summary: 
 +^ AL Value ^ Meaning ^ What Happens ^ 
 +| < 97 | before ''a'' | Skipped. | 
 +| 97-122 | ''a'' to ''z'' | SUB #32 becomes 'A' to 'Z'. | 
 +| >= 123 | after 'z'\\ //'}' and up// | Skipped. | 
 + 
 +=== Processing player input 
 +We will use the HJKL convention: 
 + 
 +<codify armasm> 
 +gi_check_keys: 
 +    CMP AL, #'H' 
 +    JZ @move_left 
 + 
 +    CMP AL, #'J' 
 +    JZ @move_down 
 + 
 +    CMP AL, #'K' 
 +    JZ @move_up 
 + 
 +    CMP AL, #'L' 
 +    JZ @move_right 
 + 
 +    CMP AL, #'Q' 
 +    JZ @quit_game 
 + 
 +    RET 
 +</codify> 
 + 
 +This is easy enough; after a CMP, if the values are equal then the zero flag is set. We will use JZ (jump if zero flag is set) to go to the correct routine. 
 + 
 +=== processing each command 
 +<codify armasm> 
 +move_left: 
 +    LDAL [@PX]        ; load variable PX into register AL. 
 +    DEC AL            ; X = X - 1 (move to the left!) 
 +     
 +    CMP AL, #1        ; bounds check. Is the player on the border? 
 +    JC @ml_ok         ; AL >= 1, so it's ok. skip to ml_ok, 
 +     
 +    LDAL #1           ; If  we reach here the player was on the border; set position to 1. 
 +     
 +ml_ok: 
 +    STAL [@PX]        ; pass! Save the player's location. 
 +    RET 
 +</codify> 
 + 
 +This is the move_left command. We begin by loading the player's X location into AL and executing the move. After a bounds check, we save the variable. All of the other moves operate this way.
sd/part_ii_writing_games_in_assembly_language.1775158957.txt.gz · Last modified: by appledog

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki