https://retrocomputing.stackexchange.com/questions/29565/does-this-8088-code-in-the-leisure-suit-larry-2-game-actually-do-anything Stack Exchange Network Stack Exchange network consists of 183 Q&A communities including Stack Overflow, the largest, most trusted online community for developers to learn, share their knowledge, and build their careers. Visit Stack Exchange [ ] Loading... 1. + Tour Start here for a quick overview of the site + Help Center Detailed answers to any questions you might have + Meta Discuss the workings and policies of this site + About Us Learn more about Stack Overflow the company, and our products 2. 3. current community + Retrocomputing help chat + Retrocomputing Meta your communities Sign up or log in to customize your list. more stack exchange communities company blog 4. 5. Log in 6. Sign up Retrocomputing 1. 1. Home 2. Questions 3. Tags 4. 5. Users 6. Companies 7. Unanswered 2. Teams Stack Overflow for Teams - Start collaborating and sharing organizational knowledge. [teams-illo-free-si] Create a free Team Why Teams? 3. Teams 4. Create free Team Teams Q&A for work Connect and share knowledge within a single location that is structured and easy to search. Learn more about Teams Does this 8088 code in the Leisure Suit Larry 2 game actually do anything? Ask Question Asked 2 days ago Modified today Viewed 9k times 28 In the Sierra On-Line game "Leisure Suit Larry 2" there's a part in the game where the main character (Larry) has to write a program in 8088 assembly language as part of his tribal initiation. Larry then jokes that he's written a multi-user operating system called "Eunuchs". Animated screenshot showing the scene from the game The code shown in the game is: INT 21 JB 0103 MOV AH,4D INT 21 CS: MOV [0BEA],AX JMP 02B2 JMP 1451 CS: TEST BYTE PTR [0C59],01 JZ 0150 CS: TEST BYTE PTR [0C59],02 JZ 014F IRET INT 21 JB 0103 TEST BYTE PTR [0C59],04 JZ 0169 CMP AH,01 JA 014F I haven't run this code as I presume it probably isn't complete, but does anyone know what it might do? * programming * assembly * gaming Share Improve this question Follow edited yesterday user3840170's user avatar user3840170 23k44 gold badges9191 silver badges149149 bronze badges asked 2 days ago Noel Whitemore's user avatar Noel WhitemoreNoel Whitemore 46322 silver badges1010 bronze badges New contributor Noel Whitemore is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 12 * 4 It seems to be nonsense. Some of the int 21h calls don't specify the call, and AH = 4D requests the result of an exec call which hasn't been made. There's a spurious IRET in the middle of it. The jump and branch destinations are meaningless without more context. The protagonist can't have written a "multiuser OS" in 20 lines using MS-DOS calls. It's the code equivalent of a panel with fake leds and gauges. - Weather Vane 2 days ago * 9 Most people here may already know this, but "Eunuchs" is a pun on UNIX, which is an actual multi-user operating system (but it never ran natively on an 8088). And UNIX was, itself, a pun - it was envisioned as a simpler version of MULTICS. - Jacob Krall 2 days ago * 7 @JacobKrall Unix was of course available for the 8088PC/XT. Even trice, first as V7 based Venix/86, then as System III based Xenix 3 Release 1 by SCO and last as System V based PX/ix by IBM (developed by Interactive Systems). All in the 1983/1984 time frame and each under genuine AT&T licence. - Raffzahn 2 days ago * 2 @JacobKrall memory protection is a good thing, not just for multi user, even on single user/single tasking like DOS. Still, it's just a nice add on, not necessary for anything. Also, Unix does not need multiple users either. - Raffzahn 2 days ago * 8 Being Leisure Suite Larry, I'm somewhat surprised it's not 80085 Assembly language! - Jon P yesterday | Show 7 more comments 4 Answers 4 Sorted by: Reset to default [Highest score (default) ] 34 It's most definitely not a program 'written' by a programmer, but rather a listing of some random program segment using the disassembly command of a debugger. Have you tried to find that code within the program? Let's See What We Got Hard to say anything definitive with only this (incomplete) section. A few details visible are: 01: INT 21 ; An unknown (*1) call to DOS, function code would have been set prior to this line 02: JB 0103 ; Jump to address 0103h if DOS returns NO error 03: MOV AH,4D ; Get return code from DOS (*1) 04: INT 21 05: CS: ; (*2) 06: MOV [OBEA],AX ; Save return information within the program code at offset 0BEAh 07: JMP 02B2 ; Continue at 02B2h 08: JMP 1451 ; Continue at 1451h (*3) 09: CS: ; (*4) 10: TEST BYTE PTR [0C59],01 ; Test the lowest bit of the byte at 0C59h within code 11: JZ 0150 ; Continue at 0150h if not set (*6) 12: CS: 13: TEST BYTE PTR [OC59],02 ; Test the second lowest bit 14: JZ 014F ; Continue at 014Fh if not set (*6) 15: IRET ; Return from Interrupt to terminate the program(*5,*6) 16: INT 21 ; Again a an unknown DOS call (*7) 17: JB 0103 ; Continue at 0103h if no error reported (*8) 18: TEST BYTE PTR [0C59],04 ; Test the third lowest bit 19: JZ 0169 ; Continue at 0169h if not set 20: CMP AH,01 ; check AH for 01h (*7) 21: JA 014F ; If AH was greater than 01h continue at 014Fh (*9) *1 - Since the second INT 21h (L:04), made when an error is returned, asks DOS for a program's return code, the previous DOS call (L:01) was most likely an EXEC call to run a different program as child process. Using this function also tells that the program was written/ compiled for MS-DOS 2.0 or later. *2 - A hint that the debugger used was most likely the one supplied with MS-DOS. *3 - Line 08 might be a target from a previous branch, one like the one on L:02. Such would be a typical compiler structure to continue from a branch to a destination more than 128 bytes away. *4 - An entry point, like *2, except here operation continues *5 - Using an IRET here is a strong indicator that the program may be a .COM program and this being used to terminate it. DOS prepares the memory of a COM program much like CP/M, including a way that a jump at address 0000h will terminate it. This is done by placing it's original termination interrupt INT 20h at the start of the PSP - which is at CS:0 for COM programs - and pushing a word of 0000h onto the stack. Now a simple RET NEAR can be used to terminate. This of course only works if CS doesn't get changed inbetween. A condition true for most simple programs, especially such converted from 8080 code. To still use that way of termination while possibly changing CS during program run it was common for COM programs to start by pushing CS and another word of 0000h onto the stack. Now a RETF could used, no matter what content CS had at the moment (and as long as all stack levels were cleaned up). EXE programs added a little issue as their initial CS is not pointing to the PSP. But DS is loaded in both types with the PSP address, so pushing DS instead of CS would make the code usable for both types of program. Since that 'trick' would leave a a single word on stack (the one provided by DOS to start with), it became common to use an IRET instead of a RET FAR, which does take that word as well off the stack. Not that it made a difference, but it felt better :)) *6 - It's extreme hard to do any guess without knowing the address that code is located. But having two jumps targeted only one byte apart means that either some (for x86) unusual program trick is used, or 014Fh containing a single byte instruction. Considering that an IRET/INT combination is rather unusual and that IRET is a single byte instruction, it could quite well be that it's address is 014Fh. But then again the previous JZ wont make much sense, as either way would lead to taking the IRET. *7 - Checking AH after DOS functions is rare, as the standard return code is contained in AL (AX). Get Return code (see L:03/04) in turn does use AH and AL different. AL contains the child return code, while AH contains the termination reason. Here 00h/01h are regular termination reasons, while 02h is a critical error abort. Checking for above 01h would make sense if the previous INT 21h was as well an EXEC call. *7 - Note this being he same target as used on line 02, which seems to be the default good exit. *8 - Note this being he same target as used on line 14 --------------------------------------------------------------------- Conclusions From Code The code snipplet is most likely part of an exec function that starts a child program and checks if the execution went well and continues afterwards. It might thus be some menu system/framework starting overlay modules for different tasks (game sections??). It seems to be written in some High level language. Also, it's most likely not from DOS or any OS level software, but user space, as it used INT 21h functions. Using the IRET termination hints to some really old code with DOS 1.x origin, or a compiler using that trick to save code size if here are multiple termination points. It must be an older one, as MS discouraged use of returning via PSP:0 and INT 20h in general with DOS 3 Taking into account that the target for 'good' execution (L:02/L:17) points to a very low address within this code, this could be an endless loop starting around the loading and executing a child process. Together with the fact that it checks flags within its own code segment after returning from the child process to decide how to continue, I could imagine this being a loader for a larger program, whose only job is to reload that program whenever it got normally terminated, unless some flags have been set by the child before termination. A program like this could be a simple solution to catch certain errors without adding lots of error checking code within the application. Any error detection would just exit the child, which then gets restarted from above code. Note: These are all wild guesses, not necessary true. There is no way to tell where it's originated, unless one finds exactly that code in some program. Now, What is It? Nothing. I'd say they just started up their debugger, loaded some program, dumped a random section of 21 lines and copied them into the game text. Could be from the game or any other program. Share Improve this answer Follow edited 22 hours ago answered 2 days ago Raffzahn's user avatar RaffzahnRaffzahn 219k2222 gold badges617617 silver badges908908 bronze badges 2 * Comments have been moved to chat; please do not continue the discussion here. Before posting a comment below this one, please review the purposes of comments. Comments that do not request clarification or suggest improvements usually belong as an answer , on Retrocomputing Meta, or in Retrocomputing Chat. Comments continuing discussion may be removed. - Chenmunka 1 hour ago * @Chenmunka Moving these comments seems like a _very_bad move as they contained a lot of follow up information (Like Al Lowes own reply). Those actions seem to be quite random and not really targeting off topic comments. Might be better for all to keep a more hands off approach. - Raffzahn 19 mins ago Add a comment | 15 As a whole, the code doesn't make much sense, though some instruction sequences in it do look somewhat realistic. Judging by the form of each instruction, the code was almost certainly obtained by disassembling some binary using MS-DOS's bundled debugger DEBUG. Almost all the syntax choices are consistent with the style used by that program: * segment-override prefixes are written on a separate line, as if they were stand-alone instructions * everything is written in capital letters * hexadecimal constants are written in full width (with leading zeroes) and without any numeric base suffixes * all memory locations are denoted with bare addresses and not symbolic references * memory operand size specifiers like BYTE PTR are only used when their lack would result in ambiguity * the branch instruction after a syscall is written with the mnemonic JB (jump if below), where manually-written code would more often use the mnemonic JC (jump if carry set) for the same instruction * no spaces after commas separating operands * the number of spaces between opcode mnemonics and operands (as stored in game files; this may be hard to measure when the game displays the code in a proportional font) matches DEBUG disassembly output exactly Not all of these are strong indicators, but their lack would have been a rather telling counter-indicator that, at the very least, the code was edited. Which there was little reason to do anyway, given that the code is basically used merely as filler text. As for what it does, this is what I can tell from reading it: * At the beginning there is an MS-DOS syscall instruction, INT 21; we don't know which syscall it was meant to invoke, but judging by the following code, it was likely the "exec" syscall. It is followed by a test of the carry flag (which is how the DOS kernel signals errors), and then immediately by an invocation of the "wait"^1 syscall, the return value from which is stored in memory. This fragment looks rather realistic. * After that, there are two unconditional jump instructions, one after the other. These may extend the range of conditional branch instructions elsewhere (on the 8086, conditional branches are normally limited to a 256-byte range), or maybe some shown here. Or they may be a dispatch table, though these usually do not appear after straight-line code. Without the full code, I cannot tell. * Further down, a single memory location has it bits checked, one after the other, with a conditional branch after each test. In the middle of it, there is an IRET instruction and a repetition of code from before; these look especially out of place, as if the code were altered. The subsequent bit test is missing a segment-override prefix. Other than that, this fragment also looks pretty typical. * And finally, there is a check whether the AH register is larger than 1, and a corresponding branch instruction. The code ends before any point where the result of that check could be used. I can't help but wonder if this piece was meant to go after the "wait" syscall mentioned earlier. All in all, I would guess that the code is a disassembly of a real binary (or perhaps taken from two different binaries), which was then altered slightly and maybe had instructions shuffled in order to disguise the code's origin, and thus avoid a copyright-infringement lawsuit. Or maybe it was obtained by launching DEBUG without loading any binary and then immediately disassembling, in which case it is a disassembly of whatever uninitialized contents the memory had at that time. Unfortunately, the binary encoding corresponding to the jump/branch instructions will depend on the address from which they run (while MOV [0BEA],AX even has an ambiguous encoding, which may be either A3 EA 0B or 89 06 EA 0B; but it probably was the former). This means it will be pretty hard to identify the original binary code just from that listing. If you want to hunt for the executable yourself, the longest instruction with an unambiguous encoding is (CS:) TEST BYTE PTR [0C59], xx which corresponds to the byte sequence (2E) F6 06 59 0C xx, and the first six lines of the listing probably correspond to a byte sequence matching CD 21 72 ?? B4 4D CD 21 2E A3 EA 0B. I was unable to find any binary with this code myself, but I did not look all that hard. --------------------------------------------------------------------- ^1 RBIL does not use this name, but MS-DOS did. It was one of many "Eunuchs" inspirations in MS-DOS 2. Share Improve this answer Follow edited 7 hours ago answered 2 days ago user3840170's user avatar user3840170user3840170 23k44 gold badges9191 silver badges149149 bronze badges 5 * Thank you for your answer and suggestions for byte searches. The closest match I could find for your CD 21 72 ?? B4 4D CD 21 2E A3 EA 0B byte string was 5F 5E 72 04 B4 4D CD 21 E9 C6 E7 00 which was in the install.exe file. This is in a segment of code that shortly after has copyright information for the "MS Run-Time Library". - Noel Whitemore 2 days ago * 1 @NoelWhitemore That's not even close, actually. B4 4D CD 21 is just MOV AH,4D / INT 21, which is almost bound to appear somewhere if a DOS program spawns subprocesses at all, but it isn't particularly specific. - user3840170 2 days ago * @user3840170 I agree it's not close, but that's the closest match I've found in either of the executable files to part of your string. The other strings I couldn't match at all. - Noel Whitemore 2 days ago * 1 I agree, the output was most likely made using DEBUG's U command. Still some points (2&7) given do not really resonate. It was quite common to write assembly source in all caps and without any space after a comma. Using lower case and random spaces are mannerism that only came into use rather recent (I'd say 1990s onward). Possibly due gaining popularity of C and Unix. - Raffzahn yesterday * 3 @user3840170 I heard back from Al. He thinks it might be from the COMMAND.COM file shipped with MS-DOS. I found a match for CD 21 72 D2 B4 4D CD 21 2E A3 early on in a random COMMAND.COM file from MS-DOS 3 I just downloaded off of archive.org so that looks promising. - Noel Whitemore 22 hours ago Add a comment | 8 In a brief email conversation with Al Lowe (yes, the man himself!) he suggested that he probably used the COMMAND.COM file as the basis for this code as it would have been installed on every PC. Booting up a vanilla copy of MS-DOS(R) Version 3.30 and using the debug tool on the COMMAND.COM file shows the following disassembled code: MS-DOS debug output of COMMAND.COM MS-DOS debug output of COMMAND.COM Accepting some variation in the byte code due to differences between MS-DOS versions, I think for all practical purposes this is fairly close to what's seen in the game. Share Improve this answer Follow answered 2 hours ago Noel Whitemore's user avatar Noel WhitemoreNoel Whitemore 46322 silver badges1010 bronze badges New contributor Noel Whitemore is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. Add a comment | 0 The thing that immediately leaps out to me is that the hex address OBEAh is apparently a pun - it's a "hex" address, and the word "Obeah" is of Jamaican origin, meaning JuJu, magic, which might make garbled sense in the context of a tribal initiation. Share Improve this answer Follow answered 57 mins ago Ben Collier's user avatar Ben CollierBen Collier 1 New contributor Ben Collier is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. Add a comment | You must log in to answer this question. Not the answer you're looking for? Browse other questions tagged * programming * assembly * gaming . * The Overflow Blog * Even LLMs need education--quality data makes LLMs overperform * How to convince your CEO it's worth paying down tech debt * Featured on Meta * Upcoming privacy updates: removal of the Activity data section and Google... * Changing how community leadership works on Stack Exchange: a proposal and... Linked 13 Difference between INT 0x20 and INT 0x21 (0x4C)? Related 11 How does JSR actually work on the 65c816 CPU for the SNES (Super Nintendo)? 9 Why does this 6502 code push a function address onto the stack before calling? 15 Why does this ZX Spectrum machine code "Hello World" routine not produce the expected result? 31 Does the video game Control (2019) depict a real computer system? What is it? 17 Does this 1978 code for a 6800 really clear ALL of memory? Hot Network Questions * Hermiticity of a projection operator * How to define (not reproject) a CRS of a shapefile in QGIS? * When was Hermann Hesse arrested for 'seducing a young girl'? * Why is the horizon problem a problem? * The implication if we discovered that natural abiogenesis is statistically nearly impossible * Are there mutually independent undecidable statements? * Are bells the only instrument whose second harmonic forms a minor interval with its fundamental? * Decompose a function into a bounded part and a Lipschitz part * Is one hour enough for a connection in Bogota? * Why were the SRB cameras looking down called "forward cameras"? * Can someone tell me what kind of fitting for this toilet water shut off valve is? * Why std::allocator::allocate calls ::operator new? * What is the meaning of the RGB band value is more than 255 * Firefox on Ubuntu 22.04 is garbled on HP laptop * Who is Dracula's son as mentioned in the song Monster Mash? * Brian Chen's Splash 2016 hunt #5 * I2C signals over longer wires * One party member in the tavern, the others doing a heist * Reviewer's Concerns about Excessive Simulation Results * Does it economically cost the same to launch a satellite into LEO and GTO? * The salesman said," You need to fill in this form before getting the exchange." Convert this into reported speech * Why require permanent pens and disallow correction tools in exams? * Thunderwave in constricted area * Search the deepest depths of an array more hot questions Question feed Subscribe to RSS Question feed To subscribe to this RSS feed, copy and paste this URL into your RSS reader. [https://retrocomputi] * Retrocomputing * Tour * Help * Chat * Contact * Feedback Company * Stack Overflow * Teams * Advertising * Collectives * Talent * About * Press * Legal * Privacy Policy * Terms of Service * Cookie Settings * Cookie Policy Stack Exchange Network * Technology * Culture & recreation * Life & arts * Science * Professional * Business * API * Data * Blog * Facebook * Twitter * LinkedIn * Instagram Site design / logo (c) 2024 Stack Exchange Inc; user contributions licensed under CC BY-SA. rev 2024.2.27.5415