Decoded: Rogue (1980) by Toy, Arnold, Wichman DOS version (1983) by Mel Sibony and Jon Lane Source file: BEGIN.ASM Beginner friendly, line-by-line code walkthrough by MaiZure BEGIN.ASM sets up segments and passes command line arguments in to the C loader (Croot.C). This is a generic .EXE loader using a small memory model Original code: https://britzl.github.io/roguearchive/ Original code with line numbers http://www.maizure.org/projects/decoded-rogue/BEGIN_linenum.txt 1 COMMENT 2 COMMENT 3 COMMENT 4 COMMENT (tab stop set to 8) 5 Begin code segment 6 Expose the heap top variable ($MEMRY). This is an Aztec C managed symbol 7 Expose memory start (ds end), stack bottom (stack pointer), user mem 8 Begin data segment 9 Heap is current uninitialized 10 errno is 0 11 Expose CS and DS values 12 Expose data segment and code segment addresses 13 Init CS to 0 14 Init DS to 0 15 Init mbot to end of DS...which is zero right now 16 Stack is also zero for now 17 Label for low memory area set up 18 Import user memory space from compiler 19 End of data segment 20 Expose exit for code segment and data segment 21 End of code segment is 0 for now 22 End of data segment is 0 for now 23 BLANK 24 Assume CS register is the code segment, all other segments are dataseg 25 Import the Croot_ call linked from CROOT.C 26 Expose the real entry point 27 Expose the real exit point ABSOLUTE ENTRY POINT 28 Begin program 29 The data segment address to the base pointer 30 Check if the data segment base has a nonzero value 31 This isn't a .COM file if the data segment has data (.COM files are are only 64kb code segments) 32 This *might* be a .COM, move base pointer to the supposedly blank ds HANDLING NON .COM (.EXE) FILE - SET UP LARGE MEMORY SEGMENTS 33 Label for exe file processing 34 The last line of the code segment would also be the base of the ds 35 Move the next byte in to DS in to BX (Segment top) 36 Subtract bp from bx (These should span a segment of memory, get size) 37 Compare segment differences with 4096 (There are 4096 paragraphs in a segment. Each segment increments on the paragraph, hence paragraph aligned) 38 If segments are < 4096, we're using small memory model. Jump to line 45 39 Get the address of the end of the segment in to bx 40 Move an unused segment pointer in to AX 41 Calculate segment size and store paragraph size in to BX 42 Clobber AH to set up the resize memory block syscall 43 Invoke DOS syscall to resize memory to segment size 44 Clobber BX with a 64k segment size SET UP STACK AND CLEAR MEMORY 45 If we're using small segments (we're setting it up in all cases) 46 Move the base pointer (within DS), in to BX 47 Set CL to 4 to prep for a shift of the initial stack pointer 48 Shift 4096 (or smaller value in BX) left by 4 for a maximum of 64k 49 Disable interrupts while we set up the stack 50 Set the current segment in bp (the DS?) as the bottom for the stack 51 Set the newly calculated stack segment span from BX to the top in SP 52 Enable interrupts 53 Set DF to 0 while we clear data 54 COMMENT 55 Move the base of the user segment to the offset of the user data origin 56 Move the offset of the end of user data in to CX 57 Subtract both to get the size of the segment in to CX 58 Plus 1 59 And cut in half to get the number of words (16-bit blocks) 60 This may be zero...if so, jump to line 63... 61 Otherwise, clear AX to use as the source 62 Repeatedly store 0 across the entire user data segment (~.BSS) GET SYSTEM INFO FROM DOS 63 Label to jump past the data clearing section 64 COMMENT 65 Move 0x2c in to the environmental segment 66 Clear the desintation index 67 Move the ES pointer to the memory address of the DOS Environment variables in the PSP SEARCH FOR ARGUMENTS 68 Label to check for arugments 69 Move the first byte of the environment in to AH 70 Check if the first byte has no name (is null) 71 If it is null, then the arguments must be next, jump to line 83 72 Otherwise, test if that byte has any value 73 If no value, there is no environment, and no arguments. Jump to line 76 74 Otherwise, scan the segment for no value 75 If found, jump back to line 68 and test for arguments again NO ARGUMENT HANDLER 76 There are no arguments to set up... 77 Set CL to 128 to prepare for the largest possible argument buffer 78 Clear CH to ensure 128 in CX 79 Move 0x81 in to the source index 80 Set AX to 1 81 Jump to line 89 to move the entire argument string on to the stack ARGUMENT HANDLER 82 COMMENT 83 Label for argument handler 84 Clear AX 85 Skip the argument start delimiter 86 Change destination to source... 87 Change extra (stack) segment in to the destination index 88 Move the dest (stack) index to the data segment 89 Prepare to move arguments... 90 Push the first argument (argument counter) on to the stack 91 The actual data segment is still in BP, move it to ES 92 The end of the heap (empty heap) is the address in ES 93 Push this value to stack as an argument to the program 94 CX still contains the size of the argument string... if zero jump to 101 95 Label for copy args 96 Get all the args in to memory 97 Check if we didn't grab anything 98 If nothing then we're done jump to 101 otherwise continue... 99 Store the argument on the heap 100 Redo the loop as needed 101 We're done! Let's finalize the game segments 102 Clear AL 103 Store the cleared AL at the end of the arugment string (nullterm) 104 Store this heap segment in to DS 105 Increment the destination 106 Drop the trailing memory address (word align) 107 Move this address to $MEMRY -- top of the heap 108 It's also the bottom 109 Move the stack pointer in to AX 110 Kick it down 2kb for some stack space 111 This is now the bottom of the stack 112 Save the final value of DS in to program env variable 113 Save the final value of CS in to the program environment variable 114 Call the game loader! 115 Jump to the end EXIT POINT 116 Almost final exit point 117 Skip top stack value 118 Get the return value 119 Final exit point 120 Prepare for return with exit code 121 Invoke software interrupt 122 Jump out of this program 123 End the source file 124 End of the code segment 125 Fin! 126 EOF˙