Skip to content

Commit

Permalink
Move the 16-bit bridge heavy-lifting to the 32-bit code segment.
Browse files Browse the repository at this point in the history
Now we save off the stack pointer and immediately jmp back to 32-bit. This is
slightly easier to debug (gdb doesn't get confused by addresses, registers or
disassembly), and puts all the 32-bit registers in a 32-bit code segment, to
keep things sane.

Also: doesn't write duplicate instructions to update %ds and %es if they are
the same values in Linux land.
  • Loading branch information
icculus committed Jan 4, 2018
1 parent b72ccd6 commit 44565f5
Showing 1 changed file with 42 additions and 32 deletions.
74 changes: 42 additions & 32 deletions native/os2native16.h
Expand Up @@ -66,19 +66,20 @@

/* This is the original assembly code, for use with NASM.
USE16 ; start in 16-bit code where our 16-bit caller lands.
MOV BX, SS ; save off ss:sp
MOV CX, SP ; save off sp
JMP DWORD 0x7788:0x33332222 ; jmp into the 32-bit code segment (the next instruction!).
USE32
MOV BX, SS ; save off ss
SHL EBX, 16 ; scootch over!
MOV BX, SP ; save off ss:sp
MOV BX, CX ; %ebx now has 16-bit ss:sp
; our stack is tiled, so we can easily find the linear address of it.
MOV AX, SS ; move the stack segment into the low word.
SHR AX, 3 ; shift out the control bits from the segment.
SHL EAX, 16 ; move the remaining selector bits to the high word of %eax
MOV AX, SP ; move the stack offset into the low word. Now %eax has the linear stack pointer.
MOV AX, CX ; move the stack offset into the low word. Now %eax has the linear stack pointer.
JMP DWORD 0x7788:0x33332222 ; jmp into the 32-bit code segment (the next instruction!).
USE32
MOV CX, 0xABCD ; original linear stack segment from lx_loader's main().
MOV SS, CX
MOV ESP, EAX ; and the same stack pointer, but linear.
Expand All @@ -104,8 +105,8 @@ POP ES ; get back caller's %es register.
POP DS ; get back our 16-bit data segment.
; Restore 16:16 stack. !!! FIXME: can use LSS if we figure out prefix and DS politics.
POP BX ; Get our original ss back.
POP CX ; Get our original sp back.
POP BX ; Get our original sp back.
POP CX ; Get our original ss back.
JMP WORD 0xAAAA:0xBBBB ; back into 16-bit land (the next instruction!).
Expand All @@ -120,32 +121,37 @@ RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling
\
/* instructions are in Intel syntax here, not AT&T. */ \
/* USE16 */ \
*(ptr++) = 0x8C; /* mov bx,ss... */ \
*(ptr++) = 0x89; /* mov cx,sp... */ \
*(ptr++) = 0xE1; /* ...mov cx,sp */ \
*(ptr++) = 0x66; /* jmp dword 0x7788:0x33332222... */ \
*(ptr++) = 0xEA; /* ...jmp dword 0x7788:0x33332222 */ \
const uint32 jmp32addr = (uint32) (ptr + 6); \
memcpy(ptr, &jmp32addr, 4); ptr += 4; \
memcpy(ptr, &GLoaderState->original_cs, 2); ptr += 2; \
\
/* USE32 */ \
*(ptr++) = 0x66; /* mov bx,ss... */ \
*(ptr++) = 0x8C; /* ...mov bx,ss */ \
*(ptr++) = 0xD3; /* ...mov bx,ss */ \
*(ptr++) = 0x66; /* shl ebx,byte 0x10... */ \
*(ptr++) = 0xC1; /* ...shl ebx,byte 0x10 */ \
*(ptr++) = 0xC1; /* shl ebx,byte 0x10... */ \
*(ptr++) = 0xE3; /* ...shl ebx,byte 0x10 */ \
*(ptr++) = 0x10; /* ...shl ebx,byte 0x10 */ \
*(ptr++) = 0x89; /* mov bx,sp... */ \
*(ptr++) = 0xE3; /* ...mov bx,sp */ \
*(ptr++) = 0x8C; /* mov ax,ss... */ \
*(ptr++) = 0x66; /* mov bx,cx... */ \
*(ptr++) = 0x89; /* ...mov bx,cx */ \
*(ptr++) = 0xCB; /* ...mov bx,cx */ \
*(ptr++) = 0x66; /* mov ax,ss... */ \
*(ptr++) = 0x8C; /* ...mov ax,ss */ \
*(ptr++) = 0xD0; /* ...mov ax,ss */ \
*(ptr++) = 0xC1; /* shr ax,byte 0x3... */ \
*(ptr++) = 0x66; /* shr ax,byte 0x3... */ \
*(ptr++) = 0xC1; /* ...shr ax,byte 0x3 */ \
*(ptr++) = 0xE8; /* ...shr ax,byte 0x3 */ \
*(ptr++) = 0x03; /* ...shr ax,byte 0x3 */ \
*(ptr++) = 0x66; /* shl eax,byte 0x10... */ \
*(ptr++) = 0xC1; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0xC1; /* shl eax,byte 0x10... */ \
*(ptr++) = 0xE0; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0x10; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0x89; /* mov ax,sp... */ \
*(ptr++) = 0xE0; /* ...mov ax,sp */ \
*(ptr++) = 0x66; /* jmp dword 0x7788:0x33332222... */ \
*(ptr++) = 0xEA; /* ...jmp dword 0x7788:0x33332222 */ \
const uint32 jmp32addr = (uint32) (ptr + 6); \
memcpy(ptr, &jmp32addr, 4); ptr += 4; \
memcpy(ptr, &GLoaderState->original_cs, 2); ptr += 2; \
\
/* USE32 */ \
*(ptr++) = 0x66; /* mov ax,cx... */ \
*(ptr++) = 0x89; /* ...mov ax,cx */ \
*(ptr++) = 0xC8; /* ...mov ax,cx */ \
*(ptr++) = 0x66; /* mov cx,0xabcd... */ \
*(ptr++) = 0xB9; /* ...mov cx,0xabcd */ \
memcpy(ptr, &GLoaderState->original_ss, 2); ptr += 2; \
Expand All @@ -159,14 +165,18 @@ RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling
*(ptr++) = 0x53; /* push ebx */ \
*(ptr++) = 0x1E; /* push ds */ \
*(ptr++) = 0x06; /* push es */ \
*(ptr++) = 0x66; /* mov cx,0x8888... */ \
*(ptr++) = 0xB9; /* ...mov cx,0x8888 */ \
memcpy(ptr, &GLoaderState->original_ds, 2); ptr += 2; \
if (GLoaderState->original_ss != GLoaderState->original_ds) { \
*(ptr++) = 0x66; /* mov cx,0x8888... */ \
*(ptr++) = 0xB9; /* ...mov cx,0x8888 */ \
memcpy(ptr, &GLoaderState->original_ds, 2); ptr += 2; \
} \
*(ptr++) = 0x8E; /* mov ds,ecx... */ \
*(ptr++) = 0xD9; /* ...mov ds,ecx */ \
*(ptr++) = 0x66; /* mov cx,0x9999... */ \
*(ptr++) = 0xB9; /* ...mov cx,0x9999 */ \
memcpy(ptr, &GLoaderState->original_es, 2); ptr += 2; \
if (GLoaderState->original_ds != GLoaderState->original_es) { \
*(ptr++) = 0x66; /* mov cx,0x9999... */ \
*(ptr++) = 0xB9; /* ...mov cx,0x9999 */ \
memcpy(ptr, &GLoaderState->original_es, 2); ptr += 2; \
} \
*(ptr++) = 0x8E; /* mov es,ecx... */ \
*(ptr++) = 0xC1; /* ...mov es,ecx */ \
*(ptr++) = 0x50; /* push eax */ \
Expand Down

0 comments on commit 44565f5

Please sign in to comment.