NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: Roman on August 14, 2012, 06:41:03 AM
-
Hi, All!
Thanks for your help in the previous topics:)
I have a problem again:
I write code for leaving long mode, and i need make a far jump to compatibility mode.
In all examples, which i found, it write as
; fasm
jump_value:
dq jump_offset
dd jump_selector
; ....
jmp tbyte [jump_value]
but NASM not supported it.
I try replace tbyte to tword and nasm write: "error: mismatch in operand sizes"
How i can make this?
P.S. sorry for my English :)
-
I'm surprised your jump_selector is dd. I would have expected dw. I think selectors are 16 bits, even in long mode, no? I don't think it makes any difference.
I think just:
jmp far [jump_value]
will do it. I can't test this, but it looks like plausible opcodes. If Fasm emits something different, get back to us...
Best,
Frank
-
I'm surprised your jump_selector is dd. I would have expected dw.
Yes, of course, I confused :)
what you suggest does not work too.
Maybe I'm giving the wrong address to jump_offset...
-
Address is right, i check it
mov rax, some_addr
jmp rax
some_addr:
; print "Hello"
but code:
jmp far [jump_value]
jump_value:
dq some_addr
dw CODE_SELECTOR
don't work :(
-
I try simple code
; in long mode
jmp [jmp_v]
jmp_v:
dd ToLa(lbl)
lbl:
; some code
where ToLa() is macro for make linear address from offset
and it don't work
What I'm doing wrong?
-
Are you sure you need far jumps? Be careful with brackets
Example 1 (this one works fine):
[org 100h]
[section .text]
jmp Etiqueta
msg DB 'Hola, mundo!$'
Etiqueta:
MOV DX, msg
MOV AH, 9
INT 21h
MOV AX, 4c00h
INT 21h
Example 2 (this other one not):
[org 100h]
[section .text]
jmp [Etiqueta]
msg DB 'Hola, mundo!$'
Etiqueta:
MOV DX, msg
MOV AH, 9
INT 21h
MOV AX, 4c00h
INT 21h
Why Example 2 does not work?:
D:\Alfonso\AVCH>debug prueba2.com
-u
0D81:0100 FF261101 JMP [0111]
0D81:0104 48 DEC AX
0D81:0105 6F DB 6F
0D81:0106 6C DB 6C
0D81:0107 61 DB 61
0D81:0108 2C20 SUB AL,20
0D81:010A 6D DB 6D
0D81:010B 756E JNZ 017B
0D81:010D 64 DB 64
0D81:010E 6F DB 6F
0D81:010F 2124 AND [SI],SP
0D81:0111 BA0401 MOV DX,0104
0D81:0114 B409 MOV AH,09
0D81:0116 CD21 INT 21
0D81:0118 B8004C MOV AX,4C00
0D81:011B CD21 INT 21
0D81:011D 64 DB 64
0D81:011E 69 DB 69
0D81:011F 7265 JB 0186
-p
AX=0000 BX=0000 CX=001D DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=0D81 ES=0D81 SS=0D81 CS=0D81 IP=04BA NV UP EI PL NZ NA PO NC
0D81:04BA 68 DB 68
You have jumped to the value saved in [0111] = BA04h (we are working in 16 bits), and because of little endians: 04BAh.
If I'm not wrong you need far jumps for different segments (I need review it ;-)). An example that I did some time ago that works
http://www.abreojosensamblador.net/Productos/AOE/html/Codigos/Cap12/RelojCN1.asm (http://www.abreojosensamblador.net/Productos/AOE/html/Codigos/Cap12/RelojCN1.asm)
JMP FAR [CS:OldInt8h]
I needed use it in such a way because I handled a system interruption Int08, surely in other segment.
Cheers
-
jmp far [jump_value]
jump_value:
dq some_addr
dw CODE_SELECTOR
don't work :(
The biggest problem with that code is architectural. The original AMD64 instruction set did not support/encode JMP FAR MEM16:64, therefore it is not universal and such code should be avoided.
The following code is three different ways that should put the processor into compatibility mode. It assumes that COMPAT_SEL is a valid (protected mode code, IIRC) GDT selector. Operative word being should, as my working knowledge is a bit rusty and some minor changes may be needed.
Also note that o64 retf should probably be its own instruction called retfq, akin to iretq. It was probably overlooked due to imprecise instruction set documentation. However, %define retfq o64 retf should suffice in the interim.
[BITS 64]
%define retfq o64 retf
%define COMPAT_SEL 8 ;Compatibility Mode GDT Selector (change as needed)
;Indirect 32-bit Far Jump Version
jmp far DWORD[ptr] ;JMP FAR MEM16:32 (works on all x86-64 processors)
ptr:
DD COMPAT_START ;EIP of Compatibility Mode Entrypoint
DW COMPAT_SEL ;Compatibility Mode GDT Selector
;RETFQ Version
push COMPAT_SEL ;Push Compatibility Mode GDT Selector
push COMPAT_START ;Push RIP of Compatibility Mode Entrypoint
retfq ;64-bit RETF
;IRETQ Version
mov rbx,rsp ;Current Stack Pointer
mov ax,ss ;Segment Selector
movzx eax,ax ;Zero Extend top 48-bits of RAX
push rax ;Push QWORD Aligned SS
push rbx ;Push Desired Stack Pointer
pushfq ;Push RFLAGS
push COMPAT_SEL ;Push Compatibility Mode GDT Selector
push COMPAT_START ;Push RIP of Compatibility Mode Entrypoint
iretq ;Return from Long Mode Interrupt
[BITS 32]
;Compatibility Mode Entrypoint
COMPAT_START:
jmp $
HtH.
-
avcaballero, thanks, but your examples for 16 bit mode.
Keith Kanios, Thank you very much!
I have some questions:
Can i use protected mode code selector instead of COMPAT_SEL?
Do I need to first calculate the linear address of the label COMPAT_START or i should use COMPAT_START as is?
-
;RETFQ Version
push COMPAT_SEL ;Push Compatibility Mode GDT Selector
push COMPAT_START ;Push RIP of Compatibility Mode Entrypoint
retfq ;64-bit RETF
It's work for me :)
and i have answers for my questions
Can i use protected mode code selector instead of COMPAT_SEL?
Yes
Do I need to first calculate the linear address of the label COMPAT_START or i should use COMPAT_START as is?
]
use label as is
-
;RETFQ Version
push COMPAT_SEL ;Push Compatibility Mode GDT Selector
push COMPAT_START ;Push RIP of Compatibility Mode Entrypoint
retfq ;64-bit RETF
It's work for me :)
Good. Thanks for letting us know that said method does work.
I think most OS code will use the IRETQ method since the interrupt handler is already there and will also work as-is for returning to a compatibility mode process.
and i have answers for my questions
Can i use protected mode code selector instead of COMPAT_SEL?
Yes
Yep. As alluded to in my initial reply -- (protected mode code, IIRC) -- a compatibility mode selector is the same as you would use for 32-bit protected mode.
Do I need to first calculate the linear address of the label COMPAT_START or i should use COMPAT_START as is?
]
use label as is
Yes, as long as the reference is absolute, which it should be in the above code context.