DATABASE LOGIC STEPPING PROGRAM - IMPLEMENTATION FILE BX - Current Spot in DB INITIALIZATION STEP COMMENTS ASSEMBLY OPCODES Op Dest [Src] Op Data Setting Up Eval Actions | Set Eval Result → MOV ← ?? C606 ???? ?? Adjust Pointer To SIZELEN From SIZE | Compare Skip Value To 0 CMP AL ← 00 3C ?? | Jump To Grab SIZELEN If Not 0 JNZ 75 ?? | Skip Over Max SIZE ADD BX ← 0xFF 83C3 FF Size Length Zero? | Compare Size Length To Zero CMP [BX] ← 00 ???? 00 | Jump Result If Match JE 74 ?? The following function is set up to behave differently as it loops - to satisfy Initial, A, B and C requirements in the notes, in a single block of code. CONDITIONAL SIZE This is what we send back if SIZELEN is zero. Tells other programs we didn't find anything. | Set DX to Zero Return Value MOV DX ← 01 00 BA 01 00 If SIZELEN is 0, all there is here is a zero. We're done! | Grab SIZELEN to AL MOV AL ← [BX] 8A07 | Compare Data To 0 CMP AL ← 00 3C 00 | Jump if No Match JNE 75 ?? The first cycle of this is NOP'd. This is designed to skip SIZELEN checks. Do we need this..? | Jump To Increment BX (/ NOP) JMP EB ?? I might not include this if I still can't think of why it's there. Maybe it was a jump point for custom SIZELEN interpretation? No point to that unless it's an E9 XXXX. Store SIZELEN in CL, so we remember its real size. We might not use the whole size, and we might treat the value the same as other sizes. But we will need to correctly skip over the real size of the data, so we need this to stick around. | Put SIZELEN in CL MOV CL ← AL 88C1 This code can be hijacked at JB to handle SIZELENs above 5. Currently, the real size is remembered, but the data is treated as SIZELEN of 4 by the reader. You can make it stop like at SIZELEN 0 if you like, just jump to the same spot as that JNE. | Compare SIZELEN To 5 CMP AL ← 05 3C 05 | Jump if Below JB 72 ?? | Set SIZELEN To 4 MOV AL ← 04 B4 04 The SIZELEN now holds a value from 0x01 to 0x04. We ruled out 0x00 with the earlier check. You will *hang* your system if this *ever* eats a 0x00 in AL. I make sure not to, but don't let that happen to you! Always wrap this in a zero check! Move BX to wherever the SIZE data is. can be one byte ahead, but can also be somewhere dependent on SIZELEN. This needs to be fleshed out to handle that. [ PLEASE IMPLEMENT ME! ] Previous code for that was just an increment. The things I do for cool data structures. | Add/Subtract Position To BX INC BX 43 The reason I'm sacrificing the glorious INC is so that the database can have a variable length SIZE field without changing the SIZELEN or the start position of the DB to other programs. <---SIZE expands this way-| SIZELEN (1 byte) |-DB expands this way---> Look how nice that is. Now imagine if SIZE's arrow had to go in the other direction. It'd overwrite or force data to move and that's not good. In other words, fix 255 bytes for SIZE, take how many bytes you need, and set SIZELEN to reflect it. Ignore the unused bytes or add a silly <255 character comment. We're dividing SIZELEN by 2. This will tell us two things - if the number is even, and if it's greater than two. This is everything we need to know. Remember, the number is 0x01 to 0x04. With the above we can know exactly which number it is - more importantly, what to and not to do based on the number. I specifically arranged the meanings attached to the numbers (since it's arbitrary) to make the check work in one pass. | Set CH To 2 MOV CH ← 02 B5 02 | Divide AL By 2 DIV AL ← CH F6 F5 We're not returning that default value anymore - we want this zeroed. (Do we really?) | Zero DX XOR DX ← DX 31 D2 Take the first word of SIZE and add it to the value in DX, which is now zero. | Add Size Data To DX ADD DX ← [BX] 89 1F Hey, wait a second. Can't I just do a MOV? [ CHECK THIS LATER ] If the SIZELEN was even, AH will be zero. We can skip the code for relative addresses - our address must be absolute. | Compare AH to 00 CMP AH ← 00 80FC 00 | Jump Multiply AL JE 74 ?? If the SIZELEN was odd, we run this code. First, we subtract the SIZE word, undoing what we did earlier. | Subtract Size Data from DX SUB DX ← [BX] 2B 1F Then we do the right thing - adding the SIZE *byte*. | Add Size Byte to DX ADD DX ← [BX] 88 1F Then, since this is relative, we add the current location. | Add Current Location to BX ADD DX ← BX 8B D3 We exclude the size from this calculation. | Add Size Length to DX ADD DX ← CL 8A D1 Because of our fancy SIZE structure, this isn't enough. We'll be sitting at SIZELEN in that case, so we'd also need to push forward by one. We should add an Increment DX/NOP here. Single byte, so easy to NOP. | Increment DX (/NOP) INC DX 42 [ DON'T FORGET TO NOP ME ON CONDITION! ] 1 00 01 2 01 00 3 01 01 04 02 00 Add the remainder to AL, then Multiply AL by 2. | Add AH to AL ADD AL ← AH | Multiply AL By 2 MUL AL ← CH Intel uses 'Less' to describe signed integer < checks and 'Below' to describe unsigned < checks. Signed means that 00-FF is split in uneven halves at the highest bit, and half is 'positive', half is 'negative'. 'Positive' numbers use up a spot for zero, so negative always goes one bit farther. If positive has up to the integer 3, negative will have up to -4, for example. Try to avoid mixing up signed and unsigned checks, even when they would normally behave the same, unless you're doing something special. If the value in AL | Compare SIZELEN(AL) to 2 CMP AL ← CH 3C 02 | Jump if Below or Equal JBE | Increment BX INC BX 43 | Jump To Increment BX (/ NOP) JMP EB ?? |