Brendan wrote:Hi,
While I don't agree with "Just use C" (partly because most C compilers can't/won't support "call far"); if you intend to use assembly then you should find an assembler that is capable of assembling. Any 80x86 assembler that can't handle an instruction that has been around since 8086 (like "call far") is not an assembler that is worth bothering with. Of course it's entirely possible that the assembler you're using isn't a steaming pile of camel puke, and that the reason your "call16" macro exists is because you have no idea how to use your assembler. In that case, learn to use your assembler...
Also note that if you use a "call far" instruction (which pushes a "return CS" and "return eIP" on the stack), then you have to return with a "return far" instruction (that returns to the CS:eIP" that is on the stack). If you use a normal "return near" then you'll end up returning to the wrong code segment with a corrupt stack.
If using the wrong type of "ret" isn't the problem, then the problem could be anything else (including your GDT, your "lgdt" instruction, your stack, your memory management, etc).
Cheers,
Brendan
Hi:
My assembler is masm 5.1,I don't define stack segment in GDT,must I define stack?
I change "ret" to "ret far" or "retf far",but the PC also restart.
There are my codes:
Code: Select all
;Jmp Macro
jump macro selector,offsetv
db 0eah
dw offsetv
dw selector
endm
;Call Macro
call16 macro selector,offsetv
db 09ah
dw offsetv
dw selector
endm
descriptor struc
limitl dw 0
basel dw 0
basem db 0
attributes dw 0
baseh db 0
descriptor ends
pdesc struc
limit dw 0
base dd 0
pdesc ends
.386P
;--------------------------------------------------------
dseg segment use16
gdt label byte
dummy descriptor <>
code descriptor <0ffffh,,,98h,>
code_sel =code-gdt
codes descriptor <0ffffh,,,98h,>
codes_sel =codes-gdt ;sub-program
gdtlen =$-gdt
;
vgdtr pdesc <gdtlen-1,>
;
dseg ends
;-------------------------------------------------------------
;subprogram
cseg1 segment use16
assume cs:cseg1
dspmsg:
ret far
cseg1 ends
;------------------------------------------
cseg segment use16
assume cs:cseg, ds:dseg
start:
mov ax,dseg
mov ds,ax
;
mov bx,16
mul bx
add ax,offset gdt
adc dx,0
mov word ptr vgdtr.base,ax
mov word ptr vgdtr.base+2,dx
;
mov ax,cs
mul bx
mov code.basel,ax
mov code.basem,dl
mov code.baseh,dh
;
mov ax,cseg1
mul bx
mov codes.basel,ax
mov codes.basem,dl
mov codes.baseh,dh
;
lgdt fword ptr vgdtr
;
cli
call ea20
;
mov eax,cr0
or eax,1
mov cr0,eax
;
jump <code_sel>,<offset virtual>
;
virtual:
call16 codes_sel,dspmsg ;call sub-program
;
mov eax,cr0
and eax,0fffffffeh
mov cr0,eax
;
jump <seg real>,<offset real>
;
real:
call da20
sti
mov ax,4c00h
int 21h
;
ea20 proc
push ax
in al,92h
or al,2
out 92h,al
pop ax
ret
ea20 endp
;
;
da20 proc
push ax
in al,92h
and al,0fdh ;0fdh=not 20h
out 92h,al
pop ax
ret
da20 endp
;
cseg ends
end start