Move the 16-bit bridge heavy-lifting to the 32-bit code segment.

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.
This commit is contained in:
Ryan C. Gordon committed 2018-01-04 00:15:31 -05:00
1 parent b72ccd6e5a
commit 44565f529b
1 file changed
+43 -33
+43 -33
View File
@@ -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.
@@ -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!).
@@ -120,25 +121,8 @@ 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++) = 0xD3; /* ...mov bx,ss */ \
*(ptr++) = 0x66; /* 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++) = 0xD0; /* ...mov ax,ss */ \
*(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++) = 0xE0; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0x10; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0x89; /* mov ax,sp... */ \
*(ptr++) = 0xE0; /* ...mov ax,sp */ \
*(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); \
@@ -146,6 +130,28 @@ RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling
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++) = 0xC1; /* shl ebx,byte 0x10... */ \
*(ptr++) = 0xE3; /* ...shl ebx,byte 0x10 */ \
*(ptr++) = 0x10; /* ...shl ebx,byte 0x10 */ \
*(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++) = 0x66; /* shr ax,byte 0x3... */ \
*(ptr++) = 0xC1; /* ...shr ax,byte 0x3 */ \
*(ptr++) = 0xE8; /* ...shr ax,byte 0x3 */ \
*(ptr++) = 0x03; /* ...shr ax,byte 0x3 */ \
*(ptr++) = 0xC1; /* shl eax,byte 0x10... */ \
*(ptr++) = 0xE0; /* ...shl eax,byte 0x10 */ \
*(ptr++) = 0x10; /* ...shl eax,byte 0x10 */ \
*(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; \
@@ -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 */ \