; ; asm_decoder_translate_e8() ; ; Assembly implementation of this from decxlat.c ; ; 26-Jul-96 jforbes Initial version ; TITLE XLATASM.ASM .386P .model FLAT PUBLIC _asm_decoder_translate_e8 OFFSET_INSTR_POS equ 28 OFFSET_FILE_SIZE equ 32 OFFSET_MEM equ 36 OFFSET_BYTES equ 40 ; ; ulong asm_decoder_translate_e8(instr_pos, file_size, mem *, bytes) ; ; returns new instr_pos in EAX ; _TEXT SEGMENT _asm_decoder_translate_e8 PROC NEAR push ebx push ecx push edx push esi push edi push ebp ; edx = bytes mov edx, DWORD PTR [esp + OFFSET_BYTES] ; if (bytes >= 6) cmp edx, 6 jge greater_than_6_bytes ; ; less than 6 bytes to translate, so don't translate ; ; instr_pos += bytes add edx, [esp + OFFSET_INSTR_POS] ; return new instr_pos in eax mov eax, edx pop ebp pop edi pop esi pop edx pop ecx pop ebx ret 0 greater_than_6_bytes: ; ebp = current_file_size mov ebp, DWORD PTR [esp + OFFSET_FILE_SIZE] ; ebx = 0xE8, our magic number mov ebx, 0E8h ; 232 ; esi = instr_pos mov esi, DWORD PTR [esp + OFFSET_INSTR_POS] ; ecx = mem mov ecx, DWORD PTR [esp + OFFSET_MEM] ; edi = instr_pos + bytes - 6 mov edi, esi add edi, edx sub edi, 6 ; backup the last 6 bytes in the buffer sub esp, 6 ; eax = &mem[bytes-6] mov eax, ecx add eax, edx sub eax, 6 mov edx, [eax] mov [esp], edx mov dx, WORD PTR [eax+4] mov WORD PTR [esp+4], dx ; now store 0xE8's in there mov DWORD PTR [eax], 0E8E8E8E8h mov WORD PTR [eax+4], 0E8E8h ; save &mem[bytes-6] push eax ; ; main loop ; ; eax = temporary ; ebx = 0xE8 ; ecx = source ptr ; edx = temporary ; esi = instr pos ; edi = end_instr_pos ; ebp = current_file_size ; loop_top: ; ; while (*mem++ != 0xE8) ; ; ; eax = mem before mov eax, ecx ; u1 nop ; v1 main_subloop: cmp bl, [ecx] ; u2 je SHORT equals_e8 ; v1 cmp bl, [ecx+1] ; u2 je SHORT pre1 ; v1 cmp bl, [ecx+2] ; u2 je SHORT pre2 ; v1 cmp bl, [ecx+3] ; u2 je SHORT pre3 ; v1 add ecx, 4 ; u1 jmp SHORT main_subloop ; v1 pre3: add ecx, 3 ; u1 jmp SHORT equals_e8 ; v1 pre2: add ecx, 2 ; u1 jmp SHORT equals_e8 ; v1 pre1: inc ecx equals_e8: ; instr_pos += bytes visited in above loop ; esi := esi + (ecx - eax) sub esi, eax ; u1 add esi, ecx ; v1 ; ; Here is the only place we check for the end. ; ; We can do this because we force an 0xE8 at the end ; of the buffer. ; ; We cannot overlap the MOV below in between the ; cmp/jge, because ecx+1 may point to invalid memory. ; cmp esi, edi ; u1 jge SHORT bottom ; v1 ; eax = absolute = *(long *) mem mov eax, [ecx+1] ; u1 add ecx, 5 ; v1 memptr += 5 ; ; if (absolute < current_file_size && absolute >= 0) ; ; use unsigned comparison here so that if absolute < 0 ; then it seems like it's some huge number ; ; this way we only do one comparison, abs >= file_size ; cmp eax, ebp ; u1 jae SHORT second_check ; v1 ; ; instead of doing "offset = absolute - instr_pos" and ; then storing it, we just say *mem -= instr_pos ; ; instead of: ; ; sub eax, esi ; mov [ecx-4], eax ; ; we do: sub [ecx-4], esi ; u3 add esi, 5 ; v1 instr_pos += 5 mov eax, ecx ; u1 (copied from loop_top) jmp SHORT main_subloop ; v1 ; ; we want (absolute < 0) && (absolute >= -instr_pos) ; ; which can be rewritten as: ; ; (-absolute > 0) && (-absolute - instr_pos <= 0) ; ; then: ; ; (-absolute > 0) && (-absolute <= instr_pos) ; ; we can do both of these checks by checking with ; unsigned arithmetic, since if absolute < 0 then it ; will seem like some huge number: ; ; if ((ulong) (-(long) absolute) <= instr_pos) ; ; note: absolute==0 is taken care of in the first case ; second_check: ; edx = instr_pos + absolute neg eax ; u cmp eax, esi ; u1 ja SHORT no_conversion ; v1 ; ; instead of storing "offset = absolute + current_file_size" ; we can do *mem += file_size. ; ; instead of doing: ; ; neg eax ; add eax, ebp ; mov DWORD PTR [ecx-4], eax ; ; we do: add [ecx-4], ebp ; u3 no_conversion: ; instr_pos += 5 add esi, 5 ; v1 u1 jmp SHORT loop_top ; v1 bottom: ; instr_pos = end_instr_pos + 6 add edi, 6 ; restore the 6 bytes ; get &mem[bytes-6] pop eax mov edx, DWORD PTR [esp] mov DWORD PTR [eax], edx mov dx, WORD PTR [esp+4] mov WORD PTR [eax+4], dx add esp, 6 ; return new instr_pos in eax mov eax, edi pop ebp pop edi pop esi pop edx pop ecx pop ebx ret 0 _asm_decoder_translate_e8 ENDP _TEXT ENDS END